forked from mirrors/gecko-dev
135 lines
3.7 KiB
JavaScript
135 lines
3.7 KiB
JavaScript
/* 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";
|
|
|
|
ChromeUtils.defineESModuleGetters(this, {
|
|
TelemetryTestUtils: "resource://testing-common/TelemetryTestUtils.sys.mjs",
|
|
});
|
|
|
|
const TEST_URL = "https://example.com/";
|
|
|
|
add_virtual_authenticator();
|
|
|
|
function getTelemetryForScalar(aName) {
|
|
let scalars = TelemetryTestUtils.getProcessScalars("parent", true);
|
|
return scalars[aName] || 0;
|
|
}
|
|
|
|
function cleanupTelemetry() {
|
|
Services.telemetry.clearScalars();
|
|
Services.telemetry.clearEvents();
|
|
}
|
|
|
|
function validateHistogramEntryCount(aHistogramName, aExpectedCount) {
|
|
let hist = Services.telemetry.getHistogramById(aHistogramName);
|
|
let resultIndexes = hist.snapshot();
|
|
|
|
let entriesSeen = Object.values(resultIndexes.values).reduce(
|
|
(a, b) => a + b,
|
|
0
|
|
);
|
|
|
|
is(
|
|
entriesSeen,
|
|
aExpectedCount,
|
|
"Expecting " + aExpectedCount + " histogram entries in " + aHistogramName
|
|
);
|
|
}
|
|
|
|
add_task(async function test_setup() {
|
|
cleanupTelemetry();
|
|
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [
|
|
["security.webauth.webauthn", true],
|
|
["security.webauth.webauthn_enable_softtoken", true],
|
|
["security.webauth.webauthn_enable_usbtoken", false],
|
|
["security.webauth.webauthn_testing_allow_direct_attestation", true],
|
|
],
|
|
});
|
|
});
|
|
|
|
add_task(async function test() {
|
|
// These tests can't run simultaneously as the preference changes will race.
|
|
// So let's run them sequentially here, but in an async function so we can
|
|
// use await.
|
|
|
|
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
|
|
|
|
// Create a new credential.
|
|
let { attObj, rawId } = await promiseWebAuthnMakeCredential(tab);
|
|
let { authDataObj } = await webAuthnDecodeCBORAttestation(attObj);
|
|
|
|
// Make sure the RP ID hash matches what we calculate.
|
|
await checkRpIdHash(authDataObj.rpIdHash, "example.com");
|
|
|
|
// Get a new assertion.
|
|
let { clientDataJSON, authenticatorData, signature } =
|
|
await promiseWebAuthnGetAssertion(tab, rawId);
|
|
|
|
// Check the we can parse clientDataJSON.
|
|
JSON.parse(buffer2string(clientDataJSON));
|
|
|
|
// Check auth data.
|
|
let attestation = await webAuthnDecodeAuthDataArray(
|
|
new Uint8Array(authenticatorData)
|
|
);
|
|
is(
|
|
"" + (attestation.flags & flag_TUP),
|
|
"" + flag_TUP,
|
|
"Assertion's user presence byte set correctly"
|
|
);
|
|
|
|
// Verify the signature.
|
|
let params = await deriveAppAndChallengeParam(
|
|
"example.com",
|
|
clientDataJSON,
|
|
attestation
|
|
);
|
|
let signedData = await assembleSignedData(
|
|
params.appParam,
|
|
params.attestation.flags,
|
|
params.attestation.counter,
|
|
params.challengeParam
|
|
);
|
|
let valid = await verifySignature(
|
|
authDataObj.publicKeyHandle,
|
|
signedData,
|
|
signature
|
|
);
|
|
ok(valid, "signature is valid");
|
|
|
|
// Check telemetry data.
|
|
let webauthn_used = getTelemetryForScalar("security.webauthn_used");
|
|
ok(
|
|
webauthn_used,
|
|
"Scalar keys are set: " + Object.keys(webauthn_used).join(", ")
|
|
);
|
|
is(
|
|
webauthn_used.CTAPRegisterFinish,
|
|
1,
|
|
"webauthn_used CTAPRegisterFinish scalar should be 1"
|
|
);
|
|
is(
|
|
webauthn_used.CTAPSignFinish,
|
|
1,
|
|
"webauthn_used CTAPSignFinish scalar should be 1"
|
|
);
|
|
is(
|
|
webauthn_used.CTAPSignAbort,
|
|
undefined,
|
|
"webauthn_used CTAPSignAbort scalar must be unset"
|
|
);
|
|
is(
|
|
webauthn_used.CTAPRegisterAbort,
|
|
undefined,
|
|
"webauthn_used CTAPRegisterAbort scalar must be unset"
|
|
);
|
|
|
|
BrowserTestUtils.removeTab(tab);
|
|
|
|
// There aren't tests for register succeeding and sign failing, as I don't see an easy way to prompt
|
|
// the soft token to fail that way _and_ trigger the Abort telemetry.
|
|
});
|