summaryrefslogtreecommitdiffstats
path: root/dom/webauthn/tests/browser/head.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/webauthn/tests/browser/head.js')
-rw-r--r--dom/webauthn/tests/browser/head.js259
1 files changed, 259 insertions, 0 deletions
diff --git a/dom/webauthn/tests/browser/head.js b/dom/webauthn/tests/browser/head.js
new file mode 100644
index 0000000000..d6cbd56133
--- /dev/null
+++ b/dom/webauthn/tests/browser/head.js
@@ -0,0 +1,259 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+let exports = this;
+
+const scripts = [
+ "pkijs/common.js",
+ "pkijs/asn1.js",
+ "pkijs/x509_schema.js",
+ "pkijs/x509_simpl.js",
+ "browser/cbor.js",
+ "browser/u2futil.js",
+];
+
+for (let script of scripts) {
+ Services.scriptloader.loadSubScript(
+ `chrome://mochitests/content/browser/dom/webauthn/tests/${script}`,
+ this
+ );
+}
+
+function add_virtual_authenticator(autoremove = true) {
+ let webauthnService = Cc["@mozilla.org/webauthn/service;1"].getService(
+ Ci.nsIWebAuthnService
+ );
+ let id = webauthnService.addVirtualAuthenticator(
+ "ctap2_1",
+ "internal",
+ true,
+ true,
+ true,
+ true
+ );
+ if (autoremove) {
+ registerCleanupFunction(() => {
+ webauthnService.removeVirtualAuthenticator(id);
+ });
+ }
+ return id;
+}
+
+async function addCredential(authenticatorId, rpId) {
+ let keyPair = await crypto.subtle.generateKey(
+ {
+ name: "ECDSA",
+ namedCurve: "P-256",
+ },
+ true,
+ ["sign"]
+ );
+
+ let credId = new Uint8Array(32);
+ crypto.getRandomValues(credId);
+ credId = bytesToBase64UrlSafe(credId);
+
+ let privateKey = await crypto.subtle
+ .exportKey("pkcs8", keyPair.privateKey)
+ .then(privateKey => bytesToBase64UrlSafe(privateKey));
+
+ let webauthnService = Cc["@mozilla.org/webauthn/service;1"].getService(
+ Ci.nsIWebAuthnService
+ );
+
+ webauthnService.addCredential(
+ authenticatorId,
+ credId,
+ true, // resident key
+ rpId,
+ privateKey,
+ "VGVzdCBVc2Vy", // "Test User"
+ 0 // sign count
+ );
+
+ return credId;
+}
+
+async function removeCredential(authenticatorId, credId) {
+ let webauthnService = Cc["@mozilla.org/webauthn/service;1"].getService(
+ Ci.nsIWebAuthnService
+ );
+
+ webauthnService.removeCredential(authenticatorId, credId);
+}
+
+function memcmp(x, y) {
+ let xb = new Uint8Array(x);
+ let yb = new Uint8Array(y);
+
+ if (x.byteLength != y.byteLength) {
+ return false;
+ }
+
+ for (let i = 0; i < xb.byteLength; ++i) {
+ if (xb[i] != yb[i]) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+function arrivingHereIsBad(aResult) {
+ ok(false, "Bad result! Received a: " + aResult);
+}
+
+function expectError(aType) {
+ let expected = `${aType}Error`;
+ return function (aResult) {
+ is(
+ aResult.slice(0, expected.length),
+ expected,
+ `Expecting a ${aType}Error`
+ );
+ };
+}
+
+/* eslint-disable no-shadow */
+function promiseWebAuthnMakeCredential(
+ tab,
+ attestation = "none",
+ residentKey = "discouraged",
+ extensions = {}
+) {
+ return ContentTask.spawn(
+ tab.linkedBrowser,
+ [attestation, residentKey, extensions],
+ ([attestation, residentKey, extensions]) => {
+ const cose_alg_ECDSA_w_SHA256 = -7;
+
+ let challenge = content.crypto.getRandomValues(new Uint8Array(16));
+
+ let pubKeyCredParams = [
+ {
+ type: "public-key",
+ alg: cose_alg_ECDSA_w_SHA256,
+ },
+ ];
+
+ let publicKey = {
+ rp: { id: content.document.domain, name: "none" },
+ user: {
+ id: new Uint8Array(),
+ name: "none",
+ displayName: "none",
+ },
+ pubKeyCredParams,
+ authenticatorSelection: {
+ authenticatorAttachment: "cross-platform",
+ residentKey,
+ },
+ extensions,
+ attestation,
+ challenge,
+ };
+
+ return content.navigator.credentials
+ .create({ publicKey })
+ .then(credential => {
+ return {
+ clientDataJSON: credential.response.clientDataJSON,
+ attObj: credential.response.attestationObject,
+ rawId: credential.rawId,
+ };
+ });
+ }
+ );
+}
+
+function promiseWebAuthnGetAssertion(tab, key_handle = null, extensions = {}) {
+ return ContentTask.spawn(
+ tab.linkedBrowser,
+ [key_handle, extensions],
+ ([key_handle, extensions]) => {
+ let challenge = content.crypto.getRandomValues(new Uint8Array(16));
+ if (key_handle == null) {
+ key_handle = content.crypto.getRandomValues(new Uint8Array(16));
+ }
+
+ let credential = {
+ id: key_handle,
+ type: "public-key",
+ transports: ["usb"],
+ };
+
+ let publicKey = {
+ challenge,
+ extensions,
+ rpId: content.document.domain,
+ allowCredentials: [credential],
+ };
+
+ return content.navigator.credentials
+ .get({ publicKey })
+ .then(assertion => {
+ return {
+ authenticatorData: assertion.response.authenticatorData,
+ clientDataJSON: assertion.response.clientDataJSON,
+ extensions: assertion.getClientExtensionResults(),
+ signature: assertion.response.signature,
+ };
+ });
+ }
+ );
+}
+
+function promiseWebAuthnGetAssertionDiscoverable(
+ tab,
+ mediation = "optional",
+ extensions = {}
+) {
+ return ContentTask.spawn(
+ tab.linkedBrowser,
+ [extensions, mediation],
+ ([extensions, mediation]) => {
+ let challenge = content.crypto.getRandomValues(new Uint8Array(16));
+
+ let publicKey = {
+ challenge,
+ extensions,
+ rpId: content.document.domain,
+ allowCredentials: [],
+ };
+
+ return content.navigator.credentials.get({ publicKey, mediation });
+ }
+ );
+}
+
+function checkRpIdHash(rpIdHash, hostname) {
+ return crypto.subtle
+ .digest("SHA-256", string2buffer(hostname))
+ .then(calculatedRpIdHash => {
+ let calcHashStr = bytesToBase64UrlSafe(
+ new Uint8Array(calculatedRpIdHash)
+ );
+ let providedHashStr = bytesToBase64UrlSafe(new Uint8Array(rpIdHash));
+
+ if (calcHashStr != providedHashStr) {
+ throw new Error("Calculated RP ID hash doesn't match.");
+ }
+ });
+}
+
+function promiseNotification(id) {
+ return new Promise(resolve => {
+ PopupNotifications.panel.addEventListener("popupshown", function shown() {
+ let notification = PopupNotifications.getNotification(id);
+ if (notification) {
+ ok(true, `${id} prompt visible`);
+ PopupNotifications.panel.removeEventListener("popupshown", shown);
+ resolve();
+ }
+ });
+ });
+}
+/* eslint-enable no-shadow */