<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[245638] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/245638">245638</a></dd>
<dt>Author</dt> <dd>jiewen_tan@apple.com</dd>
<dt>Date</dt> <dd>2019-05-22 12:27:49 -0700 (Wed, 22 May 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>[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:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestshttpwptwebauthnpublickeycredentialcreatesuccesshidhttpsexpectedtxt">trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttpwptwebauthnpublickeycredentialcreatesuccesshidhttpshtml">trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https.html</a></li>
<li><a href="#trunkLayoutTestshttpwptwebauthnpublickeycredentialcreatesuccesslocalhttpsexpectedtxt">trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttpwptwebauthnpublickeycredentialcreatesuccesslocalhttpshtml">trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https.html</a></li>
<li><a href="#trunkLayoutTestshttpwptwebauthnpublickeycredentialcreatesuccessu2fhttpsexpectedtxt">trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-u2f.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttpwptwebauthnpublickeycredentialcreatesuccessu2fhttpshtml">trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-u2f.https.html</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreDerivedSourcesinputxcfilelist">trunk/Source/WebCore/DerivedSources-input.xcfilelist</a></li>
<li><a href="#trunkSourceWebCoreDerivedSourcesoutputxcfilelist">trunk/Source/WebCore/DerivedSources-output.xcfilelist</a></li>
<li><a href="#trunkSourceWebCoreDerivedSourcesmake">trunk/Source/WebCore/DerivedSources.make</a></li>
<li><a href="#trunkSourceWebCoreHeaderscmake">trunk/Source/WebCore/Headers.cmake</a></li>
<li><a href="#trunkSourceWebCoreModuleswebauthnPublicKeyCredentialCreationOptionsh">trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.h</a></li>
<li><a href="#trunkSourceWebCoreModuleswebauthnPublicKeyCredentialCreationOptionsidl">trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.idl</a></li>
<li><a href="#trunkSourceWebCoreModuleswebauthnWebAuthenticationConstantsh">trunk/Source/WebCore/Modules/webauthn/WebAuthenticationConstants.h</a></li>
<li><a href="#trunkSourceWebCoreModuleswebauthnWebAuthenticationUtilscpp">trunk/Source/WebCore/Modules/webauthn/WebAuthenticationUtils.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebauthnWebAuthenticationUtilsh">trunk/Source/WebCore/Modules/webauthn/WebAuthenticationUtils.h</a></li>
<li><a href="#trunkSourceWebCoreModuleswebauthnfidoDeviceResponseConvertercpp">trunk/Source/WebCore/Modules/webauthn/fido/DeviceResponseConverter.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebauthnfidoDeviceResponseConverterh">trunk/Source/WebCore/Modules/webauthn/fido/DeviceResponseConverter.h</a></li>
<li><a href="#trunkSourceWebCoreModuleswebauthnfidoFidoConstantsh">trunk/Source/WebCore/Modules/webauthn/fido/FidoConstants.h</a></li>
<li><a href="#trunkSourceWebCoreModuleswebauthnfidoU2fResponseConvertercpp">trunk/Source/WebCore/Modules/webauthn/fido/U2fResponseConverter.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebauthnfidoU2fResponseConverterh">trunk/Source/WebCore/Modules/webauthn/fido/U2fResponseConverter.h</a></li>
<li><a href="#trunkSourceWebCoreSourcestxt">trunk/Source/WebCore/Sources.txt</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebAuthenticationCocoaLocalAuthenticatormm">trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebAuthenticationfidoCtapHidAuthenticatorcpp">trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebAuthenticationfidoU2fHidAuthenticatorcpp">trunk/Source/WebKit/UIProcess/WebAuthentication/fido/U2fHidAuthenticator.cpp</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebCoreCtapRequestTestcpp">trunk/Tools/TestWebKitAPI/Tests/WebCore/CtapRequestTest.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreModuleswebauthnAttestationConveyancePreferenceh">trunk/Source/WebCore/Modules/webauthn/AttestationConveyancePreference.h</a></li>
<li><a href="#trunkSourceWebCoreModuleswebauthnAttestationConveyancePreferenceidl">trunk/Source/WebCore/Modules/webauthn/AttestationConveyancePreference.idl</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog      2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/LayoutTests/ChangeLog 2019-05-22 19:27:49 UTC (rev 245638)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2019-05-22  Jiewen Tan  <jiewen_tan@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:
+
</ins><span class="cx"> 2019-05-22  Jer Noble  <jer.noble@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Hide MediaCapabilities.encodingInfo() when the platform does not support it.
</span></span></pre></div>
<a id="trunkLayoutTestshttpwptwebauthnpublickeycredentialcreatesuccesshidhttpsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -6,4 +6,7 @@
</span><span class="cx"> PASS PublicKeyCredential's [[create]] with userVerification { 'discouraged' } in a mock local authenticator. 
</span><span class="cx"> PASS PublicKeyCredential's [[create]] with mixed options in a mock local authenticator. 
</span><span class="cx"> PASS PublicKeyCredential's [[create]] with two consecutive requests. 
</span><ins>+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. 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestshttpwptwebauthnpublickeycredentialcreatesuccesshidhttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https.html (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -9,7 +9,7 @@
</span><span class="cx">     if (window.testRunner)
</span><span class="cx">         testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", payloadBase64: [testCreationMessageBase64] } });
</span><span class="cx"> 
</span><del>-    function checkResult(credential)
</del><ins>+    function checkResult(credential, isNoneAttestation = true)
</ins><span class="cx">     {
</span><span class="cx">         // Check response
</span><span class="cx">         assert_array_equals(Base64URL.parse(credential.id), Base64URL.parse(testHidCredentialIdBase64));
</span><span class="lines">@@ -20,18 +20,28 @@
</span><span class="cx"> 
</span><span class="cx">         // Check attestation
</span><span class="cx">         const attestationObject = CBOR.decode(credential.response.attestationObject);
</span><del>-        assert_equals(attestationObject.fmt, "packed");
</del><ins>+        if (isNoneAttestation)
+            assert_equals(attestationObject.fmt, "none");
+        else
+            assert_equals(attestationObject.fmt, "packed");
</ins><span class="cx">         // Check authData
</span><span class="cx">         const authData = decodeAuthData(attestationObject.authData);
</span><span class="cx">         assert_equals(bytesToHexString(authData.rpIdHash), "46cc7fb9679d55b2db9092e1c8d9e5e1d02b7580f0b4812c770962e1e48f5ad8");
</span><span class="cx">         assert_equals(authData.flags, 65);
</span><span class="cx">         assert_equals(authData.counter, 78);
</span><del>-        assert_equals(bytesToHexString(authData.aaguid), "f8a011f38c0a4d15800617111f9edc7d");
</del><ins>+        if (isNoneAttestation)
+            assert_equals(bytesToHexString(authData.aaguid), "00000000000000000000000000000000");
+        else
+            assert_equals(bytesToHexString(authData.aaguid), "f8a011f38c0a4d15800617111f9edc7d");
</ins><span class="cx">         assert_array_equals(authData.credentialID, Base64URL.parse(testHidCredentialIdBase64));
</span><span class="cx">         // Check packed attestation
</span><del>-        assert_equals(attestationObject.attStmt.alg, -7);
</del><span class="cx">         assert_true(checkPublicKey(authData.publicKey));
</span><del>-        assert_equals(attestationObject.attStmt.x5c.length, 1);
</del><ins>+        if (isNoneAttestation)
+            assert_object_equals(attestationObject.attStmt, { });
+        else {
+            assert_equals(attestationObject.attStmt.alg, -7);
+            assert_equals(attestationObject.attStmt.x5c.length, 1);
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     promise_test(t => {
</span><span class="lines">@@ -193,4 +203,73 @@
</span><span class="cx">             checkResult(credential);
</span><span class="cx">         });
</span><span class="cx">     }, "PublicKeyCredential's [[create]] with two consecutive requests.");
</span><ins>+
+    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.");
</ins><span class="cx"> </script>
</span></span></pre></div>
<a id="trunkLayoutTestshttpwptwebauthnpublickeycredentialcreatesuccesslocalhttpsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https-expected.txt (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -2,4 +2,7 @@
</span><span class="cx"> PASS PublicKeyCredential's [[create]] with minimum options in a mock local authenticator. 
</span><span class="cx"> PASS PublicKeyCredential's [[create]] with authenticatorSelection { 'platform' } in a mock local authenticator. 
</span><span class="cx"> PASS PublicKeyCredential's [[create]] with matched exclude credential ids but not transports in a mock local authenticator. 
</span><ins>+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. 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestshttpwptwebauthnpublickeycredentialcreatesuccesslocalhttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https.html (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -17,7 +17,7 @@
</span><span class="cx">             }
</span><span class="cx">         });
</span><span class="cx"> 
</span><del>-    function checkResult(credential)
</del><ins>+    function checkResult(credential, isNoneAttestation = true)
</ins><span class="cx">     {
</span><span class="cx">         // Check keychain
</span><span class="cx">         if (window.testRunner) {
</span><span class="lines">@@ -34,7 +34,10 @@
</span><span class="cx"> 
</span><span class="cx">         // Check attestation
</span><span class="cx">         const attestationObject = CBOR.decode(credential.response.attestationObject);
</span><del>-        assert_equals(attestationObject.fmt, "Apple");
</del><ins>+        if (isNoneAttestation)
+            assert_equals(attestationObject.fmt, "none");
+        else
+            assert_equals(attestationObject.fmt, "Apple");
</ins><span class="cx">         // Check authData
</span><span class="cx">         const authData = decodeAuthData(attestationObject.authData);
</span><span class="cx">         assert_equals(bytesToHexString(authData.rpIdHash), "49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763");
</span><span class="lines">@@ -43,22 +46,32 @@
</span><span class="cx">         assert_equals(bytesToHexString(authData.aaguid), "00000000000000000000000000000000");
</span><span class="cx">         assert_array_equals(authData.credentialID, Base64URL.parse(testCredentialIdBase64));
</span><span class="cx">         // Check self attestation
</span><del>-        assert_equals(attestationObject.attStmt.alg, -7);
</del><span class="cx">         assert_true(checkPublicKey(authData.publicKey));
</span><del>-        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));
</del><ins>+        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));
</ins><span class="cx"> 
</span><del>-        // 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);
</del><ins>+            // 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);
+                });
</ins><span class="cx">             });
</span><del>-        });
</del><ins>+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     promise_test(t => {
</span><span class="lines">@@ -131,4 +144,70 @@
</span><span class="cx">             checkResult(credential);
</span><span class="cx">         });
</span><span class="cx">     }, "PublicKeyCredential's [[create]] with matched exclude credential ids but not transports in a mock local authenticator.");
</span><ins>+
+    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.");
</ins><span class="cx"> </script>
</span></span></pre></div>
<a id="trunkLayoutTestshttpwptwebauthnpublickeycredentialcreatesuccessu2fhttpsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-u2f.https-expected.txt (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -3,4 +3,7 @@
</span><span class="cx"> PASS PublicKeyCredential's [[create]] with excludeCredentials in a mock u2f authenticator. 
</span><span class="cx"> PASS PublicKeyCredential's [[create]] with excludeCredentials in a mock u2f authenticator. 2 
</span><span class="cx"> PASS PublicKeyCredential's [[create]] with test of user presence in a mock u2f authenticator. 
</span><ins>+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. 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestshttpwptwebauthnpublickeycredentialcreatesuccessu2fhttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-u2f.https.html (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -5,7 +5,7 @@
</span><span class="cx"> <script src="./resources/util.js"></script>
</span><span class="cx"> <script src="./resources/cbor.js"></script>
</span><span class="cx"> <script>
</span><del>-    function checkResult(credential)
</del><ins>+    function checkResult(credential, isNoneAttestation = true)
</ins><span class="cx">     {
</span><span class="cx">         // Check response
</span><span class="cx">         assert_array_equals(Base64URL.parse(credential.id), Base64URL.parse(testU2fCredentialIdBase64));
</span><span class="lines">@@ -16,7 +16,10 @@
</span><span class="cx"> 
</span><span class="cx">         // Check attestation
</span><span class="cx">         const attestationObject = CBOR.decode(credential.response.attestationObject);
</span><del>-        assert_equals(attestationObject.fmt, "fido-u2f");
</del><ins>+        if (isNoneAttestation)
+            assert_equals(attestationObject.fmt, "none");
+        else
+            assert_equals(attestationObject.fmt, "fido-u2f");
</ins><span class="cx">         // Check authData
</span><span class="cx">         const authData = decodeAuthData(attestationObject.authData);
</span><span class="cx">         assert_equals(bytesToHexString(authData.rpIdHash), "49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763");
</span><span class="lines">@@ -26,7 +29,10 @@
</span><span class="cx">         assert_array_equals(authData.credentialID, Base64URL.parse(testU2fCredentialIdBase64));
</span><span class="cx">         // Check fido-u2f attestation
</span><span class="cx">         assert_true(checkPublicKey(authData.publicKey));
</span><del>-        assert_equals(attestationObject.attStmt.x5c.length, 1);
</del><ins>+        if (isNoneAttestation)
+            assert_object_equals(attestationObject.attStmt, { });
+        else
+            assert_equals(attestationObject.attStmt.x5c.length, 1);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     promise_test(t => {
</span><span class="lines">@@ -126,4 +132,79 @@
</span><span class="cx">             checkResult(credential);
</span><span class="cx">         });
</span><span class="cx">     }, "PublicKeyCredential's [[create]] with test of user presence in a mock u2f authenticator.");
</span><ins>+
+    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.");
</ins><span class="cx"> </script>
</span></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -441,6 +441,7 @@
</span><span class="cx">     Modules/webaudio/ScriptProcessorNode.idl
</span><span class="cx">     Modules/webaudio/WaveShaperNode.idl
</span><span class="cx"> 
</span><ins>+    Modules/webauthn/AttestationConveyancePreference.idl
</ins><span class="cx">     Modules/webauthn/AuthenticationExtensionsClientInputs.idl
</span><span class="cx">     Modules/webauthn/AuthenticatorAssertionResponse.idl
</span><span class="cx">     Modules/webauthn/AuthenticatorAttestationResponse.idl
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,3 +1,46 @@
</span><ins>+2019-05-22  Jiewen Tan  <jiewen_tan@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:
+
</ins><span class="cx"> 2019-05-22  Zalan Bujtas  <zalan@apple.com>
</span><span class="cx"> 
</span><span class="cx">         [Paste] Add support for preferred presentation size when pasting an image
</span></span></pre></div>
<a id="trunkSourceWebCoreDerivedSourcesinputxcfilelist"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/DerivedSources-input.xcfilelist (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -294,6 +294,7 @@
</span><span class="cx"> $(PROJECT_DIR)/Modules/webaudio/PeriodicWave.idl
</span><span class="cx"> $(PROJECT_DIR)/Modules/webaudio/ScriptProcessorNode.idl
</span><span class="cx"> $(PROJECT_DIR)/Modules/webaudio/WaveShaperNode.idl
</span><ins>+$(PROJECT_DIR)/Modules/webauthn/AttestationConveyancePreference.idl
</ins><span class="cx"> $(PROJECT_DIR)/Modules/webauthn/AuthenticationExtensionsClientInputs.idl
</span><span class="cx"> $(PROJECT_DIR)/Modules/webauthn/AuthenticatorAssertionResponse.idl
</span><span class="cx"> $(PROJECT_DIR)/Modules/webauthn/AuthenticatorAttestationResponse.idl
</span></span></pre></div>
<a id="trunkSourceWebCoreDerivedSourcesoutputxcfilelist"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/DerivedSources-output.xcfilelist (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -124,6 +124,8 @@
</span><span class="cx"> $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSApplePayValidateMerchantEvent.h
</span><span class="cx"> $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAriaAttributes.cpp
</span><span class="cx"> $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAriaAttributes.h
</span><ins>+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAttestationConveyancePreference.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAttestationConveyancePreference.h
</ins><span class="cx"> $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAttr.cpp
</span><span class="cx"> $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAttr.h
</span><span class="cx"> $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAudioBuffer.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreDerivedSourcesmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/DerivedSources.make (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -351,6 +351,7 @@
</span><span class="cx">     $(WebCore)/Modules/webaudio/PeriodicWave.idl \
</span><span class="cx">     $(WebCore)/Modules/webaudio/ScriptProcessorNode.idl \
</span><span class="cx">     $(WebCore)/Modules/webaudio/WaveShaperNode.idl \
</span><ins>+    $(WebCore)/Modules/webauthn/AttestationConveyancePreference.idl \
</ins><span class="cx">     $(WebCore)/Modules/webauthn/AuthenticationExtensionsClientInputs.idl \
</span><span class="cx">     $(WebCore)/Modules/webauthn/AuthenticatorAssertionResponse.idl \
</span><span class="cx">     $(WebCore)/Modules/webauthn/AuthenticatorAttestationResponse.idl \
</span></span></pre></div>
<a id="trunkSourceWebCoreHeaderscmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Headers.cmake (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -112,6 +112,7 @@
</span><span class="cx">     Modules/streams/ReadableStreamSink.h
</span><span class="cx">     Modules/streams/ReadableStreamSource.h
</span><span class="cx"> 
</span><ins>+    Modules/webauthn/AttestationConveyancePreference.h
</ins><span class="cx">     Modules/webauthn/AuthenticationExtensionsClientInputs.h
</span><span class="cx">     Modules/webauthn/AuthenticatorCoordinator.h
</span><span class="cx">     Modules/webauthn/AuthenticatorCoordinatorClient.h
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebauthnAttestationConveyancePreferencehfromrev245637trunkSourceWebCoreModuleswebauthnWebAuthenticationUtilsh"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/Modules/webauthn/AttestationConveyancePreference.h (from rev 245637, trunk/Source/WebCore/Modules/webauthn/WebAuthenticationUtils.h) (0 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,55 @@
</span><ins>+/*
+ * 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)
</ins></span></pre></div>
<a id="trunkSourceWebCoreModuleswebauthnAttestationConveyancePreferenceidlfromrev245637trunkSourceWebCoreModuleswebauthnWebAuthenticationUtilsh"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/Modules/webauthn/AttestationConveyancePreference.idl (from rev 245637, trunk/Source/WebCore/Modules/webauthn/WebAuthenticationUtils.h) (0 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,32 @@
</span><ins>+/*
+ * 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"
+};
</ins></span></pre></div>
<a id="trunkSourceWebCoreModuleswebauthnPublicKeyCredentialCreationOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.h (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEB_AUTHN)
</span><span class="cx"> 
</span><ins>+#include "AttestationConveyancePreference.h"
</ins><span class="cx"> #include "AuthenticationExtensionsClientInputs.h"
</span><span class="cx"> #include "BufferSource.h"
</span><span class="cx"> #include "PublicKeyCredentialDescriptor.h"
</span><span class="lines">@@ -84,6 +85,7 @@
</span><span class="cx">     Optional<unsigned> timeout;
</span><span class="cx">     Vector<PublicKeyCredentialDescriptor> excludeCredentials;
</span><span class="cx">     Optional<AuthenticatorSelectionCriteria> authenticatorSelection;
</span><ins>+    AttestationConveyancePreference attestation;
</ins><span class="cx">     Optional<AuthenticationExtensionsClientInputs> extensions; // A place holder, but never used.
</span><span class="cx"> 
</span><span class="cx">     template<class Encoder> void encode(Encoder&) const;
</span><span class="lines">@@ -142,7 +144,7 @@
</span><span class="cx">     encoder << rp.id << rp.name << rp.icon;
</span><span class="cx">     encoder << static_cast<uint64_t>(user.id.length());
</span><span class="cx">     encoder.encodeFixedLengthData(user.id.data(), user.id.length(), 1);
</span><del>-    encoder << user.displayName << user.name << user.icon << pubKeyCredParams << timeout << excludeCredentials << authenticatorSelection;
</del><ins>+    encoder << user.displayName << user.name << user.icon << pubKeyCredParams << timeout << excludeCredentials << authenticatorSelection << attestation;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template<class Decoder>
</span><span class="lines">@@ -181,6 +183,12 @@
</span><span class="cx">         return WTF::nullopt;
</span><span class="cx">     result.authenticatorSelection = WTFMove(*authenticatorSelection);
</span><span class="cx"> 
</span><ins>+    Optional<AttestationConveyancePreference> attestation;
+    decoder >> attestation;
+    if (!attestation)
+        return WTF::nullopt;
+    result.attestation = WTFMove(*attestation);
+
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebauthnPublicKeyCredentialCreationOptionsidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.idl (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -37,8 +37,7 @@
</span><span class="cx">     unsigned long timeout;
</span><span class="cx">     sequence<PublicKeyCredentialDescriptor> excludeCredentials = [];
</span><span class="cx">     AuthenticatorSelectionCriteria authenticatorSelection;
</span><del>-    // Always "direct" for us.
-    // AttestationConveyancePreference attestation = "none";
</del><ins>+    AttestationConveyancePreference attestation = "none";
</ins><span class="cx">     AuthenticationExtensionsClientInputs extensions;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebauthnWebAuthenticationConstantsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webauthn/WebAuthenticationConstants.h (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -67,4 +67,7 @@
</span><span class="cx"> // Per Section 2.3.5 of http://www.secg.org/sec1-v2.pdf
</span><span class="cx"> const size_t ES256FieldElementLength = 32;
</span><span class="cx"> 
</span><ins>+// https://www.w3.org/TR/webauthn/#none-attestation
+const char noneAttestationValue[] = "none";
+
</ins><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebauthnWebAuthenticationUtilscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webauthn/WebAuthenticationUtils.cpp (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -110,9 +110,20 @@
</span><span class="cx">     return authData;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Vector<uint8_t> buildAttestationObject(Vector<uint8_t>&& authData, String&& format, cbor::CBORValue::MapValue&& statementMap)
</del><ins>+Vector<uint8_t> buildAttestationObject(Vector<uint8_t>&& authData, String&& format, cbor::CBORValue::MapValue&& statementMap, const AttestationConveyancePreference& attestation)
</ins><span class="cx"> {
</span><span class="cx">     cbor::CBORValue::MapValue attestationObjectMap;
</span><ins>+    // 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();
+    }
</ins><span class="cx">     attestationObjectMap[cbor::CBORValue("authData")] = cbor::CBORValue(WTFMove(authData));
</span><span class="cx">     attestationObjectMap[cbor::CBORValue("fmt")] = cbor::CBORValue(WTFMove(format));
</span><span class="cx">     attestationObjectMap[cbor::CBORValue("attStmt")] = cbor::CBORValue(WTFMove(statementMap));
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebauthnWebAuthenticationUtilsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webauthn/WebAuthenticationUtils.h (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEB_AUTHN)
</span><span class="cx"> 
</span><ins>+#include "AttestationConveyancePreference.h"
</ins><span class="cx"> #include "CBORValue.h"
</span><span class="cx"> #include <wtf/Forward.h>
</span><span class="cx"> 
</span><span class="lines">@@ -46,7 +47,7 @@
</span><span class="cx"> WEBCORE_EXPORT Vector<uint8_t> buildAuthData(const String& rpId, const uint8_t flags, const uint32_t counter, const Vector<uint8_t>& optionalAttestedCredentialData);
</span><span class="cx"> 
</span><span class="cx"> // https://www.w3.org/TR/webauthn/#attestation-object
</span><del>-WEBCORE_EXPORT Vector<uint8_t> buildAttestationObject(Vector<uint8_t>&& authData, String&& format, cbor::CBORValue::MapValue&& statementMap);
</del><ins>+WEBCORE_EXPORT Vector<uint8_t> buildAttestationObject(Vector<uint8_t>&& authData, String&& format, cbor::CBORValue::MapValue&& statementMap, const AttestationConveyancePreference&);
</ins><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebauthnfidoDeviceResponseConvertercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webauthn/fido/DeviceResponseConverter.cpp (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> #include "CBORReader.h"
</span><span class="cx"> #include "CBORWriter.h"
</span><span class="cx"> #include "WebAuthenticationConstants.h"
</span><ins>+#include "WebAuthenticationUtils.h"
</ins><span class="cx"> #include <wtf/StdSet.h>
</span><span class="cx"> #include <wtf/Vector.h>
</span><span class="cx"> 
</span><span class="lines">@@ -84,7 +85,7 @@
</span><span class="cx"> 
</span><span class="cx"> // Decodes byte array response from authenticator to CBOR value object and
</span><span class="cx"> // checks for correct encoding format.
</span><del>-Optional<PublicKeyCredentialData> readCTAPMakeCredentialResponse(const Vector<uint8_t>& inBuffer)
</del><ins>+Optional<PublicKeyCredentialData> readCTAPMakeCredentialResponse(const Vector<uint8_t>& inBuffer, const WebCore::AttestationConveyancePreference& attestation)
</ins><span class="cx"> {
</span><span class="cx">     if (inBuffer.size() <= kResponseCodeLength)
</span><span class="cx">         return WTF::nullopt;
</span><span class="lines">@@ -115,11 +116,19 @@
</span><span class="cx">         return WTF::nullopt;
</span><span class="cx">     auto attStmt = it->second.clone();
</span><span class="cx"> 
</span><del>-    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)));
</del><ins>+    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)));
+    }
</ins><span class="cx"> 
</span><span class="cx">     return PublicKeyCredentialData { ArrayBuffer::create(credentialId.data(), credentialId.size()), true, nullptr, ArrayBuffer::create(attestationObject.value().data(), attestationObject.value().size()), nullptr, nullptr, nullptr, WTF::nullopt };
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebauthnfidoDeviceResponseConverterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webauthn/fido/DeviceResponseConverter.h (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEB_AUTHN)
</span><span class="cx"> 
</span><ins>+#include "AttestationConveyancePreference.h"
</ins><span class="cx"> #include "AuthenticatorGetInfoResponse.h"
</span><span class="cx"> #include "FidoConstants.h"
</span><span class="cx"> #include "PublicKeyCredentialData.h"
</span><span class="lines">@@ -48,7 +49,7 @@
</span><span class="cx"> // and converts response to AuthenticatorMakeCredentialResponse object with
</span><span class="cx"> // CBOR map keys that conform to format of attestation object defined by the
</span><span class="cx"> // WebAuthN spec : https://w3c.github.io/webauthn/#fig-attStructs
</span><del>-WEBCORE_EXPORT Optional<WebCore::PublicKeyCredentialData> readCTAPMakeCredentialResponse(const Vector<uint8_t>&);
</del><ins>+WEBCORE_EXPORT Optional<WebCore::PublicKeyCredentialData> readCTAPMakeCredentialResponse(const Vector<uint8_t>&, const WebCore::AttestationConveyancePreference& attestation = WebCore::AttestationConveyancePreference::Direct);
</ins><span class="cx"> 
</span><span class="cx"> // De-serializes CBOR encoded response to AuthenticatorGetAssertion /
</span><span class="cx"> // AuthenticatorGetNextAssertion request to AuthenticatorGetAssertionResponse
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebauthnfidoFidoConstantsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webauthn/fido/FidoConstants.h (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -207,7 +207,6 @@
</span><span class="cx"> const char kFormatKey[] = "fmt";
</span><span class="cx"> const char kAttestationStatementKey[] = "attStmt";
</span><span class="cx"> const char kAuthDataKey[] = "authData";
</span><del>-const char kNoneAttestationValue[] = "none";
</del><span class="cx"> 
</span><span class="cx"> // String representation of public key credential enum.
</span><span class="cx"> // https://w3c.github.io/webauthn/#credentialType
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebauthnfidoU2fResponseConvertercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webauthn/fido/U2fResponseConverter.cpp (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -147,7 +147,7 @@
</span><span class="cx"> 
</span><span class="cx"> } // namespace
</span><span class="cx"> 
</span><del>-Optional<PublicKeyCredentialData> readU2fRegisterResponse(const String& rpId, const Vector<uint8_t>& u2fData)
</del><ins>+Optional<PublicKeyCredentialData> readU2fRegisterResponse(const String& rpId, const Vector<uint8_t>& u2fData, const AttestationConveyancePreference& attestation)
</ins><span class="cx"> {
</span><span class="cx">     auto publicKey = extractECPublicKeyFromU2fRegistrationResponse(u2fData);
</span><span class="cx">     if (publicKey.isEmpty())
</span><span class="lines">@@ -168,7 +168,7 @@
</span><span class="cx">     if (fidoAttestationStatement.empty())
</span><span class="cx">         return WTF::nullopt;
</span><span class="cx"> 
</span><del>-    auto attestationObject = buildAttestationObject(WTFMove(authData), "fido-u2f", WTFMove(fidoAttestationStatement));
</del><ins>+    auto attestationObject = buildAttestationObject(WTFMove(authData), "fido-u2f", WTFMove(fidoAttestationStatement), attestation);
</ins><span class="cx"> 
</span><span class="cx">     return PublicKeyCredentialData { ArrayBuffer::create(credentialId.data(), credentialId.size()), true, nullptr, ArrayBuffer::create(attestationObject.data(), attestationObject.size()), nullptr, nullptr, nullptr, WTF::nullopt };
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebauthnfidoU2fResponseConverterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webauthn/fido/U2fResponseConverter.h (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEB_AUTHN)
</span><span class="cx"> 
</span><ins>+#include "AttestationConveyancePreference.h"
</ins><span class="cx"> #include "PublicKeyCredentialData.h"
</span><span class="cx"> #include <wtf/Forward.h>
</span><span class="cx"> 
</span><span class="lines">@@ -38,7 +39,7 @@
</span><span class="cx"> 
</span><span class="cx"> // Converts a U2F register response to WebAuthN makeCredential response.
</span><span class="cx"> // https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#u2f-authenticatorMakeCredential-interoperability
</span><del>-WEBCORE_EXPORT Optional<WebCore::PublicKeyCredentialData> readU2fRegisterResponse(const String& rpId, const Vector<uint8_t>& u2fData);
</del><ins>+WEBCORE_EXPORT Optional<WebCore::PublicKeyCredentialData> readU2fRegisterResponse(const String& rpId, const Vector<uint8_t>& u2fData, const WebCore::AttestationConveyancePreference& attestation = WebCore::AttestationConveyancePreference::Direct);
</ins><span class="cx"> 
</span><span class="cx"> // Converts a U2F authentication response to WebAuthN getAssertion response.
</span><span class="cx"> // https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#u2f-authenticatorGetAssertion-interoperability
</span></span></pre></div>
<a id="trunkSourceWebCoreSourcestxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Sources.txt (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -2518,6 +2518,7 @@
</span><span class="cx"> JSAudioNode.cpp
</span><span class="cx"> JSAudioParam.cpp
</span><span class="cx"> JSAudioProcessingEvent.cpp
</span><ins>+JSAttestationConveyancePreference.cpp
</ins><span class="cx"> JSAuthenticationExtensionsClientInputs.cpp
</span><span class="cx"> JSAuthenticatorAssertionResponse.cpp
</span><span class="cx"> JSAuthenticatorAttestationResponse.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1810,6 +1810,9 @@
</span><span class="cx">          57C7A68C1E56967500C67D71 /* BasicCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 57C7A68B1E56967500C67D71 /* BasicCredential.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          57C7A69F1E57917800C67D71 /* JSBasicCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 57C7A69D1E57910D00C67D71 /* JSBasicCredential.h */; };
</span><span class="cx">          57D0018D1DD5413200ED19D9 /* JSCryptoKeyUsage.h in Headers */ = {isa = PBXBuildFile; fileRef = 57D0018C1DD5413200ED19D9 /* JSCryptoKeyUsage.h */; };
</span><ins>+               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 */; };
</ins><span class="cx">           57D8462E1FEAF69900CA3682 /* PublicKeyCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 57D8462B1FEAF68F00CA3682 /* PublicKeyCredential.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          57D846351FEAFCD300CA3682 /* JSPublicKeyCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 57D846301FEAFC2F00CA3682 /* JSPublicKeyCredential.h */; };
</span><span class="cx">          57DA47B0224034E4002A4612 /* AuthenticationExtensionsClientInputs.h in Headers */ = {isa = PBXBuildFile; fileRef = 57DA47A522401E0F002A4612 /* AuthenticationExtensionsClientInputs.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -8691,6 +8694,10 @@
</span><span class="cx">          57D0018B1DD3DBA400ED19D9 /* CryptoKeyUsage.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = CryptoKeyUsage.idl; sourceTree = "<group>"; };
</span><span class="cx">          57D0018C1DD5413200ED19D9 /* JSCryptoKeyUsage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCryptoKeyUsage.h; sourceTree = "<group>"; };
</span><span class="cx">          57D0018E1DD5415300ED19D9 /* JSCryptoKeyUsage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCryptoKeyUsage.cpp; sourceTree = "<group>"; };
</span><ins>+               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>"; };
</ins><span class="cx">           57D846241FE895F500CA3682 /* NavigatorCredentials.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NavigatorCredentials.cpp; sourceTree = "<group>"; };
</span><span class="cx">          57D846251FE895F600CA3682 /* NavigatorCredentials.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NavigatorCredentials.idl; sourceTree = "<group>"; };
</span><span class="cx">          57D846261FE895F800CA3682 /* NavigatorCredentials.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NavigatorCredentials.h; sourceTree = "<group>"; };
</span><span class="lines">@@ -19532,6 +19539,8 @@
</span><span class="cx">                          57152B5321CB2CE3000C37CA /* apdu */,
</span><span class="cx">                          57303BB32006C6ED00355965 /* cbor */,
</span><span class="cx">                          578A4BFA2166AE0000D08F34 /* fido */,
</span><ins>+                               57D135212294973400827401 /* AttestationConveyancePreference.h */,
+                               57D135232294973400827401 /* AttestationConveyancePreference.idl */,
</ins><span class="cx">                           57DA47A522401E0F002A4612 /* AuthenticationExtensionsClientInputs.h */,
</span><span class="cx">                          57DA47A722401E0F002A4612 /* AuthenticationExtensionsClientInputs.idl */,
</span><span class="cx">                          57303C272009B2FC00355965 /* AuthenticatorAssertionResponse.h */,
</span><span class="lines">@@ -19570,6 +19579,8 @@
</span><span class="cx">          57D8462F1FEAFB0500CA3682 /* WebAuthN */ = {
</span><span class="cx">                  isa = PBXGroup;
</span><span class="cx">                  children = (
</span><ins>+                               57D135272294A7A800827401 /* JSAttestationConveyancePreference.cpp */,
+                               57D135262294A7A700827401 /* JSAttestationConveyancePreference.h */,
</ins><span class="cx">                           57DA47AC224032DC002A4612 /* JSAuthenticationExtensionsClientInputs.cpp */,
</span><span class="cx">                          57DA47AD224032DD002A4612 /* JSAuthenticationExtensionsClientInputs.h */,
</span><span class="cx">                          57303C2E2009B7DA00355965 /* JSAuthenticatorAssertionResponse.cpp */,
</span><span class="lines">@@ -28187,6 +28198,7 @@
</span><span class="cx">                          FD5686CA13AC180200B69C68 /* AsyncAudioDecoder.h in Headers */,
</span><span class="cx">                          E1CDE9221501916900862CC5 /* AsyncFileStream.h in Headers */,
</span><span class="cx">                          0FFD4D6118651FA300512F6E /* AsyncScrollingCoordinator.h in Headers */,
</span><ins>+                               57D135252294A33C00827401 /* AttestationConveyancePreference.h in Headers */,
</ins><span class="cx">                           A8C4A80D09D563270003AC8D /* Attr.h in Headers */,
</span><span class="cx">                          A8C4A80B09D563270003AC8D /* Attribute.h in Headers */,
</span><span class="cx">                          E4A814DA1C70E10D00BF85AC /* AttributeChangeInvalidation.h in Headers */,
</span><span class="lines">@@ -29551,6 +29563,7 @@
</span><span class="cx">                          7C6579F41E00856600E3A27A /* JSApplePayShippingMethod.h in Headers */,
</span><span class="cx">                          1AE96A931D1A0DDD00B86768 /* JSApplePayShippingMethodSelectedEvent.h in Headers */,
</span><span class="cx">                          A12C59FE20360B4A0012236B /* JSApplePayShippingMethodUpdate.h in Headers */,
</span><ins>+                               57D1352C2294AA3D00827401 /* JSAttestationConveyancePreference.h in Headers */,
</ins><span class="cx">                           65DF31DB09D1C123000BE325 /* JSAttr.h in Headers */,
</span><span class="cx">                          FDA15E9E12B03EE1003A583A /* JSAudioBuffer.h in Headers */,
</span><span class="cx">                          FDF7E9C413AC21DB00A51EAC /* JSAudioBufferCallback.h in Headers */,
</span><span class="lines">@@ -29563,6 +29576,7 @@
</span><span class="cx">                          FDA15EB612B03EE1003A583A /* JSAudioProcessingEvent.h in Headers */,
</span><span class="cx">                          BE8EF043171C8FF9009B48C3 /* JSAudioTrack.h in Headers */,
</span><span class="cx">                          BE8EF045171C8FF9009B48C3 /* JSAudioTrackList.h in Headers */,
</span><ins>+                               57D1352A2294AA3900827401 /* JSAuthenticationExtensionsClientInputs.h in Headers */,
</ins><span class="cx">                           57303C2F2009B7E100355965 /* JSAuthenticatorAssertionResponse.h in Headers */,
</span><span class="cx">                          57303C222009AF0300355965 /* JSAuthenticatorAttestationResponse.h in Headers */,
</span><span class="cx">                          57303BE120095D6100355965 /* JSAuthenticatorResponse.h in Headers */,
</span></span></pre></div>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2019-05-22  Jiewen Tan  <jiewen_tan@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):
+
</ins><span class="cx"> 2019-05-22  Zalan Bujtas  <zalan@apple.com>
</span><span class="cx"> 
</span><span class="cx">         [Paste] Add support for preferred presentation size when pasting an image
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebAuthenticationCocoaLocalAuthenticatormm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -324,7 +324,7 @@
</span><span class="cx">             cborArray.append(cbor::CBORValue(toVector((NSData *)adoptCF(SecCertificateCopyData((__bridge SecCertificateRef)certificates[i])).get())));
</span><span class="cx">         attestationStatementMap[cbor::CBORValue("x5c")] = cbor::CBORValue(WTFMove(cborArray));
</span><span class="cx">     }
</span><del>-    auto attestationObject = buildAttestationObject(WTFMove(authData), "Apple", WTFMove(attestationStatementMap));
</del><ins>+    auto attestationObject = buildAttestationObject(WTFMove(authData), "Apple", WTFMove(attestationStatementMap), requestData().creationOptions.attestation);
</ins><span class="cx"> 
</span><span class="cx">     receiveRespond(PublicKeyCredentialData { ArrayBuffer::create(credentialId.data(), credentialId.size()), true, nullptr, ArrayBuffer::create(attestationObject.data(), attestationObject.size()), nullptr, nullptr, nullptr, WTF::nullopt });
</span><span class="cx"> #endif // !PLATFORM(IOS_FAMILY)
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebAuthenticationfidoCtapHidAuthenticatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.cpp (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -62,7 +62,7 @@
</span><span class="cx"> 
</span><span class="cx"> void CtapHidAuthenticator::continueMakeCredentialAfterResponseReceived(Vector<uint8_t>&& data) const
</span><span class="cx"> {
</span><del>-    auto response = readCTAPMakeCredentialResponse(data);
</del><ins>+    auto response = readCTAPMakeCredentialResponse(data, requestData().creationOptions.attestation);
</ins><span class="cx">     if (!response) {
</span><span class="cx">         auto error = getResponseCode(data);
</span><span class="cx">         if (error == CtapDeviceResponseCode::kCtap2ErrCredentialExcluded)
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebAuthenticationfidoU2fHidAuthenticatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/fido/U2fHidAuthenticator.cpp (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -152,7 +152,7 @@
</span><span class="cx"> {
</span><span class="cx">     switch (apduResponse.status()) {
</span><span class="cx">     case ApduResponse::Status::SW_NO_ERROR: {
</span><del>-        auto response = readU2fRegisterResponse(requestData().creationOptions.rp.id, apduResponse.data());
</del><ins>+        auto response = readU2fRegisterResponse(requestData().creationOptions.rp.id, apduResponse.data(), requestData().creationOptions.attestation);
</ins><span class="cx">         if (!response) {
</span><span class="cx">             receiveRespond(ExceptionData { UnknownError, "Couldn't parse the U2F register response."_s });
</span><span class="cx">             return;
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog    2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Tools/ChangeLog       2019-05-22 19:27:49 UTC (rev 245638)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2019-05-22  Jiewen Tan  <jiewen_tan@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.
+
</ins><span class="cx"> 2019-05-22  Zalan Bujtas  <zalan@apple.com>
</span><span class="cx"> 
</span><span class="cx">         [Paste] Add support for preferred presentation size when pasting an image
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebCoreCtapRequestTestcpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/CtapRequestTest.cpp (245637 => 245638)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -59,7 +59,7 @@
</span><span class="cx">     Vector<PublicKeyCredentialCreationOptions::Parameters> params { { PublicKeyCredentialType::PublicKey, 7 }, { PublicKeyCredentialType::PublicKey, 257 } };
</span><span class="cx">     PublicKeyCredentialCreationOptions::AuthenticatorSelectionCriteria selection { PublicKeyCredentialCreationOptions::AuthenticatorAttachment::Platform, true, UserVerificationRequirement::Preferred };
</span><span class="cx"> 
</span><del>-    PublicKeyCredentialCreationOptions options { rp, user, { }, params, WTF::nullopt, { }, selection, WTF::nullopt };
</del><ins>+    PublicKeyCredentialCreationOptions options { rp, user, { }, params, WTF::nullopt, { }, selection, AttestationConveyancePreference::None, WTF::nullopt };
</ins><span class="cx">     Vector<uint8_t> hash;
</span><span class="cx">     hash.append(TestData::kClientDataHash, sizeof(TestData::kClientDataHash));
</span><span class="cx">     auto serializedData = encodeMakeCredenitalRequestAsCBOR(hash, options, AuthenticatorSupportedOptions::UserVerificationAvailability::kSupportedButNotConfigured);
</span></span></pre>
</div>
</div>

</body>
</html>