Diff
Modified: trunk/LayoutTests/ChangeLog (236685 => 236686)
--- trunk/LayoutTests/ChangeLog 2018-10-01 19:45:24 UTC (rev 236685)
+++ trunk/LayoutTests/ChangeLog 2018-10-01 19:47:05 UTC (rev 236686)
@@ -1,3 +1,25 @@
+2018-10-01 Jiewen Tan <jiewen_...@apple.com>
+
+ [WebAuthN] Import a JS CBOR coder
+ https://bugs.webkit.org/show_bug.cgi?id=189877
+ <rdar://problem/44701124>
+
+ Reviewed by Chris Dumez.
+
+ This patch import a 3rd party JS CBOR coder from https://github.com/paroga/cbor-js.
+ The library is MIT licensed, which should be fine to use within WebKit.
+
+ As a benefit from the library, tests are updated to check CBOR binaries.
+
+ * http/wpt/credential-management/credentialscontainer-store-basics.https.html:
+ * http/wpt/webauthn/idl.https.html:
+ * http/wpt/webauthn/public-key-credential-create-failure-local.https.html:
+ * http/wpt/webauthn/public-key-credential-create-success-local.https.html:
+ * http/wpt/webauthn/public-key-credential-get-failure-local.https.html:
+ * http/wpt/webauthn/public-key-credential-get-success-local.https.html:
+ * http/wpt/webauthn/resources/cbor.js: Added.
+ * http/wpt/webauthn/resources/util.js:
+
2018-10-01 Daniel Bates <daba...@apple.com>
[iOS] Special keys are misidentified in DOM keyboard events
Modified: trunk/LayoutTests/http/wpt/credential-management/credentialscontainer-store-basics.https.html (236685 => 236686)
--- trunk/LayoutTests/http/wpt/credential-management/credentialscontainer-store-basics.https.html 2018-10-01 19:45:24 UTC (rev 236685)
+++ trunk/LayoutTests/http/wpt/credential-management/credentialscontainer-store-basics.https.html 2018-10-01 19:47:05 UTC (rev 236686)
@@ -7,6 +7,31 @@
"BDj/zxSkzKgaBuS3cdWDF558of8AaIpgFpsjF/Qm1749VBJPgqUIwfhWHJ91nb7U" +
"PH76c0+WFOzZKslPyyFse4goGIW2R7k9VHLPEZl5nfnBgEVFh5zev+/xpHQIvuq6" +
"RQ==";
+ const testAttestationCertificateBase64 =
+ "MIIB6jCCAZCgAwIBAgIGAWHAxcjvMAoGCCqGSM49BAMCMFMxJzAlBgNVBAMMHkJh" +
+ "c2ljIEF0dGVzdGF0aW9uIFVzZXIgU3ViIENBMTETMBEGA1UECgwKQXBwbGUgSW5j" +
+ "LjETMBEGA1UECAwKQ2FsaWZvcm5pYTAeFw0xODAyMjMwMzM3MjJaFw0xODAyMjQw" +
+ "MzQ3MjJaMGoxIjAgBgNVBAMMGTAwMDA4MDEwLTAwMEE0OUEyMzBBMDIxM0ExGjAY" +
+ "BgNVBAsMEUJBQSBDZXJ0aWZpY2F0aW9uMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMw" +
+ "EQYDVQQIDApDYWxpZm9ybmlhMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvCje" +
+ "Pzr6Sg76XMoHuGabPaG6zjpLFL8Zd8/74Hh5PcL2Zq+o+f7ENXX+7nEXXYt0S8Ux" +
+ "5TIRw4hgbfxXQbWLEqM5MDcwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBPAw" +
+ "FwYJKoZIhvdjZAgCBAowCKEGBAR0ZXN0MAoGCCqGSM49BAMCA0gAMEUCIAlK8A8I" +
+ "k43TbvKuYGHZs1DTgpTwmKTBvIUw5bwgZuYnAiEAtuJjDLKbGNJAJFMi5deEBqno" +
+ "pBTCqbfbDJccfyQpjnY=";
+ const testAttestationIssuingCACertificateBase64 =
+ "MIICIzCCAaigAwIBAgIIeNjhG9tnDGgwCgYIKoZIzj0EAwIwUzEnMCUGA1UEAwwe" +
+ "QmFzaWMgQXR0ZXN0YXRpb24gVXNlciBSb290IENBMRMwEQYDVQQKDApBcHBsZSBJ" +
+ "bmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMB4XDTE3MDQyMDAwNDIwMFoXDTMyMDMy" +
+ "MjAwMDAwMFowUzEnMCUGA1UEAwweQmFzaWMgQXR0ZXN0YXRpb24gVXNlciBTdWIg" +
+ "Q0ExMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMFkw" +
+ "EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoSZ/1t9eBAEVp5a8PrXacmbGb8zNC1X3" +
+ "StLI9YO6Y0CL7blHmSGmjGWTwD4Q+i0J2BY3+bPHTGRyA9jGB3MSbaNmMGQwEgYD" +
+ "VR0TAQH/BAgwBgEB/wIBADAfBgNVHSMEGDAWgBSD5aMhnrB0w/lhkP2XTiMQdqSj" +
+ "8jAdBgNVHQ4EFgQU5mWf1DYLTXUdQ9xmOH/uqeNSD80wDgYDVR0PAQH/BAQDAgEG" +
+ "MAoGCCqGSM49BAMCA2kAMGYCMQC3M360LLtJS60Z9q3vVjJxMgMcFQ1roGTUcKqv" +
+ "W+4hJ4CeJjySXTgq6IEHn/yWab4CMQCm5NnK6SOSK+AqWum9lL87W3E6AA1f2TvJ" +
+ "/hgok/34jr93nhS87tOQNdxDS8zyiqw=";
const testRpId = "localhost";
function asciiToUint8Array(str)
{
@@ -15,22 +40,7 @@
chars.push(str.charCodeAt(i));
return new Uint8Array(chars);
}
- function hexStringToUint8Array(hexString)
- {
- if (hexString.length % 2 != 0)
- throw "Invalid hexString";
- var arrayBuffer = new Uint8Array(hexString.length / 2);
- for (var i = 0; i < hexString.length; i += 2) {
- var byteValue = parseInt(hexString.substr(i, 2), 16);
- if (byteValue == NaN)
- throw "Invalid hexString";
- arrayBuffer[i/2] = byteValue;
- }
-
- return arrayBuffer;
- }
-
promise_test(async function(t) {
const options = {
publicKey: {
@@ -48,7 +58,15 @@
};
// A mock attestation object
if (window.testRunner)
- testRunner.setWebAuthenticationMockConfiguration({ local: { acceptAuthentication: true, acceptAttestation: true, privateKeyBase64: testES256PrivateKeyBase64 } });
+ testRunner.setWebAuthenticationMockConfiguration({
+ local: {
+ acceptAuthentication: true,
+ acceptAttestation: true,
+ privateKeyBase64: testES256PrivateKeyBase64,
+ userCertificateBase64: testAttestationCertificateBase64,
+ intermediateCACertificateBase64: testAttestationIssuingCACertificateBase64
+ }
+ });
const credential = await navigator.credentials.create(options);
return promise_rejects(t, "NotSupportedError",
Modified: trunk/LayoutTests/http/wpt/webauthn/idl.https.html (236685 => 236686)
--- trunk/LayoutTests/http/wpt/webauthn/idl.https.html 2018-10-01 19:45:24 UTC (rev 236685)
+++ trunk/LayoutTests/http/wpt/webauthn/idl.https.html 2018-10-01 19:47:05 UTC (rev 236686)
@@ -20,7 +20,15 @@
<script>
if (window.testRunner)
- testRunner.setWebAuthenticationMockConfiguration({ local: { acceptAuthentication: true, acceptAttestation: true, privateKeyBase64: testES256PrivateKeyBase64 } });
+ testRunner.setWebAuthenticationMockConfiguration({
+ local: {
+ acceptAuthentication: true,
+ acceptAttestation: true,
+ privateKeyBase64: testES256PrivateKeyBase64,
+ userCertificateBase64: testAttestationCertificateBase64,
+ intermediateCACertificateBase64: testAttestationIssuingCACertificateBase64
+ }
+ });
promise_test(async () => {
const idlURL = ["WebAuthN.idl"];
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https.html (236685 => 236686)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https.html 2018-10-01 19:45:24 UTC (rev 236685)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https.html 2018-10-01 19:47:05 UTC (rev 236686)
@@ -6,7 +6,7 @@
<script>
// Default mock configuration. Tests need to override if they need different configuration.
if (window.testRunner)
- testRunner.setWebAuthenticationMockConfiguration({ local: { acceptAuthentication: false, acceptAttestation: false, privateKeyBase64: "" } });
+ testRunner.setWebAuthenticationMockConfiguration({ local: { acceptAuthentication: false, acceptAttestation: false } });
promise_test(t => {
const options = {
@@ -39,7 +39,7 @@
},
challenge: asciiToUint8Array("123456"),
pubKeyCredParams: [{ type: "public-key", alg: -7 }],
- excludeCredentials: [{ type: "public-key", id: Base64URL.parse(testCredentialIdBase64url) }]
+ excludeCredentials: [{ type: "public-key", id: Base64URL.parse(testCredentialIdBase64) }]
}
};
if (window.testRunner)
@@ -64,10 +64,10 @@
challenge: asciiToUint8Array("123456"),
pubKeyCredParams: [{ type: "public-key", alg: -7 }],
excludeCredentials: [
- { type: "public-key", id: Base64URL.parse(testCredentialIdBase64url), transports: ["usb"] },
- { type: "public-key", id: Base64URL.parse(testCredentialIdBase64url), transports: ["nfc"] },
- { type: "public-key", id: Base64URL.parse(testCredentialIdBase64url), transports: ["ble"] },
- { type: "public-key", id: Base64URL.parse(testCredentialIdBase64url), transports: ["internal"] }
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["usb"] },
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["nfc"] },
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["ble"] },
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["internal"] }
]
}
};
@@ -113,7 +113,7 @@
}
};
if (window.testRunner)
- testRunner.setWebAuthenticationMockConfiguration({ local: { acceptAuthentication: true, acceptAttestation: false, privateKeyBase64: "" } });
+ testRunner.setWebAuthenticationMockConfiguration({ local: { acceptAuthentication: true, acceptAttestation: false } });
return promiseRejects(t, "UnknownError", navigator.credentials.create(options), "Unknown internal error.");
}, "PublicKeyCredential's [[create]] without attestation in a mock local authenticator.");
@@ -133,7 +133,7 @@
}
};
if (window.testRunner) {
- testRunner.setWebAuthenticationMockConfiguration({ local: { acceptAuthentication: true, acceptAttestation: false, privateKeyBase64: "" } });
+ testRunner.setWebAuthenticationMockConfiguration({ local: { acceptAuthentication: true, acceptAttestation: false } });
testRunner.addTestKeyToKeychain(testES256PrivateKeyBase64, testRpId, testUserhandleBase64);
}
return promiseRejects(t, "UnknownError", navigator.credentials.create(options), "Unknown internal error.").then(() => {
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https.html (236685 => 236686)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https.html 2018-10-01 19:45:24 UTC (rev 236685)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https.html 2018-10-01 19:47:05 UTC (rev 236686)
@@ -3,10 +3,19 @@
<script src=""
<script src=""
<script src=""
+<script src=""
<script>
// Default mock configuration. Tests need to override if they need different configuration.
if (window.testRunner)
- testRunner.setWebAuthenticationMockConfiguration({ local: { acceptAuthentication: true, acceptAttestation: true, privateKeyBase64: testES256PrivateKeyBase64 } });
+ testRunner.setWebAuthenticationMockConfiguration({
+ local: {
+ acceptAuthentication: true,
+ acceptAttestation: true,
+ privateKeyBase64: testES256PrivateKeyBase64,
+ userCertificateBase64: testAttestationCertificateBase64,
+ intermediateCACertificateBase64: testAttestationIssuingCACertificateBase64
+ }
+ });
function checkResult(credential)
{
@@ -17,12 +26,39 @@
}
// Check respond
- assert_equals(credential.id, testCredentialIdBase64url);
+ assert_array_equals(Base64URL.parse(credential.id), Base64URL.parse(testCredentialIdBase64));
assert_equals(credential.type, 'public-key');
- assert_equals(bytesToHexString(credential.rawId), "48c4971e7805ee110eb04940ef70b7458fbc6d1e");
+ assert_array_equals(new Uint8Array(credential.rawId), Base64URL.parse(testCredentialIdBase64));
assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.create","challenge":"MTIzNDU2","origin":"https://localhost:9443","hashAlgorithm":"SHA-256"}');
- // FIXME(): Check attestation object
assert_throws("NotSupportedError", () => { credential.getClientExtensionResults() });
+
+ // Check attestation
+ const attestationObject = CBOR.decode(credential.response.attestationObject);
+ assert_equals(attestationObject.fmt, "Apple");
+ // Check authData
+ const authData = decodeAuthData(attestationObject.authData);
+ assert_equals(bytesToHexString(authData.rpIdHash), "49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763");
+ assert_equals(authData.flags, 69);
+ assert_equals(authData.counter, 0);
+ 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));
+
+ // 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 => {
@@ -82,9 +118,9 @@
challenge: asciiToUint8Array("123456"),
pubKeyCredParams: [{ type: "public-key", alg: -7 }],
excludeCredentials: [
- { type: "public-key", id: Base64URL.parse(testCredentialIdBase64url), transports: ["usb"] },
- { type: "public-key", id: Base64URL.parse(testCredentialIdBase64url), transports: ["nfc"] },
- { type: "public-key", id: Base64URL.parse(testCredentialIdBase64url), transports: ["ble"] }
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["usb"] },
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["nfc"] },
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["ble"] }
]
}
};
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local.https.html (236685 => 236686)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local.https.html 2018-10-01 19:45:24 UTC (rev 236685)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local.https.html 2018-10-01 19:47:05 UTC (rev 236686)
@@ -6,7 +6,7 @@
<script>
// Default mock configuration. Tests need to override if they need different configuration.
if (window.testRunner)
- testRunner.setWebAuthenticationMockConfiguration({ local: { acceptAuthentication: false, acceptAttestation: false, privateKeyBase64: "" } });
+ testRunner.setWebAuthenticationMockConfiguration({ local: { acceptAuthentication: false, acceptAttestation: false } });
promise_test(t => {
const options = {
@@ -13,10 +13,10 @@
publicKey: {
challenge: asciiToUint8Array("123456"),
allowCredentials: [
- { type: "public-key", id: Base64URL.parse(testCredentialIdBase64url), transports: ["usb"] },
- { type: "public-key", id: Base64URL.parse(testCredentialIdBase64url), transports: ["nfc"] },
- { type: "public-key", id: Base64URL.parse(testCredentialIdBase64url), transports: ["ble"] },
- { type: "public-key", id: Base64URL.parse(testCredentialIdBase64url), transports: ["internal"] }
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["usb"] },
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["nfc"] },
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["ble"] },
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["internal"] }
]
}
};
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-local.https.html (236685 => 236686)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-local.https.html 2018-10-01 19:45:24 UTC (rev 236685)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-local.https.html 2018-10-01 19:47:05 UTC (rev 236686)
@@ -6,7 +6,7 @@
<script>
// Default mock configuration. Tests need to override if they need different configuration.
if (window.testRunner)
- testRunner.setWebAuthenticationMockConfiguration({ local: { acceptAuthentication: true, acceptAttestation: false, privateKeyBase64: "" } });
+ testRunner.setWebAuthenticationMockConfiguration({ local: { acceptAuthentication: true, acceptAttestation: false } });
function checkResult(credential)
{
@@ -14,9 +14,9 @@
testRunner.cleanUpKeychain(testRpId);
// Check respond
- assert_equals(credential.id, testCredentialIdBase64url);
+ assert_array_equals(Base64URL.parse(credential.id), Base64URL.parse(testCredentialIdBase64));
assert_equals(credential.type, 'public-key');
- assert_equals(bytesToHexString(credential.rawId), "48c4971e7805ee110eb04940ef70b7458fbc6d1e");
+ assert_array_equals(new Uint8Array(credential.rawId), Base64URL.parse(testCredentialIdBase64));
assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.get","challenge":"MTIzNDU2","origin":"https://localhost:9443","hashAlgorithm":"SHA-256"}');
assert_equals(bytesToHexString(credential.response.userHandle), "00010203040506070809");
@@ -27,7 +27,7 @@
assert_equals(authData.counter, 0);
// Check signature
- return crypto.subtle.importKey("raw", Base64URL.parse(testES256PublicKeyBase64url), { name: "ECDSA", namedCurve: "P-256" }, false, ['verify']).then( publicKey => {
+ return crypto.subtle.importKey("raw", Base64URL.parse(testES256PublicKeyBase64), { name: "ECDSA", namedCurve: "P-256" }, false, ['verify']).then( publicKey => {
return crypto.subtle.digest("sha-256", credential.response.clientDataJSON).then ( hash => {
// credential.response.signature is in ASN.1 and WebCrypto expect signatures provides in r|s.
return crypto.subtle.verify({name: "ECDSA", hash: "SHA-256"}, publicKey, extractRawSignature(credential.response.signature), concatenateBuffers(credential.response.authenticatorData, hash)).then( verified => {
@@ -58,7 +58,7 @@
challenge: Base64URL.parse("MTIzNDU2"),
allowCredentials: [
{ type: "public-key", id: Base64URL.parse(testUserhandleBase64), transports: ["internal"] },
- { type: "public-key", id: Base64URL.parse(testCredentialIdBase64url), transports: ["internal"] }
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["internal"] }
]
}
};
Added: trunk/LayoutTests/http/wpt/webauthn/resources/cbor.js (0 => 236686)
--- trunk/LayoutTests/http/wpt/webauthn/resources/cbor.js (rev 0)
+++ trunk/LayoutTests/http/wpt/webauthn/resources/cbor.js 2018-10-01 19:47:05 UTC (rev 236686)
@@ -0,0 +1,406 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-2016 Patrick Gansterer <par...@paroga.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+(function(global, undefined) { "use strict";
+var POW_2_24 = 5.960464477539063e-8,
+ POW_2_32 = 4294967296,
+ POW_2_53 = 9007199254740992;
+
+function encode(value) {
+ var data = "" ArrayBuffer(256);
+ var dataView = new DataView(data);
+ var lastLength;
+ var offset = 0;
+
+ function prepareWrite(length) {
+ var newByteLength = data.byteLength;
+ var requiredLength = offset + length;
+ while (newByteLength < requiredLength)
+ newByteLength <<= 1;
+ if (newByteLength !== data.byteLength) {
+ var oldDataView = dataView;
+ data = "" ArrayBuffer(newByteLength);
+ dataView = new DataView(data);
+ var uint32count = (offset + 3) >> 2;
+ for (var i = 0; i < uint32count; ++i)
+ dataView.setUint32(i << 2, oldDataView.getUint32(i << 2));
+ }
+
+ lastLength = length;
+ return dataView;
+ }
+ function commitWrite() {
+ offset += lastLength;
+ }
+ function writeFloat64(value) {
+ commitWrite(prepareWrite(8).setFloat64(offset, value));
+ }
+ function writeUint8(value) {
+ commitWrite(prepareWrite(1).setUint8(offset, value));
+ }
+ function writeUint8Array(value) {
+ var dataView = prepareWrite(value.length);
+ for (var i = 0; i < value.length; ++i)
+ dataView.setUint8(offset + i, value[i]);
+ commitWrite();
+ }
+ function writeUint16(value) {
+ commitWrite(prepareWrite(2).setUint16(offset, value));
+ }
+ function writeUint32(value) {
+ commitWrite(prepareWrite(4).setUint32(offset, value));
+ }
+ function writeUint64(value) {
+ var low = value % POW_2_32;
+ var high = (value - low) / POW_2_32;
+ var dataView = prepareWrite(8);
+ dataView.setUint32(offset, high);
+ dataView.setUint32(offset + 4, low);
+ commitWrite();
+ }
+ function writeTypeAndLength(type, length) {
+ if (length < 24) {
+ writeUint8(type << 5 | length);
+ } else if (length < 0x100) {
+ writeUint8(type << 5 | 24);
+ writeUint8(length);
+ } else if (length < 0x10000) {
+ writeUint8(type << 5 | 25);
+ writeUint16(length);
+ } else if (length < 0x100000000) {
+ writeUint8(type << 5 | 26);
+ writeUint32(length);
+ } else {
+ writeUint8(type << 5 | 27);
+ writeUint64(length);
+ }
+ }
+
+ function encodeItem(value) {
+ var i;
+
+ if (value === false)
+ return writeUint8(0xf4);
+ if (value === true)
+ return writeUint8(0xf5);
+ if (value === null)
+ return writeUint8(0xf6);
+ if (value === undefined)
+ return writeUint8(0xf7);
+
+ switch (typeof value) {
+ case "number":
+ if (Math.floor(value) === value) {
+ if (0 <= value && value <= POW_2_53)
+ return writeTypeAndLength(0, value);
+ if (-POW_2_53 <= value && value < 0)
+ return writeTypeAndLength(1, -(value + 1));
+ }
+ writeUint8(0xfb);
+ return writeFloat64(value);
+
+ case "string":
+ var utf8data = [];
+ for (i = 0; i < value.length; ++i) {
+ var charCode = value.charCodeAt(i);
+ if (charCode < 0x80) {
+ utf8data.push(charCode);
+ } else if (charCode < 0x800) {
+ utf8data.push(0xc0 | charCode >> 6);
+ utf8data.push(0x80 | charCode & 0x3f);
+ } else if (charCode < 0xd800) {
+ utf8data.push(0xe0 | charCode >> 12);
+ utf8data.push(0x80 | (charCode >> 6) & 0x3f);
+ utf8data.push(0x80 | charCode & 0x3f);
+ } else {
+ charCode = (charCode & 0x3ff) << 10;
+ charCode |= value.charCodeAt(++i) & 0x3ff;
+ charCode += 0x10000;
+
+ utf8data.push(0xf0 | charCode >> 18);
+ utf8data.push(0x80 | (charCode >> 12) & 0x3f);
+ utf8data.push(0x80 | (charCode >> 6) & 0x3f);
+ utf8data.push(0x80 | charCode & 0x3f);
+ }
+ }
+
+ writeTypeAndLength(3, utf8data.length);
+ return writeUint8Array(utf8data);
+
+ default:
+ var length;
+ if (Array.isArray(value)) {
+ length = value.length;
+ writeTypeAndLength(4, length);
+ for (i = 0; i < length; ++i)
+ encodeItem(value[i]);
+ } else if (value instanceof Uint8Array) {
+ writeTypeAndLength(2, value.length);
+ writeUint8Array(value);
+ } else {
+ var keys = Object.keys(value);
+ length = keys.length;
+ writeTypeAndLength(5, length);
+ for (i = 0; i < length; ++i) {
+ var key = keys[i];
+ encodeItem(key);
+ encodeItem(value[key]);
+ }
+ }
+ }
+ }
+
+ encodeItem(value);
+
+ if ("slice" in data)
+ return data.slice(0, offset);
+
+ var ret = new ArrayBuffer(offset);
+ var retView = new DataView(ret);
+ for (var i = 0; i < offset; ++i)
+ retView.setUint8(i, dataView.getUint8(i));
+ return ret;
+}
+
+function decode(data, tagger, simpleValue) {
+ var dataView = new DataView(data);
+ var offset = 0;
+
+ if (typeof tagger !== "function")
+ tagger = function(value) { return value; };
+ if (typeof simpleValue !== "function")
+ simpleValue = function() { return undefined; };
+
+ function commitRead(length, value) {
+ offset += length;
+ return value;
+ }
+ function readArrayBuffer(length) {
+ return commitRead(length, new Uint8Array(data, offset, length));
+ }
+ function readFloat16() {
+ var tempArrayBuffer = new ArrayBuffer(4);
+ var tempDataView = new DataView(tempArrayBuffer);
+ var value = readUint16();
+
+ var sign = value & 0x8000;
+ var exponent = value & 0x7c00;
+ var fraction = value & 0x03ff;
+
+ if (exponent === 0x7c00)
+ exponent = 0xff << 10;
+ else if (exponent !== 0)
+ exponent += (127 - 15) << 10;
+ else if (fraction !== 0)
+ return (sign ? -1 : 1) * fraction * POW_2_24;
+
+ tempDataView.setUint32(0, sign << 16 | exponent << 13 | fraction << 13);
+ return tempDataView.getFloat32(0);
+ }
+ function readFloat32() {
+ return commitRead(4, dataView.getFloat32(offset));
+ }
+ function readFloat64() {
+ return commitRead(8, dataView.getFloat64(offset));
+ }
+ function readUint8() {
+ return commitRead(1, dataView.getUint8(offset));
+ }
+ function readUint16() {
+ return commitRead(2, dataView.getUint16(offset));
+ }
+ function readUint32() {
+ return commitRead(4, dataView.getUint32(offset));
+ }
+ function readUint64() {
+ return readUint32() * POW_2_32 + readUint32();
+ }
+ function readBreak() {
+ if (dataView.getUint8(offset) !== 0xff)
+ return false;
+ offset += 1;
+ return true;
+ }
+ function readLength(additionalInformation) {
+ if (additionalInformation < 24)
+ return additionalInformation;
+ if (additionalInformation === 24)
+ return readUint8();
+ if (additionalInformation === 25)
+ return readUint16();
+ if (additionalInformation === 26)
+ return readUint32();
+ if (additionalInformation === 27)
+ return readUint64();
+ if (additionalInformation === 31)
+ return -1;
+ throw "Invalid length encoding";
+ }
+ function readIndefiniteStringLength(majorType) {
+ var initialByte = readUint8();
+ if (initialByte === 0xff)
+ return -1;
+ var length = readLength(initialByte & 0x1f);
+ if (length < 0 || (initialByte >> 5) !== majorType)
+ throw "Invalid indefinite length element";
+ return length;
+ }
+
+ function appendUtf16Data(utf16data, length) {
+ for (var i = 0; i < length; ++i) {
+ var value = readUint8();
+ if (value & 0x80) {
+ if (value < 0xe0) {
+ value = (value & 0x1f) << 6
+ | (readUint8() & 0x3f);
+ length -= 1;
+ } else if (value < 0xf0) {
+ value = (value & 0x0f) << 12
+ | (readUint8() & 0x3f) << 6
+ | (readUint8() & 0x3f);
+ length -= 2;
+ } else {
+ value = (value & 0x0f) << 18
+ | (readUint8() & 0x3f) << 12
+ | (readUint8() & 0x3f) << 6
+ | (readUint8() & 0x3f);
+ length -= 3;
+ }
+ }
+
+ if (value < 0x10000) {
+ utf16data.push(value);
+ } else {
+ value -= 0x10000;
+ utf16data.push(0xd800 | (value >> 10));
+ utf16data.push(0xdc00 | (value & 0x3ff));
+ }
+ }
+ }
+
+ function decodeItem() {
+ var initialByte = readUint8();
+ var majorType = initialByte >> 5;
+ var additionalInformation = initialByte & 0x1f;
+ var i;
+ var length;
+
+ if (majorType === 7) {
+ switch (additionalInformation) {
+ case 25:
+ return readFloat16();
+ case 26:
+ return readFloat32();
+ case 27:
+ return readFloat64();
+ }
+ }
+
+ length = readLength(additionalInformation);
+ if (length < 0 && (majorType < 2 || 6 < majorType))
+ throw "Invalid length";
+
+ switch (majorType) {
+ case 0:
+ return length;
+ case 1:
+ return -1 - length;
+ case 2:
+ if (length < 0) {
+ var elements = [];
+ var fullArrayLength = 0;
+ while ((length = readIndefiniteStringLength(majorType)) >= 0) {
+ fullArrayLength += length;
+ elements.push(readArrayBuffer(length));
+ }
+ var fullArray = new Uint8Array(fullArrayLength);
+ var fullArrayOffset = 0;
+ for (i = 0; i < elements.length; ++i) {
+ fullArray.set(elements[i], fullArrayOffset);
+ fullArrayOffset += elements[i].length;
+ }
+ return fullArray;
+ }
+ return readArrayBuffer(length);
+ case 3:
+ var utf16data = [];
+ if (length < 0) {
+ while ((length = readIndefiniteStringLength(majorType)) >= 0)
+ appendUtf16Data(utf16data, length);
+ } else
+ appendUtf16Data(utf16data, length);
+ return String.fromCharCode.apply(null, utf16data);
+ case 4:
+ var retArray;
+ if (length < 0) {
+ retArray = [];
+ while (!readBreak())
+ retArray.push(decodeItem());
+ } else {
+ retArray = new Array(length);
+ for (i = 0; i < length; ++i)
+ retArray[i] = decodeItem();
+ }
+ return retArray;
+ case 5:
+ var retObject = {};
+ for (i = 0; i < length || length < 0 && !readBreak(); ++i) {
+ var key = decodeItem();
+ retObject[key] = decodeItem();
+ }
+ return retObject;
+ case 6:
+ return tagger(decodeItem(), length);
+ case 7:
+ switch (length) {
+ case 20:
+ return false;
+ case 21:
+ return true;
+ case 22:
+ return null;
+ case 23:
+ return undefined;
+ default:
+ return simpleValue(length);
+ }
+ }
+ }
+
+ var ret = decodeItem();
+ if (offset !== data.byteLength)
+ throw "Remaining bytes";
+ return ret;
+}
+
+var obj = { encode: encode, decode: decode };
+
+if (typeof define === "function" && define.amd)
+ define("cbor/cbor", obj);
+else if (typeof module !== "undefined" && module.exports)
+ module.exports = obj;
+else if (!global.CBOR)
+ global.CBOR = obj;
+
+})(this);
Modified: trunk/LayoutTests/http/wpt/webauthn/resources/util.js (236685 => 236686)
--- trunk/LayoutTests/http/wpt/webauthn/resources/util.js 2018-10-01 19:45:24 UTC (rev 236685)
+++ trunk/LayoutTests/http/wpt/webauthn/resources/util.js 2018-10-01 19:47:05 UTC (rev 236686)
@@ -1,13 +1,38 @@
-const testCredentialIdBase64url = "SMSXHngF7hEOsElA73C3RY-8bR4";
+const testCredentialIdBase64 = "SMSXHngF7hEOsElA73C3RY+8bR4=";
const testES256PrivateKeyBase64 =
"BDj/zxSkzKgaBuS3cdWDF558of8AaIpgFpsjF/Qm1749VBJPgqUIwfhWHJ91nb7U" +
"PH76c0+WFOzZKslPyyFse4goGIW2R7k9VHLPEZl5nfnBgEVFh5zev+/xpHQIvuq6" +
"RQ==";
-const testES256PublicKeyBase64url =
- "BDj_zxSkzKgaBuS3cdWDF558of8AaIpgFpsjF_Qm1749VBJPgqUIwfhWHJ91nb7U" +
- "PH76c0-WFOzZKslPyyFse4g";
+const testES256PublicKeyBase64 =
+ "BDj/zxSkzKgaBuS3cdWDF558of8AaIpgFpsjF/Qm1749VBJPgqUIwfhWHJ91nb7U" +
+ "PH76c0+WFOzZKslPyyFse4g=";
const testRpId = "localhost";
const testUserhandleBase64 = "AAECAwQFBgcICQ==";
+const testAttestationCertificateBase64 =
+ "MIIB6jCCAZCgAwIBAgIGAWHAxcjvMAoGCCqGSM49BAMCMFMxJzAlBgNVBAMMHkJh" +
+ "c2ljIEF0dGVzdGF0aW9uIFVzZXIgU3ViIENBMTETMBEGA1UECgwKQXBwbGUgSW5j" +
+ "LjETMBEGA1UECAwKQ2FsaWZvcm5pYTAeFw0xODAyMjMwMzM3MjJaFw0xODAyMjQw" +
+ "MzQ3MjJaMGoxIjAgBgNVBAMMGTAwMDA4MDEwLTAwMEE0OUEyMzBBMDIxM0ExGjAY" +
+ "BgNVBAsMEUJBQSBDZXJ0aWZpY2F0aW9uMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMw" +
+ "EQYDVQQIDApDYWxpZm9ybmlhMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvCje" +
+ "Pzr6Sg76XMoHuGabPaG6zjpLFL8Zd8/74Hh5PcL2Zq+o+f7ENXX+7nEXXYt0S8Ux" +
+ "5TIRw4hgbfxXQbWLEqM5MDcwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBPAw" +
+ "FwYJKoZIhvdjZAgCBAowCKEGBAR0ZXN0MAoGCCqGSM49BAMCA0gAMEUCIAlK8A8I" +
+ "k43TbvKuYGHZs1DTgpTwmKTBvIUw5bwgZuYnAiEAtuJjDLKbGNJAJFMi5deEBqno" +
+ "pBTCqbfbDJccfyQpjnY=";
+const testAttestationIssuingCACertificateBase64 =
+ "MIICIzCCAaigAwIBAgIIeNjhG9tnDGgwCgYIKoZIzj0EAwIwUzEnMCUGA1UEAwwe" +
+ "QmFzaWMgQXR0ZXN0YXRpb24gVXNlciBSb290IENBMRMwEQYDVQQKDApBcHBsZSBJ" +
+ "bmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMB4XDTE3MDQyMDAwNDIwMFoXDTMyMDMy" +
+ "MjAwMDAwMFowUzEnMCUGA1UEAwweQmFzaWMgQXR0ZXN0YXRpb24gVXNlciBTdWIg" +
+ "Q0ExMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMFkw" +
+ "EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoSZ/1t9eBAEVp5a8PrXacmbGb8zNC1X3" +
+ "StLI9YO6Y0CL7blHmSGmjGWTwD4Q+i0J2BY3+bPHTGRyA9jGB3MSbaNmMGQwEgYD" +
+ "VR0TAQH/BAgwBgEB/wIBADAfBgNVHSMEGDAWgBSD5aMhnrB0w/lhkP2XTiMQdqSj" +
+ "8jAdBgNVHQ4EFgQU5mWf1DYLTXUdQ9xmOH/uqeNSD80wDgYDVR0PAQH/BAQDAgEG" +
+ "MAoGCCqGSM49BAMCA2kAMGYCMQC3M360LLtJS60Z9q3vVjJxMgMcFQ1roGTUcKqv" +
+ "W+4hJ4CeJjySXTgq6IEHn/yWab4CMQCm5NnK6SOSK+AqWum9lL87W3E6AA1f2TvJ" +
+ "/hgok/34jr93nhS87tOQNdxDS8zyiqw=";
const RESOURCES_DIR = "/WebKit/webauthn/resources/";
@@ -125,7 +150,10 @@
authDataObject.credentialID = authDataUint8Array.slice(pos, pos + size);
pos = pos + size;
- // FIXME(): Add CBOR decoder to parse the public key.
+ // Public Key
+ authDataObject.publicKey = CBOR.decode(authDataUint8Array.slice(pos).buffer);
+ if (!authDataObject.publicKey)
+ return { };
// Assume no extensions.
return authDataObject;
@@ -178,4 +206,20 @@
assert_throws(expected, function() { throw e }, description);
assert_equals(e.message, description);
});
-}
\ No newline at end of file
+}
+
+// COSE Key Format: https://www.w3.org/TR/webauthn/#sctn-encoded-credPubKey-examples.
+function checkPublicKey(publicKey)
+{
+ if (publicKey['1'] != 2)
+ return false;
+ if (publicKey['3'] != -7)
+ return false;
+ if (publicKey['-1'] != 1)
+ return false;
+ if (publicKey['-2'].byteLength != 32)
+ return false;
+ if (publicKey['-3'].byteLength != 32)
+ return false;
+ return true;
+}
Modified: trunk/Source/WebKit/ChangeLog (236685 => 236686)
--- trunk/Source/WebKit/ChangeLog 2018-10-01 19:45:24 UTC (rev 236685)
+++ trunk/Source/WebKit/ChangeLog 2018-10-01 19:47:05 UTC (rev 236686)
@@ -1,3 +1,21 @@
+2018-10-01 Jiewen Tan <jiewen_...@apple.com>
+
+ [WebAuthN] Import a JS CBOR coder
+ https://bugs.webkit.org/show_bug.cgi?id=189877
+ <rdar://problem/44701124>
+
+ Reviewed by Chris Dumez.
+
+ Update MockWebAuthenticationConfiguration to have userCertificateBase64 and intermediateCACertificateBase64
+ as Local's memeber such that tests can pass those certificates to MockLocalConnection instead of letting it
+ holds some static ones.
+
+ * UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
+ (WKWebsiteDataStoreSetWebAuthenticationMockConfiguration):
+ * UIProcess/WebAuthentication/Mock/MockLocalConnection.mm:
+ (WebKit::MockLocalConnection::getAttestation const):
+ * UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h:
+
2018-10-01 Chris Dumez <cdu...@apple.com>
Regression(r236512): http/tests/navigation/keyboard-events-during-provisional-navigation.html is flaky
Modified: trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp (236685 => 236686)
--- trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp 2018-10-01 19:45:24 UTC (rev 236685)
+++ trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp 2018-10-01 19:47:05 UTC (rev 236686)
@@ -582,7 +582,11 @@
MockWebAuthenticationConfiguration::Local local;
local.acceptAuthentication = WKBooleanGetValue(static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(localRef, adoptWK(WKStringCreateWithUTF8CString("AcceptAuthentication")).get())));
local.acceptAttestation = WKBooleanGetValue(static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(localRef, adoptWK(WKStringCreateWithUTF8CString("AcceptAttestation")).get())));
- local.privateKeyBase64 = WebKit::toImpl(static_cast<WKStringRef>(WKDictionaryGetItemForKey(localRef, adoptWK(WKStringCreateWithUTF8CString("PrivateKeyBase64")).get())))->string();
+ if (local.acceptAttestation) {
+ local.privateKeyBase64 = WebKit::toImpl(static_cast<WKStringRef>(WKDictionaryGetItemForKey(localRef, adoptWK(WKStringCreateWithUTF8CString("PrivateKeyBase64")).get())))->string();
+ local.userCertificateBase64 = WebKit::toImpl(static_cast<WKStringRef>(WKDictionaryGetItemForKey(localRef, adoptWK(WKStringCreateWithUTF8CString("UserCertificateBase64")).get())))->string();
+ local.intermediateCACertificateBase64 = WebKit::toImpl(static_cast<WKStringRef>(WKDictionaryGetItemForKey(localRef, adoptWK(WKStringCreateWithUTF8CString("IntermediateCACertificateBase64")).get())))->string();
+ }
configuration.local = WTFMove(local);
}
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.mm (236685 => 236686)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.mm 2018-10-01 19:45:24 UTC (rev 236685)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.mm 2018-10-01 19:47:05 UTC (rev 236686)
@@ -36,34 +36,6 @@
namespace WebKit {
-namespace MockLocalConnectionInternal {
-const char* const testAttestationCertificateBase64 =
- "MIIB6jCCAZCgAwIBAgIGAWHAxcjvMAoGCCqGSM49BAMCMFMxJzAlBgNVBAMMHkJh"
- "c2ljIEF0dGVzdGF0aW9uIFVzZXIgU3ViIENBMTETMBEGA1UECgwKQXBwbGUgSW5j"
- "LjETMBEGA1UECAwKQ2FsaWZvcm5pYTAeFw0xODAyMjMwMzM3MjJaFw0xODAyMjQw"
- "MzQ3MjJaMGoxIjAgBgNVBAMMGTAwMDA4MDEwLTAwMEE0OUEyMzBBMDIxM0ExGjAY"
- "BgNVBAsMEUJBQSBDZXJ0aWZpY2F0aW9uMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMw"
- "EQYDVQQIDApDYWxpZm9ybmlhMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvCje"
- "Pzr6Sg76XMoHuGabPaG6zjpLFL8Zd8/74Hh5PcL2Zq+o+f7ENXX+7nEXXYt0S8Ux"
- "5TIRw4hgbfxXQbWLEqM5MDcwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBPAw"
- "FwYJKoZIhvdjZAgCBAowCKEGBAR0ZXN0MAoGCCqGSM49BAMCA0gAMEUCIAlK8A8I"
- "k43TbvKuYGHZs1DTgpTwmKTBvIUw5bwgZuYnAiEAtuJjDLKbGNJAJFMi5deEBqno"
- "pBTCqbfbDJccfyQpjnY=";
-const char* const testAttestationIssuingCACertificateBase64 =
- "MIICIzCCAaigAwIBAgIIeNjhG9tnDGgwCgYIKoZIzj0EAwIwUzEnMCUGA1UEAwwe"
- "QmFzaWMgQXR0ZXN0YXRpb24gVXNlciBSb290IENBMRMwEQYDVQQKDApBcHBsZSBJ"
- "bmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMB4XDTE3MDQyMDAwNDIwMFoXDTMyMDMy"
- "MjAwMDAwMFowUzEnMCUGA1UEAwweQmFzaWMgQXR0ZXN0YXRpb24gVXNlciBTdWIg"
- "Q0ExMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMFkw"
- "EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoSZ/1t9eBAEVp5a8PrXacmbGb8zNC1X3"
- "StLI9YO6Y0CL7blHmSGmjGWTwD4Q+i0J2BY3+bPHTGRyA9jGB3MSbaNmMGQwEgYD"
- "VR0TAQH/BAgwBgEB/wIBADAfBgNVHSMEGDAWgBSD5aMhnrB0w/lhkP2XTiMQdqSj"
- "8jAdBgNVHQ4EFgQU5mWf1DYLTXUdQ9xmOH/uqeNSD80wDgYDVR0PAQH/BAQDAgEG"
- "MAoGCCqGSM49BAMCA2kAMGYCMQC3M360LLtJS60Z9q3vVjJxMgMcFQ1roGTUcKqv"
- "W+4hJ4CeJjySXTgq6IEHn/yWab4CMQCm5NnK6SOSK+AqWum9lL87W3E6AA1f2TvJ"
- "/hgok/34jr93nhS87tOQNdxDS8zyiqw=";
-}
-
MockLocalConnection::MockLocalConnection(const MockWebAuthenticationConfiguration& configuration)
: m_configuration(configuration)
{
@@ -97,8 +69,6 @@
void MockLocalConnection::getAttestation(const String& rpId, const String& username, const Vector<uint8_t>& hash, AttestationCallback&& callback) const
{
- using namespace MockLocalConnectionInternal;
-
// Mock async operations.
RunLoop::main().dispatch([configuration = m_configuration, rpId, username, hash, callback = WTFMove(callback)]() mutable {
ASSERT(configuration.local);
@@ -131,10 +101,8 @@
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)addQuery, NULL);
ASSERT_UNUSED(status, !status);
- // Construct dummy certificates. The content of certificates is not important. We need them to present to
- // check the CBOR encoding procedure.
- auto attestationCertificate = adoptCF(SecCertificateCreateWithData(NULL, (__bridge CFDataRef)adoptNS([[NSData alloc] initWithBase64EncodedString:[NSString stringWithCString:testAttestationCertificateBase64 encoding:NSASCIIStringEncoding] options:NSDataBase64DecodingIgnoreUnknownCharacters]).get()));
- auto attestationIssuingCACertificate = adoptCF(SecCertificateCreateWithData(NULL, (__bridge CFDataRef)adoptNS([[NSData alloc] initWithBase64EncodedString:[NSString stringWithCString:testAttestationIssuingCACertificateBase64 encoding:NSASCIIStringEncoding] options:NSDataBase64DecodingIgnoreUnknownCharacters]).get()));
+ auto attestationCertificate = adoptCF(SecCertificateCreateWithData(NULL, (__bridge CFDataRef)adoptNS([[NSData alloc] initWithBase64EncodedString:configuration.local->userCertificateBase64 options:NSDataBase64DecodingIgnoreUnknownCharacters]).get()));
+ auto attestationIssuingCACertificate = adoptCF(SecCertificateCreateWithData(NULL, (__bridge CFDataRef)adoptNS([[NSData alloc] initWithBase64EncodedString:configuration.local->intermediateCACertificateBase64 options:NSDataBase64DecodingIgnoreUnknownCharacters]).get()));
callback(key.get(), [NSArray arrayWithObjects: (__bridge id)attestationCertificate.get(), (__bridge id)attestationIssuingCACertificate.get(), nil], NULL);
});
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h (236685 => 236686)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h 2018-10-01 19:45:24 UTC (rev 236685)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h 2018-10-01 19:47:05 UTC (rev 236686)
@@ -34,6 +34,8 @@
bool acceptAuthentication { false };
bool acceptAttestation { false };
String privateKeyBase64;
+ String userCertificateBase64;
+ String intermediateCACertificateBase64;
};
std::optional<Local> local;
Modified: trunk/Tools/ChangeLog (236685 => 236686)
--- trunk/Tools/ChangeLog 2018-10-01 19:45:24 UTC (rev 236685)
+++ trunk/Tools/ChangeLog 2018-10-01 19:47:05 UTC (rev 236686)
@@ -1,3 +1,17 @@
+2018-10-01 Jiewen Tan <jiewen_...@apple.com>
+
+ [WebAuthN] Import a JS CBOR coder
+ https://bugs.webkit.org/show_bug.cgi?id=189877
+ <rdar://problem/44701124>
+
+ Reviewed by Chris Dumez.
+
+ Add logic to only process privateKeyBase64, userCertificateBase64 and intermediateCACertificateBase64
+ only if acceptAttestation is true.
+
+ * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+ (WTR::TestRunner::setWebAuthenticationMockConfiguration):
+
2018-10-01 Chris Dumez <cdu...@apple.com>
Regression(r236512): http/tests/navigation/keyboard-events-during-provisional-navigation.html is flaky
Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp (236685 => 236686)
--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp 2018-10-01 19:45:24 UTC (rev 236685)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp 2018-10-01 19:47:05 UTC (rev 236686)
@@ -2380,11 +2380,6 @@
return;
bool acceptAttestation = JSValueToBoolean(context, acceptAttestationValue);
- JSRetainPtr<JSStringRef> privateKeyBase64PropertyName(Adopt, JSStringCreateWithUTF8CString("privateKeyBase64"));
- JSValueRef privateKeyBase64Value = JSObjectGetProperty(context, local, privateKeyBase64PropertyName.get(), 0);
- if (!JSValueIsString(context, privateKeyBase64Value))
- return;
-
Vector<WKRetainPtr<WKStringRef>> localKeys;
Vector<WKRetainPtr<WKTypeRef>> localValues;
localKeys.append({ AdoptWK, WKStringCreateWithUTF8CString("AcceptAuthentication") });
@@ -2391,9 +2386,31 @@
localValues.append(adoptWK(WKBooleanCreate(acceptAuthentication)).get());
localKeys.append({ AdoptWK, WKStringCreateWithUTF8CString("AcceptAttestation") });
localValues.append(adoptWK(WKBooleanCreate(acceptAttestation)).get());
- localKeys.append({ AdoptWK, WKStringCreateWithUTF8CString("PrivateKeyBase64") });
- localValues.append(toWK(adopt(JSValueToStringCopy(context, privateKeyBase64Value, 0)).get()));
+ if (acceptAttestation) {
+ JSRetainPtr<JSStringRef> privateKeyBase64PropertyName(Adopt, JSStringCreateWithUTF8CString("privateKeyBase64"));
+ JSValueRef privateKeyBase64Value = JSObjectGetProperty(context, local, privateKeyBase64PropertyName.get(), 0);
+ if (!JSValueIsString(context, privateKeyBase64Value))
+ return;
+
+ JSRetainPtr<JSStringRef> userCertificateBase64PropertyName(Adopt, JSStringCreateWithUTF8CString("userCertificateBase64"));
+ JSValueRef userCertificateBase64Value = JSObjectGetProperty(context, local, userCertificateBase64PropertyName.get(), 0);
+ if (!JSValueIsString(context, userCertificateBase64Value))
+ return;
+
+ JSRetainPtr<JSStringRef> intermediateCACertificateBase64PropertyName(Adopt, JSStringCreateWithUTF8CString("intermediateCACertificateBase64"));
+ JSValueRef intermediateCACertificateBase64Value = JSObjectGetProperty(context, local, intermediateCACertificateBase64PropertyName.get(), 0);
+ if (!JSValueIsString(context, intermediateCACertificateBase64Value))
+ return;
+
+ localKeys.append({ AdoptWK, WKStringCreateWithUTF8CString("PrivateKeyBase64") });
+ localValues.append(toWK(adopt(JSValueToStringCopy(context, privateKeyBase64Value, 0)).get()));
+ localKeys.append({ AdoptWK, WKStringCreateWithUTF8CString("UserCertificateBase64") });
+ localValues.append(toWK(adopt(JSValueToStringCopy(context, userCertificateBase64Value, 0)).get()));
+ localKeys.append({ AdoptWK, WKStringCreateWithUTF8CString("IntermediateCACertificateBase64") });
+ localValues.append(toWK(adopt(JSValueToStringCopy(context, intermediateCACertificateBase64Value, 0)).get()));
+ }
+
Vector<WKStringRef> rawLocalKeys;
Vector<WKTypeRef> rawLocalValues;
rawLocalKeys.resize(localKeys.size());