deleted file mode 100644
--- a/dom/u2f/U2F.cpp
+++ /dev/null
@@ -1,1069 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* 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/. */
-
-#include "hasht.h"
-#include "mozilla/dom/CallbackFunction.h"
-#include "mozilla/dom/ContentChild.h"
-#include "mozilla/dom/CryptoBuffer.h"
-#include "mozilla/dom/NSSU2FTokenRemote.h"
-#include "mozilla/dom/U2F.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/ReentrantMonitor.h"
-#include "nsContentUtils.h"
-#include "nsINSSU2FToken.h"
-#include "nsNetCID.h"
-#include "nsNSSComponent.h"
-#include "nsThreadUtils.h"
-#include "nsURLParsers.h"
-#include "nsXPCOMCIDInternal.h"
-#include "pk11pub.h"
-
-using mozilla::dom::ContentChild;
-
-namespace mozilla {
-namespace dom {
-
-#define PREF_U2F_SOFTTOKEN_ENABLED "security.webauth.u2f_enable_softtoken"
-#define PREF_U2F_USBTOKEN_ENABLED "security.webauth.u2f_enable_usbtoken"
-
-NS_NAMED_LITERAL_CSTRING(kPoolName, "WebAuth_U2F-IO");
-NS_NAMED_LITERAL_STRING(kFinishEnrollment, "navigator.id.finishEnrollment");
-NS_NAMED_LITERAL_STRING(kGetAssertion, "navigator.id.getAssertion");
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(U2F)
- NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
- NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(U2F)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(U2F)
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(U2F, mParent)
-
-static mozilla::LazyLogModule gU2FLog("u2f");
-
-static nsresult
-AssembleClientData(const nsAString& aOrigin, const nsAString& aTyp,
- const nsAString& aChallenge, CryptoBuffer& aClientData)
-{
- MOZ_ASSERT(NS_IsMainThread());
- U2FClientData clientDataObject;
- clientDataObject.mTyp.Construct(aTyp); // "Typ" from the U2F specification
- clientDataObject.mChallenge.Construct(aChallenge);
- clientDataObject.mOrigin.Construct(aOrigin);
-
- nsAutoString json;
- if (NS_WARN_IF(!clientDataObject.ToJSON(json))) {
- return NS_ERROR_FAILURE;
- }
-
- if (NS_WARN_IF(!aClientData.Assign(NS_ConvertUTF16toUTF8(json)))) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- return NS_OK;
-}
-
-U2FStatus::U2FStatus()
- : mCount(0)
- , mIsStopped(false)
- , mReentrantMonitor("U2FStatus")
-{}
-
-U2FStatus::~U2FStatus()
-{}
-
-void
-U2FStatus::WaitGroupAdd()
-{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
- mCount += 1;
- MOZ_LOG(gU2FLog, LogLevel::Debug,
- ("U2FStatus::WaitGroupAdd, now %d", mCount));
-}
-
-void
-U2FStatus::WaitGroupDone()
-{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
- MOZ_ASSERT(mCount > 0);
- mCount -= 1;
- MOZ_LOG(gU2FLog, LogLevel::Debug,
- ("U2FStatus::WaitGroupDone, now %d", mCount));
- if (mCount == 0) {
- mReentrantMonitor.NotifyAll();
- }
-}
-
-void
-U2FStatus::WaitGroupWait()
-{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
- MOZ_LOG(gU2FLog, LogLevel::Debug,
- ("U2FStatus::WaitGroupWait, now %d", mCount));
-
- while (mCount > 0) {
- mReentrantMonitor.Wait();
- }
-
- MOZ_ASSERT(mCount == 0);
- MOZ_LOG(gU2FLog, LogLevel::Debug,
- ("U2FStatus::Wait completed, now count=%d stopped=%d", mCount,
- mIsStopped));
-}
-
-void
-U2FStatus::Stop(const ErrorCode aErrorCode)
-{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
- MOZ_ASSERT(!mIsStopped);
- mIsStopped = true;
- mErrorCode = aErrorCode;
-
- // TODO: Let WaitGroupWait exit early upon a Stop. Requires consideration of
- // threads calling IsStopped() followed by WaitGroupDone(). Right now, Stop
- // prompts work tasks to end early, but it could also prompt an immediate
- // "Go ahead" to the thread waiting at WaitGroupWait.
-}
-
-void
-U2FStatus::Stop(const ErrorCode aErrorCode, const nsAString& aResponse)
-{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
- Stop(aErrorCode);
- mResponse = aResponse;
-}
-
-bool
-U2FStatus::IsStopped()
-{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
- return mIsStopped;
-}
-
-ErrorCode
-U2FStatus::GetErrorCode()
-{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
- MOZ_ASSERT(mIsStopped);
- return mErrorCode;
-}
-
-nsString
-U2FStatus::GetResponse()
-{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
- MOZ_ASSERT(mIsStopped);
- return mResponse;
-}
-
-U2FTask::U2FTask(const nsAString& aOrigin,
- const nsAString& aAppId,
- const Authenticator& aAuthenticator,
- nsISerialEventTarget* aEventTarget)
- : Runnable("dom::U2FTask")
- , mOrigin(aOrigin)
- , mAppId(aAppId)
- , mAuthenticator(aAuthenticator)
- , mEventTarget(aEventTarget)
-{}
-
-U2FTask::~U2FTask()
-{}
-
-RefPtr<U2FPromise>
-U2FTask::Execute()
-{
- RefPtr<U2FPromise> p = mPromise.Ensure(__func__);
-
- nsCOMPtr<nsIRunnable> r(this);
-
- // TODO: Use a thread pool here, but we have to solve the PContentChild issues
- // of being in a worker thread.
- mEventTarget->Dispatch(r.forget());
- return p;
-}
-
-U2FPrepTask::U2FPrepTask(const Authenticator& aAuthenticator,
- nsISerialEventTarget* aEventTarget)
- : Runnable("dom::U2FPrepTask")
- , mAuthenticator(aAuthenticator)
- , mEventTarget(aEventTarget)
-{}
-
-U2FPrepTask::~U2FPrepTask()
-{}
-
-RefPtr<U2FPrepPromise>
-U2FPrepTask::Execute()
-{
- RefPtr<U2FPrepPromise> p = mPromise.Ensure(__func__);
-
- nsCOMPtr<nsIRunnable> r(this);
-
- // TODO: Use a thread pool here, but we have to solve the PContentChild issues
- // of being in a worker thread.
- mEventTarget->Dispatch(r.forget());
- return p;
-}
-
-U2FIsRegisteredTask::U2FIsRegisteredTask(const Authenticator& aAuthenticator,
- const LocalRegisteredKey& aRegisteredKey,
- const CryptoBuffer& aAppParam,
- nsISerialEventTarget* aEventTarget)
- : U2FPrepTask(aAuthenticator, aEventTarget)
- , mRegisteredKey(aRegisteredKey)
- , mAppParam(aAppParam)
-{}
-
-U2FIsRegisteredTask::~U2FIsRegisteredTask()
-{}
-
-NS_IMETHODIMP
-U2FIsRegisteredTask::Run()
-{
- bool isCompatible = false;
- nsresult rv = mAuthenticator->IsCompatibleVersion(mRegisteredKey.mVersion,
- &isCompatible);
- if (NS_FAILED(rv)) {
- mPromise.Reject(ErrorCode::OTHER_ERROR, __func__);
- return NS_ERROR_FAILURE;
- }
-
- if (!isCompatible) {
- mPromise.Reject(ErrorCode::BAD_REQUEST, __func__);
- return NS_ERROR_FAILURE;
- }
-
- // Decode the key handle
- CryptoBuffer keyHandle;
- rv = keyHandle.FromJwkBase64(mRegisteredKey.mKeyHandle);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- mPromise.Reject(ErrorCode::BAD_REQUEST, __func__);
- return NS_ERROR_FAILURE;
- }
-
- // We ignore mTransports, as it is intended to be used for sorting the
- // available devices by preference, but is not an exclusion factor.
-
- bool isRegistered = false;
- rv = mAuthenticator->IsRegistered(keyHandle.Elements(), keyHandle.Length(),
- mAppParam.Elements(), mAppParam.Length(),
- &isRegistered);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- mPromise.Reject(ErrorCode::OTHER_ERROR, __func__);
- return NS_ERROR_FAILURE;
- }
-
- if (isRegistered) {
- mPromise.Reject(ErrorCode::DEVICE_INELIGIBLE, __func__);
- return NS_OK;
- }
-
- mPromise.Resolve(mAuthenticator, __func__);
- return NS_OK;
-}
-
-U2FRegisterTask::U2FRegisterTask(const nsAString& aOrigin,
- const nsAString& aAppId,
- const Authenticator& aAuthenticator,
- const CryptoBuffer& aAppParam,
- const CryptoBuffer& aChallengeParam,
- const LocalRegisterRequest& aRegisterEntry,
- nsISerialEventTarget* aEventTarget)
- : U2FTask(aOrigin, aAppId, aAuthenticator, aEventTarget)
- , mAppParam(aAppParam)
- , mChallengeParam(aChallengeParam)
- , mRegisterEntry(aRegisterEntry)
-{}
-
-U2FRegisterTask::~U2FRegisterTask()
-{}
-
-NS_IMETHODIMP
-U2FRegisterTask::Run()
-{
- bool isCompatible = false;
- nsresult rv = mAuthenticator->IsCompatibleVersion(mRegisterEntry.mVersion,
- &isCompatible);
- if (NS_FAILED(rv)) {
- mPromise.Reject(ErrorCode::OTHER_ERROR, __func__);
- return NS_ERROR_FAILURE;
- }
-
- if (!isCompatible) {
- mPromise.Reject(ErrorCode::BAD_REQUEST, __func__);
- return NS_ERROR_FAILURE;
- }
-
- uint8_t* buffer;
- uint32_t bufferlen;
- rv = mAuthenticator->Register(mAppParam.Elements(),
- mAppParam.Length(),
- mChallengeParam.Elements(),
- mChallengeParam.Length(),
- &buffer, &bufferlen);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- mPromise.Reject(ErrorCode::OTHER_ERROR, __func__);
- return NS_ERROR_FAILURE;
- }
-
- MOZ_ASSERT(buffer);
- CryptoBuffer regData;
- if (NS_WARN_IF(!regData.Assign(buffer, bufferlen))) {
- free(buffer);
- mPromise.Reject(ErrorCode::OTHER_ERROR, __func__);
- return NS_ERROR_OUT_OF_MEMORY;
- }
- free(buffer);
-
- // Assemble a response object to return
- nsString clientDataBase64;
- nsString registrationDataBase64;
- nsresult rvClientData = mRegisterEntry.mClientData.ToJwkBase64(clientDataBase64);
- nsresult rvRegistrationData = regData.ToJwkBase64(registrationDataBase64);
-
- if (NS_WARN_IF(NS_FAILED(rvClientData)) ||
- NS_WARN_IF(NS_FAILED(rvRegistrationData))) {
- mPromise.Reject(ErrorCode::OTHER_ERROR, __func__);
- return NS_ERROR_FAILURE;
- }
-
- RegisterResponse response;
- response.mClientData.Construct(clientDataBase64);
- response.mRegistrationData.Construct(registrationDataBase64);
- response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::OK));
-
- nsString responseStr;
- if (NS_WARN_IF(!response.ToJSON(responseStr))) {
- return NS_ERROR_FAILURE;
- }
- mPromise.Resolve(responseStr, __func__);
- return NS_OK;
-}
-
-U2FSignTask::U2FSignTask(const nsAString& aOrigin,
- const nsAString& aAppId,
- const nsAString& aVersion,
- const Authenticator& aAuthenticator,
- const CryptoBuffer& aAppParam,
- const CryptoBuffer& aChallengeParam,
- const CryptoBuffer& aClientData,
- const CryptoBuffer& aKeyHandle,
- nsISerialEventTarget* aEventTarget)
- : U2FTask(aOrigin, aAppId, aAuthenticator, aEventTarget)
- , mVersion(aVersion)
- , mAppParam(aAppParam)
- , mChallengeParam(aChallengeParam)
- , mClientData(aClientData)
- , mKeyHandle(aKeyHandle)
-{}
-
-U2FSignTask::~U2FSignTask()
-{}
-
-NS_IMETHODIMP
-U2FSignTask::Run()
-{
- bool isCompatible = false;
- nsresult rv = mAuthenticator->IsCompatibleVersion(mVersion, &isCompatible);
- if (NS_FAILED(rv)) {
- mPromise.Reject(ErrorCode::OTHER_ERROR, __func__);
- return NS_ERROR_FAILURE;
- }
-
- if (!isCompatible) {
- mPromise.Reject(ErrorCode::BAD_REQUEST, __func__);
- return NS_ERROR_FAILURE;
- }
-
- bool isRegistered = false;
- rv = mAuthenticator->IsRegistered(mKeyHandle.Elements(), mKeyHandle.Length(),
- mAppParam.Elements(), mAppParam.Length(),
- &isRegistered);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- mPromise.Reject(ErrorCode::OTHER_ERROR, __func__);
- return NS_ERROR_FAILURE;
- }
-
- if (!isRegistered) {
- mPromise.Reject(ErrorCode::DEVICE_INELIGIBLE, __func__);
- return NS_OK;
- }
-
- CryptoBuffer signatureData;
- uint8_t* buffer;
- uint32_t bufferlen;
- rv = mAuthenticator->Sign(mAppParam.Elements(), mAppParam.Length(),
- mChallengeParam.Elements(), mChallengeParam.Length(),
- mKeyHandle.Elements(), mKeyHandle.Length(),
- &buffer, &bufferlen);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- mPromise.Reject(ErrorCode::OTHER_ERROR, __func__);
- return NS_ERROR_FAILURE;
- }
-
- MOZ_ASSERT(buffer);
- if (NS_WARN_IF(!signatureData.Assign(buffer, bufferlen))) {
- free(buffer);
- mPromise.Reject(ErrorCode::OTHER_ERROR, __func__);
- return NS_ERROR_OUT_OF_MEMORY;
- }
- free(buffer);
-
- // Assemble a response object to return
- nsString clientDataBase64;
- nsString signatureDataBase64;
- nsString keyHandleBase64;
- nsresult rvClientData = mClientData.ToJwkBase64(clientDataBase64);
- nsresult rvSignatureData = signatureData.ToJwkBase64(signatureDataBase64);
- nsresult rvKeyHandle = mKeyHandle.ToJwkBase64(keyHandleBase64);
- if (NS_WARN_IF(NS_FAILED(rvClientData)) ||
- NS_WARN_IF(NS_FAILED(rvSignatureData) ||
- NS_WARN_IF(NS_FAILED(rvKeyHandle)))) {
- mPromise.Reject(ErrorCode::OTHER_ERROR, __func__);
- return NS_ERROR_FAILURE;
- }
-
- SignResponse response;
- response.mKeyHandle.Construct(keyHandleBase64);
- response.mClientData.Construct(clientDataBase64);
- response.mSignatureData.Construct(signatureDataBase64);
- response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::OK));
-
- nsString responseStr;
- if (NS_WARN_IF(!response.ToJSON(responseStr))) {
- return NS_ERROR_FAILURE;
- }
- mPromise.Resolve(responseStr, __func__);
- return NS_OK;
-}
-
-U2FRunnable::U2FRunnable(const nsAString& aOrigin, const nsAString& aAppId,
- nsISerialEventTarget* aEventTarget)
- : Runnable("dom::U2FRunnable")
- , mOrigin(aOrigin)
- , mAppId(aAppId)
- , mEventTarget(aEventTarget)
-{}
-
-U2FRunnable::~U2FRunnable()
-{}
-
-// EvaluateAppIDAndRunTask determines whether the supplied FIDO AppID is valid for
-// the current FacetID, e.g., the current origin.
-// See https://fidoalliance.org/specs/fido-u2f-v1.0-nfc-bt-amendment-20150514/fido-appid-and-facets.html
-// for a description of the algorithm.
-ErrorCode
-U2FRunnable::EvaluateAppID()
-{
- nsCOMPtr<nsIURLParser> urlParser =
- do_GetService(NS_STDURLPARSER_CONTRACTID);
-
- MOZ_ASSERT(urlParser);
-
- uint32_t facetSchemePos;
- int32_t facetSchemeLen;
- uint32_t facetAuthPos;
- int32_t facetAuthLen;
- // Facet is the specification's way of referring to the web origin.
- nsAutoCString facetUrl = NS_ConvertUTF16toUTF8(mOrigin);
- nsresult rv = urlParser->ParseURL(facetUrl.get(), mOrigin.Length(),
- &facetSchemePos, &facetSchemeLen,
- &facetAuthPos, &facetAuthLen,
- nullptr, nullptr); // ignore path
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return ErrorCode::BAD_REQUEST;
- }
-
- nsAutoCString facetScheme(Substring(facetUrl, facetSchemePos, facetSchemeLen));
- nsAutoCString facetAuth(Substring(facetUrl, facetAuthPos, facetAuthLen));
-
- uint32_t appIdSchemePos;
- int32_t appIdSchemeLen;
- uint32_t appIdAuthPos;
- int32_t appIdAuthLen;
- // AppID is user-supplied. It's quite possible for this parse to fail.
- nsAutoCString appIdUrl = NS_ConvertUTF16toUTF8(mAppId);
- rv = urlParser->ParseURL(appIdUrl.get(), mAppId.Length(),
- &appIdSchemePos, &appIdSchemeLen,
- &appIdAuthPos, &appIdAuthLen,
- nullptr, nullptr); // ignore path
- if (NS_FAILED(rv)) {
- return ErrorCode::BAD_REQUEST;
- }
-
- nsAutoCString appIdScheme(Substring(appIdUrl, appIdSchemePos, appIdSchemeLen));
- nsAutoCString appIdAuth(Substring(appIdUrl, appIdAuthPos, appIdAuthLen));
-
- // If the facetId (origin) is not HTTPS, reject
- if (!facetScheme.LowerCaseEqualsLiteral("https")) {
- return ErrorCode::BAD_REQUEST;
- }
-
- // If the appId is empty or null, overwrite it with the facetId and accept
- if (mAppId.IsEmpty() || mAppId.EqualsLiteral("null")) {
- mAppId.Assign(mOrigin);
- return ErrorCode::OK;
- }
-
- // if the appId URL is not HTTPS, reject.
- if (!appIdScheme.LowerCaseEqualsLiteral("https")) {
- return ErrorCode::BAD_REQUEST;
- }
-
- // If the facetId and the appId auths match, accept
- if (facetAuth == appIdAuth) {
- return ErrorCode::OK;
- }
-
- // TODO(Bug 1244959) Implement the remaining algorithm.
- return ErrorCode::BAD_REQUEST;
-}
-
-U2FRegisterRunnable::U2FRegisterRunnable(const nsAString& aOrigin,
- const nsAString& aAppId,
- const Sequence<RegisterRequest>& aRegisterRequests,
- const Sequence<RegisteredKey>& aRegisteredKeys,
- const Sequence<Authenticator>& aAuthenticators,
- U2FRegisterCallback* aCallback,
- nsISerialEventTarget* aEventTarget)
- : U2FRunnable(aOrigin, aAppId, aEventTarget)
- , mAuthenticators(aAuthenticators)
- // U2FRegisterCallback does not support threadsafe refcounting, and must be
- // used and destroyed on main.
- , mCallback(new nsMainThreadPtrHolder<U2FRegisterCallback>(
- "U2FRegisterRunnable::mCallback", aCallback))
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- // The WebIDL dictionary types RegisterRequest and RegisteredKey cannot
- // be copied to this thread, so store them serialized.
- for (const RegisterRequest& req : aRegisterRequests) {
- // Check for required attributes
- if (!req.mChallenge.WasPassed() || !req.mVersion.WasPassed()) {
- continue;
- }
-
- LocalRegisterRequest localReq;
- localReq.mVersion = req.mVersion.Value();
- localReq.mChallenge = req.mChallenge.Value();
-
- nsresult rv = AssembleClientData(mOrigin, kFinishEnrollment,
- localReq.mChallenge, localReq.mClientData);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- continue;
- }
-
- mRegisterRequests.AppendElement(localReq);
- }
-
- for (const RegisteredKey& key : aRegisteredKeys) {
- // Check for required attributes
- if (!key.mVersion.WasPassed() || !key.mKeyHandle.WasPassed()) {
- continue;
- }
-
- LocalRegisteredKey localKey;
- localKey.mVersion = key.mVersion.Value();
- localKey.mKeyHandle = key.mKeyHandle.Value();
- if (key.mAppId.WasPassed()) {
- localKey.mAppId.SetValue(key.mAppId.Value());
- }
-
- mRegisteredKeys.AppendElement(localKey);
- }
-}
-
-U2FRegisterRunnable::~U2FRegisterRunnable()
-{
- nsNSSShutDownPreventionLock locker;
-
- if (isAlreadyShutDown()) {
- return;
- }
- shutdown(ShutdownCalledFrom::Object);
-}
-
-void
-U2FRegisterRunnable::SetTimeout(const int32_t aTimeoutMillis)
-{
- opt_mTimeoutSeconds.SetValue(aTimeoutMillis);
-}
-
-void
-U2FRegisterRunnable::SendResponse(const RegisterResponse& aResponse)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- ErrorResult rv;
- mCallback->Call(aResponse, rv);
- NS_WARNING_ASSERTION(!rv.Failed(), "callback failed");
- // Useful exceptions already got reported.
- rv.SuppressException();
-}
-
-NS_IMETHODIMP
-U2FRegisterRunnable::Run()
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown()) {
- return NS_ERROR_FAILURE;
- }
-
- // Create a Status object to keep track of when we're done
- RefPtr<U2FStatus> status = new U2FStatus();
-
- // Evaluate the AppID
- ErrorCode appIdResult = EvaluateAppID();
- if (appIdResult != ErrorCode::OK) {
- status->Stop(appIdResult);
- }
-
- // Produce the AppParam from the current AppID
- nsCString cAppId = NS_ConvertUTF16toUTF8(mAppId);
- CryptoBuffer appParam;
- if (!appParam.SetLength(SHA256_LENGTH, fallible)) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- // Note: This could use nsICryptoHash to avoid having to interact with NSS
- // directly.
- SECStatus srv;
- srv = PK11_HashBuf(SEC_OID_SHA256, appParam.Elements(),
- reinterpret_cast<const uint8_t*>(cAppId.BeginReading()),
- cAppId.Length());
- if (srv != SECSuccess) {
- return NS_ERROR_FAILURE;
- }
-
- // First, we must determine if any of the RegisteredKeys are already
- // registered, e.g., in the whitelist.
- for (LocalRegisteredKey key : mRegisteredKeys) {
- nsTArray<RefPtr<U2FPrepPromise>> prepPromiseList;
- for (const Authenticator& token : mAuthenticators) {
- RefPtr<U2FIsRegisteredTask> compTask =
- new U2FIsRegisteredTask(token, key, appParam, mEventTarget);
- prepPromiseList.AppendElement(compTask->Execute());
- }
-
- // Treat each call to Promise::All as a work unit, as it completes together
- status->WaitGroupAdd();
-
- U2FPrepPromise::All(mEventTarget, prepPromiseList)
- ->Then(mEventTarget, __func__,
- [&status] (const nsTArray<Authenticator>& aTokens) {
- MOZ_LOG(gU2FLog, LogLevel::Debug,
- ("ALL: None of the RegisteredKeys were recognized. n=%zu",
- aTokens.Length()));
-
- status->WaitGroupDone();
- },
- [&status] (ErrorCode aErrorCode) {
- status->Stop(aErrorCode);
- status->WaitGroupDone();
- });
- }
-
- // Wait for all the IsRegistered tasks to complete
- status->WaitGroupWait();
-
- // Check to see whether we're supposed to stop, because one of the keys was
- // recognized.
- if (status->IsStopped()) {
- status->WaitGroupAdd();
- mEventTarget->Dispatch(NS_NewRunnableFunction(
- "dom::U2FRegisterRunnable::Run",
- [&status, this] () {
- RegisterResponse response;
- response.mErrorCode.Construct(
- static_cast<uint32_t>(status->GetErrorCode()));
- SendResponse(response);
- status->WaitGroupDone();
- }));
-
- // Don't exit until the main thread runnable completes
- status->WaitGroupWait();
- return NS_OK;
- }
-
- // Now proceed to actually register a new key.
- for (LocalRegisterRequest req : mRegisterRequests) {
- // Hash the ClientData into the ChallengeParam
- CryptoBuffer challengeParam;
- if (!challengeParam.SetLength(SHA256_LENGTH, fallible)) {
- continue;
- }
-
- srv = PK11_HashBuf(SEC_OID_SHA256, challengeParam.Elements(),
- req.mClientData.Elements(), req.mClientData.Length());
- if (srv != SECSuccess) {
- continue;
- }
-
- for (const Authenticator& token : mAuthenticators) {
- RefPtr<U2FRegisterTask> registerTask = new U2FRegisterTask(mOrigin, mAppId,
- token, appParam,
- challengeParam,
- req,
- mEventTarget);
- status->WaitGroupAdd();
-
- registerTask->Execute()->Then(mEventTarget, __func__,
- [&status] (nsString aResponse) {
- if (!status->IsStopped()) {
- status->Stop(ErrorCode::OK, aResponse);
- }
- status->WaitGroupDone();
- },
- [&status] (ErrorCode aErrorCode) {
- // Ignore the failing error code, as we only want the first success.
- // U2F devices don't provide much for error codes anyway, so if
- // they all fail we'll return DEVICE_INELIGIBLE.
- status->WaitGroupDone();
- });
- }
- }
-
- // Wait until the first key is successfuly generated
- status->WaitGroupWait();
-
- // If none of the tasks completed, then nothing could satisfy.
- if (!status->IsStopped()) {
- status->Stop(ErrorCode::BAD_REQUEST);
- }
-
- // Transmit back to the JS engine from the Main Thread
- status->WaitGroupAdd();
- mEventTarget->Dispatch(NS_NewRunnableFunction(
- "dom::U2FRegisterRunnable::Run",
- [&status, this] () {
- RegisterResponse response;
- if (status->GetErrorCode() == ErrorCode::OK) {
- response.Init(status->GetResponse());
- } else {
- response.mErrorCode.Construct(
- static_cast<uint32_t>(status->GetErrorCode()));
- }
- SendResponse(response);
- status->WaitGroupDone();
- }));
-
- // TODO: Add timeouts, Bug 1301793
- status->WaitGroupWait();
- return NS_OK;
-}
-
-U2FSignRunnable::U2FSignRunnable(const nsAString& aOrigin,
- const nsAString& aAppId,
- const nsAString& aChallenge,
- const Sequence<RegisteredKey>& aRegisteredKeys,
- const Sequence<Authenticator>& aAuthenticators,
- U2FSignCallback* aCallback,
- nsISerialEventTarget* aEventTarget)
- : U2FRunnable(aOrigin, aAppId, aEventTarget)
- , mAuthenticators(aAuthenticators)
- // U2FSignCallback does not support threadsafe refcounting, and must be used
- // and destroyed on main.
- , mCallback(new nsMainThreadPtrHolder<U2FSignCallback>(
- "U2FSignRunnable::mCallback", aCallback))
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- // Convert WebIDL objects to generic structs to pass between threads
- for (const RegisteredKey& key : aRegisteredKeys) {
- // Check for required attributes
- if (!key.mVersion.WasPassed() || !key.mKeyHandle.WasPassed()) {
- continue;
- }
-
- LocalRegisteredKey localKey;
- localKey.mVersion = key.mVersion.Value();
- localKey.mKeyHandle = key.mKeyHandle.Value();
- if (key.mAppId.WasPassed()) {
- localKey.mAppId.SetValue(key.mAppId.Value());
- }
-
- mRegisteredKeys.AppendElement(localKey);
- }
-
- // Assemble a clientData object
- nsresult rv = AssembleClientData(aOrigin, kGetAssertion, aChallenge,
- mClientData);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_LOG(gU2FLog, LogLevel::Warning,
- ("Failed to AssembleClientData for the U2FSignRunnable."));
- return;
- }
-}
-
-U2FSignRunnable::~U2FSignRunnable()
-{
- nsNSSShutDownPreventionLock locker;
-
- if (isAlreadyShutDown()) {
- return;
- }
- shutdown(ShutdownCalledFrom::Object);
-}
-
-void
-U2FSignRunnable::SetTimeout(const int32_t aTimeoutMillis)
-{
- opt_mTimeoutSeconds.SetValue(aTimeoutMillis);
-}
-
-void
-U2FSignRunnable::SendResponse(const SignResponse& aResponse)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- ErrorResult rv;
- mCallback->Call(aResponse, rv);
- NS_WARNING_ASSERTION(!rv.Failed(), "callback failed");
- // Useful exceptions already got reported.
- rv.SuppressException();
-}
-
-NS_IMETHODIMP
-U2FSignRunnable::Run()
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown()) {
- return NS_ERROR_FAILURE;
- }
-
- // Create a Status object to keep track of when we're done
- RefPtr<U2FStatus> status = new U2FStatus();
-
- // Evaluate the AppID
- ErrorCode appIdResult = EvaluateAppID();
- if (appIdResult != ErrorCode::OK) {
- status->Stop(appIdResult);
- }
-
- // Hash the AppID and the ClientData into the AppParam and ChallengeParam
- nsCString cAppId = NS_ConvertUTF16toUTF8(mAppId);
- CryptoBuffer appParam;
- CryptoBuffer challengeParam;
- if (!appParam.SetLength(SHA256_LENGTH, fallible) ||
- !challengeParam.SetLength(SHA256_LENGTH, fallible)) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- SECStatus srv;
- srv = PK11_HashBuf(SEC_OID_SHA256, appParam.Elements(),
- reinterpret_cast<const uint8_t*>(cAppId.BeginReading()),
- cAppId.Length());
- if (srv != SECSuccess) {
- return NS_ERROR_FAILURE;
- }
-
- srv = PK11_HashBuf(SEC_OID_SHA256, challengeParam.Elements(),
- mClientData.Elements(), mClientData.Length());
- if (srv != SECSuccess) {
- return NS_ERROR_FAILURE;
- }
-
- // Search the signing requests for one a token can fulfill
- for (LocalRegisteredKey key : mRegisteredKeys) {
- // Do not permit an individual RegisteredKey to assert a different AppID
- if (!key.mAppId.IsNull() && mAppId != key.mAppId.Value()) {
- continue;
- }
-
- // Decode the key handle
- CryptoBuffer keyHandle;
- nsresult rv = keyHandle.FromJwkBase64(key.mKeyHandle);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- continue;
- }
-
- // We ignore mTransports, as it is intended to be used for sorting the
- // available devices by preference, but is not an exclusion factor.
-
- for (const Authenticator& token : mAuthenticators) {
- RefPtr<U2FSignTask> signTask = new U2FSignTask(mOrigin, mAppId,
- key.mVersion, token,
- appParam, challengeParam,
- mClientData, keyHandle,
- mEventTarget);
- status->WaitGroupAdd();
-
- signTask->Execute()->Then(mEventTarget, __func__,
- [&status] (nsString aResponse) {
- if (!status->IsStopped()) {
- status->Stop(ErrorCode::OK, aResponse);
- }
- status->WaitGroupDone();
- },
- [&status] (ErrorCode aErrorCode) {
- // Ignore the failing error code, as we only want the first success.
- // U2F devices don't provide much for error codes anyway, so if
- // they all fail we'll return DEVICE_INELIGIBLE.
- status->WaitGroupDone();
- });
- }
- }
-
- // Wait for the authenticators to finish
- status->WaitGroupWait();
-
- // If none of the tasks completed, then nothing could satisfy.
- if (!status->IsStopped()) {
- status->Stop(ErrorCode::DEVICE_INELIGIBLE);
- }
-
- // Transmit back to the JS engine from the Main Thread
- status->WaitGroupAdd();
- mEventTarget->Dispatch(NS_NewRunnableFunction(
- "dom::U2FSignRunnable::Run",
- [&status, this] () {
- SignResponse response;
- if (status->GetErrorCode() == ErrorCode::OK) {
- response.Init(status->GetResponse());
- } else {
- response.mErrorCode.Construct(
- static_cast<uint32_t>(status->GetErrorCode()));
- }
- SendResponse(response);
- status->WaitGroupDone();
- }));
-
- // TODO: Add timeouts, Bug 1301793
- status->WaitGroupWait();
- return NS_OK;
-}
-
-U2F::U2F()
- : mInitialized(false)
-{}
-
-U2F::~U2F()
-{
- nsNSSShutDownPreventionLock locker;
-
- if (isAlreadyShutDown()) {
- return;
- }
- shutdown(ShutdownCalledFrom::Object);
-}
-
-/* virtual */ JSObject*
-U2F::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
- return U2FBinding::Wrap(aCx, this, aGivenProto);
-}
-
-void
-U2F::Init(nsPIDOMWindowInner* aParent, ErrorResult& aRv)
-{
- MOZ_ASSERT(!mInitialized);
- MOZ_ASSERT(!mParent);
- mParent = do_QueryInterface(aParent);
- MOZ_ASSERT(mParent);
-
- nsCOMPtr<nsIDocument> doc = mParent->GetDoc();
- MOZ_ASSERT(doc);
-
- nsIPrincipal* principal = doc->NodePrincipal();
- aRv = nsContentUtils::GetUTFOrigin(principal, mOrigin);
- if (NS_WARN_IF(aRv.Failed())) {
- return;
- }
-
- if (NS_WARN_IF(mOrigin.IsEmpty())) {
- aRv.Throw(NS_ERROR_FAILURE);
- return;
- }
-
- if (!EnsureNSSInitializedChromeOrContent()) {
- MOZ_LOG(gU2FLog, LogLevel::Debug,
- ("Failed to get NSS context for U2F"));
- aRv.Throw(NS_ERROR_FAILURE);
- return;
- }
-
- // This only functions in e10s mode
- if (XRE_IsParentProcess()) {
- MOZ_LOG(gU2FLog, LogLevel::Debug,
- ("Is non-e10s Process, U2F not available"));
- aRv.Throw(NS_ERROR_FAILURE);
- return;
- }
-
- // Monolithically insert compatible nsIU2FToken objects into mAuthenticators.
- // In future functionality expansions, this is where we could add a dynamic
- // add/remove interface.
- if (Preferences::GetBool(PREF_U2F_SOFTTOKEN_ENABLED)) {
- if (!mAuthenticators.AppendElement(new NSSU2FTokenRemote(),
- mozilla::fallible)) {
- aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
- return;
- }
- }
-
- mEventTarget = doc->EventTargetFor(TaskCategory::Other);
-
- mInitialized = true;
-}
-
-void
-U2F::Register(const nsAString& aAppId,
- const Sequence<RegisterRequest>& aRegisterRequests,
- const Sequence<RegisteredKey>& aRegisteredKeys,
- U2FRegisterCallback& aCallback,
- const Optional<Nullable<int32_t>>& opt_aTimeoutSeconds,
- ErrorResult& aRv)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!mInitialized) {
- aRv.Throw(NS_ERROR_NOT_AVAILABLE);
- return;
- }
-
- RefPtr<SharedThreadPool> pool = SharedThreadPool::Get(kPoolName);
- RefPtr<U2FRegisterRunnable> task = new U2FRegisterRunnable(mOrigin, aAppId,
- aRegisterRequests,
- aRegisteredKeys,
- mAuthenticators,
- &aCallback,
- mEventTarget);
- pool->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
-}
-
-void
-U2F::Sign(const nsAString& aAppId,
- const nsAString& aChallenge,
- const Sequence<RegisteredKey>& aRegisteredKeys,
- U2FSignCallback& aCallback,
- const Optional<Nullable<int32_t>>& opt_aTimeoutSeconds,
- ErrorResult& aRv)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!mInitialized) {
- aRv.Throw(NS_ERROR_NOT_AVAILABLE);
- return;
- }
-
- RefPtr<SharedThreadPool> pool = SharedThreadPool::Get(kPoolName);
- RefPtr<U2FSignRunnable> task = new U2FSignRunnable(mOrigin, aAppId, aChallenge,
- aRegisteredKeys,
- mAuthenticators, &aCallback,
- mEventTarget);
- pool->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/u2f/U2F.h
+++ /dev/null
@@ -1,332 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* 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/. */
-
-#ifndef mozilla_dom_U2F_h
-#define mozilla_dom_U2F_h
-
-#include "js/TypeDecls.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/dom/BindingDeclarations.h"
-#include "mozilla/dom/CryptoBuffer.h"
-#include "mozilla/dom/Nullable.h"
-#include "mozilla/dom/U2FBinding.h"
-#include "mozilla/ErrorResult.h"
-#include "mozilla/MozPromise.h"
-#include "mozilla/ReentrantMonitor.h"
-#include "mozilla/SharedThreadPool.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsIU2FToken.h"
-#include "nsNSSShutDown.h"
-#include "nsPIDOMWindow.h"
-#include "nsProxyRelease.h"
-#include "nsWrapperCache.h"
-
-#include "U2FAuthenticator.h"
-
-class nsISerialEventTarget;
-
-namespace mozilla {
-namespace dom {
-
-class U2FRegisterCallback;
-class U2FSignCallback;
-
-// Defined in U2FBinding.h by the U2F.webidl; their use requires a JSContext.
-struct RegisterRequest;
-struct RegisteredKey;
-
-// These structs are analogs to the WebIDL versions, but can be used on worker
-// threads which lack a JSContext.
-struct LocalRegisterRequest
-{
- nsString mChallenge;
- nsString mVersion;
- CryptoBuffer mClientData;
-};
-
-struct LocalRegisteredKey
-{
- nsString mKeyHandle;
- nsString mVersion;
- Nullable<nsString> mAppId;
- // TODO: Support transport preferences
- // Nullable<nsTArray<Transport>> mTransports;
-};
-
-typedef MozPromise<nsString, ErrorCode, false> U2FPromise;
-typedef MozPromise<Authenticator, ErrorCode, false> U2FPrepPromise;
-
-// U2FPrepTasks return lists of Authenticators that are OK to
-// proceed; they're useful for culling incompatible Authenticators.
-// Currently, only IsRegistered is supported.
-class U2FPrepTask : public Runnable
-{
-public:
- explicit U2FPrepTask(const Authenticator& aAuthenticator,
- nsISerialEventTarget* aEventTarget);
-
- RefPtr<U2FPrepPromise> Execute();
-
-protected:
- virtual ~U2FPrepTask();
-
- Authenticator mAuthenticator;
- MozPromiseHolder<U2FPrepPromise> mPromise;
- const nsCOMPtr<nsISerialEventTarget> mEventTarget;
-};
-
-// Determine whether the provided Authenticator already knows
-// of the provided Registered Key.
-class U2FIsRegisteredTask final : public U2FPrepTask
-{
-public:
- U2FIsRegisteredTask(const Authenticator& aAuthenticator,
- const LocalRegisteredKey& aRegisteredKey,
- const CryptoBuffer& aAppParam,
- nsISerialEventTarget* aEventTarget);
-
- NS_DECL_NSIRUNNABLE
-private:
- ~U2FIsRegisteredTask();
-
- LocalRegisteredKey mRegisteredKey;
- CryptoBuffer mAppParam;
-};
-
-class U2FTask : public Runnable
-{
-public:
- U2FTask(const nsAString& aOrigin,
- const nsAString& aAppId,
- const Authenticator& aAuthenticator,
- nsISerialEventTarget* aEventTarget);
-
- RefPtr<U2FPromise> Execute();
-
- nsString mOrigin;
- nsString mAppId;
- Authenticator mAuthenticator;
- const nsCOMPtr<nsISerialEventTarget> mEventTarget;
-
-protected:
- virtual ~U2FTask();
-
- MozPromiseHolder<U2FPromise> mPromise;
-};
-
-// Use the provided Authenticator to Register a new scoped credential
-// for the provided application.
-class U2FRegisterTask final : public U2FTask
-{
-public:
- U2FRegisterTask(const nsAString& aOrigin,
- const nsAString& aAppId,
- const Authenticator& aAuthenticator,
- const CryptoBuffer& aAppParam,
- const CryptoBuffer& aChallengeParam,
- const LocalRegisterRequest& aRegisterEntry,
- nsISerialEventTarget* aEventTarget);
-
- NS_DECL_NSIRUNNABLE
-private:
- ~U2FRegisterTask();
-
- CryptoBuffer mAppParam;
- CryptoBuffer mChallengeParam;
- LocalRegisterRequest mRegisterEntry;
-};
-
-// Generate an assertion using the provided Authenticator for the given origin
-// and provided application to attest to ownership of a valid scoped credential.
-class U2FSignTask final : public U2FTask
-{
-public:
- U2FSignTask(const nsAString& aOrigin,
- const nsAString& aAppId,
- const nsAString& aVersion,
- const Authenticator& aAuthenticator,
- const CryptoBuffer& aAppParam,
- const CryptoBuffer& aChallengeParam,
- const CryptoBuffer& aClientData,
- const CryptoBuffer& aKeyHandle,
- nsISerialEventTarget* aEventTarget);
-
- NS_DECL_NSIRUNNABLE
-private:
- ~U2FSignTask();
-
- nsString mVersion;
- CryptoBuffer mAppParam;
- CryptoBuffer mChallengeParam;
- CryptoBuffer mClientData;
- CryptoBuffer mKeyHandle;
-};
-
-// Mediate inter-thread communication for multiple authenticators being queried
-// in concert. Operates as a cyclic buffer with a stop-work method.
-class U2FStatus
-{
-public:
- U2FStatus();
- U2FStatus(const U2FStatus&) = delete;
-
- void WaitGroupAdd();
- void WaitGroupDone();
- void WaitGroupWait();
-
- void Stop(const ErrorCode aErrorCode);
- void Stop(const ErrorCode aErrorCode, const nsAString& aResponse);
- bool IsStopped();
- ErrorCode GetErrorCode();
- nsString GetResponse();
-
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(U2FStatus)
-
-private:
- ~U2FStatus();
-
- uint16_t mCount;
- bool mIsStopped;
- nsString mResponse;
- MOZ_INIT_OUTSIDE_CTOR ErrorCode mErrorCode;
- ReentrantMonitor mReentrantMonitor;
-};
-
-// U2FRunnables run to completion, performing a single U2F operation such as
-// registering, or signing.
-class U2FRunnable : public Runnable
- , public nsNSSShutDownObject
-{
-public:
- U2FRunnable(const nsAString& aOrigin, const nsAString& aAppId,
- nsISerialEventTarget* aEventTarget);
-
- // No NSS resources to release.
- virtual
- void virtualDestroyNSSReference() override {};
-
-protected:
- virtual ~U2FRunnable();
- ErrorCode EvaluateAppID();
-
- nsString mOrigin;
- nsString mAppId;
- const nsCOMPtr<nsISerialEventTarget> mEventTarget;
-};
-
-// This U2FRunnable completes a single application-requested U2F Register
-// operation.
-class U2FRegisterRunnable : public U2FRunnable
-{
-public:
- U2FRegisterRunnable(const nsAString& aOrigin,
- const nsAString& aAppId,
- const Sequence<RegisterRequest>& aRegisterRequests,
- const Sequence<RegisteredKey>& aRegisteredKeys,
- const Sequence<Authenticator>& aAuthenticators,
- U2FRegisterCallback* aCallback,
- nsISerialEventTarget* aEventTarget);
-
- void SendResponse(const RegisterResponse& aResponse);
- void SetTimeout(const int32_t aTimeoutMillis);
-
- NS_DECL_NSIRUNNABLE
-
-private:
- ~U2FRegisterRunnable();
-
- nsTArray<LocalRegisterRequest> mRegisterRequests;
- nsTArray<LocalRegisteredKey> mRegisteredKeys;
- nsTArray<Authenticator> mAuthenticators;
- nsMainThreadPtrHandle<U2FRegisterCallback> mCallback;
- Nullable<int32_t> opt_mTimeoutSeconds;
-};
-
-// This U2FRunnable completes a single application-requested U2F Sign operation.
-class U2FSignRunnable : public U2FRunnable
-{
-public:
- U2FSignRunnable(const nsAString& aOrigin,
- const nsAString& aAppId,
- const nsAString& aChallenge,
- const Sequence<RegisteredKey>& aRegisteredKeys,
- const Sequence<Authenticator>& aAuthenticators,
- U2FSignCallback* aCallback,
- nsISerialEventTarget* aEventTarget);
-
- void SendResponse(const SignResponse& aResponse);
- void SetTimeout(const int32_t aTimeoutMillis);
-
- NS_DECL_NSIRUNNABLE
-
-private:
- ~U2FSignRunnable();
-
- nsString mChallenge;
- CryptoBuffer mClientData;
- nsTArray<LocalRegisteredKey> mRegisteredKeys;
- nsTArray<Authenticator> mAuthenticators;
- nsMainThreadPtrHandle<U2FSignCallback> mCallback;
- Nullable<int32_t> opt_mTimeoutSeconds;
-};
-
-// The U2F Class is used by the JS engine to initiate U2F operations.
-class U2F final : public nsISupports
- , public nsWrapperCache
- , public nsNSSShutDownObject
-{
-public:
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(U2F)
-
- U2F();
-
- nsPIDOMWindowInner*
- GetParentObject() const
- {
- return mParent;
- }
-
- void
- Init(nsPIDOMWindowInner* aParent, ErrorResult& aRv);
-
- virtual JSObject*
- WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-
- void
- Register(const nsAString& aAppId,
- const Sequence<RegisterRequest>& aRegisterRequests,
- const Sequence<RegisteredKey>& aRegisteredKeys,
- U2FRegisterCallback& aCallback,
- const Optional<Nullable<int32_t>>& opt_aTimeoutSeconds,
- ErrorResult& aRv);
-
- void
- Sign(const nsAString& aAppId,
- const nsAString& aChallenge,
- const Sequence<RegisteredKey>& aRegisteredKeys,
- U2FSignCallback& aCallback,
- const Optional<Nullable<int32_t>>& opt_aTimeoutSeconds,
- ErrorResult& aRv);
-
- // No NSS resources to release.
- virtual
- void virtualDestroyNSSReference() override {};
-
-private:
- nsCOMPtr<nsPIDOMWindowInner> mParent;
- nsString mOrigin;
- Sequence<Authenticator> mAuthenticators;
- bool mInitialized;
- nsCOMPtr<nsISerialEventTarget> mEventTarget;
-
- ~U2F();
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_U2F_h
deleted file mode 100644
--- a/dom/u2f/tests/frame_appid_facet.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<head>
- <script src="u2futil.js"></script>
-</head>
-<body>
-<p>Test for AppID / FacetID behavior for FIDO Universal Second Factor</p>
-<script class="testbody" type="text/javascript">
-"use strict";
-
-local_is(window.location.origin, "https://example.com", "Is loaded correctly");
-
-var version = "U2F_V2";
-var challenge = new Uint8Array(16);
-
-local_expectThisManyTests(5);
-
-u2f.register(null, [{
- version: version,
- challenge: bytesToBase64UrlSafe(challenge),
-}], [], function(res){
- local_is(res.errorCode, 0, "Null AppID should work.");
- local_completeTest();
-});
-
-u2f.register("", [{
- version: version,
- challenge: bytesToBase64UrlSafe(challenge),
-}], [], function(res){
- local_is(res.errorCode, 0, "Empty AppID should work.");
- local_completeTest();
-});
-
-// Test: Correct TLD, but incorrect scheme
-u2f.register("http://example.com/appId", [{
- version: version,
- challenge: bytesToBase64UrlSafe(challenge),
-}], [], function(res){
- local_isnot(res.errorCode, 0, "HTTP scheme is disallowed");
- local_completeTest();
-});
-
-// Test: Correct TLD, and also HTTPS
-u2f.register("https://example.com/appId", [{
- version: version,
- challenge: bytesToBase64UrlSafe(challenge),
-}], [], function(res){
- local_is(res.errorCode, 0, "HTTPS origin for example.com should work");
- local_completeTest();
-});
-
-// Test: Dynamic origin
-u2f.register(window.location.origin + "/otherAppId", [{
- version: version,
- challenge: bytesToBase64UrlSafe(challenge),
-}], [], function(res){
- local_is(res.errorCode, 0, "Direct window origin should work");
- local_completeTest();
-});
-
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/u2f/tests/frame_appid_facet_insecure.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<head>
- <script src="u2futil.js"></script>
-</head>
-<body>
-<p>Test for AppID / FacetID behavior for FIDO Universal Second Factor</p>
-<script class="testbody" type="text/javascript">
-"use strict";
-
-local_is(window.location.origin, "http://mochi.test:8888", "Is loaded correctly");
-
-var version = "U2F_V2";
-var challenge = new Uint8Array(16);
-
-local_expectThisManyTests(5);
-
-u2f.register(null, [{
- version: version,
- challenge: bytesToBase64UrlSafe(challenge),
-}], [], function(res){
- local_isnot(res.errorCode, 0, "Insecure origin disallowed for null AppID");
- local_completeTest();
-});
-
-u2f.register("", [{
- version: version,
- challenge: bytesToBase64UrlSafe(challenge),
-}], [], function(res){
- local_isnot(res.errorCode, 0, "Insecure origin disallowed for empty AppID");
- local_completeTest();
-});
-
-u2f.register("http://example.com/appId", [{
- version: version,
- challenge: bytesToBase64UrlSafe(challenge),
-}], [], function(res){
- local_isnot(res.errorCode, 0, "Insecure origin disallowed for HTTP AppID");
- local_completeTest();
-});
-
-u2f.register("https://example.com/appId", [{
- version: version,
- challenge: bytesToBase64UrlSafe(challenge),
-}], [], function(res){
- local_isnot(res.errorCode, 0, "Insecure origin disallowed for HTTPS AppID from HTTP origin");
- local_completeTest();
-});
-
-u2f.register(window.location.origin + "/otherAppId", [{
- version: version,
- challenge: bytesToBase64UrlSafe(challenge),
-}], [], function(res){
- local_isnot(res.errorCode, 0, "Insecure origin disallowed for HTTP origin");
- local_completeTest();
-});
-
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/u2f/tests/frame_appid_facet_subdomain.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<head>
- <script src="u2futil.js"></script>
-</head>
-<body>
-<p>Test for AppID / FacetID behavior for FIDO Universal Second Factor</p>
-<script class="testbody" type="text/javascript">
-"use strict";
-
-var version = "U2F_V2";
-var challenge = new Uint8Array(16);
-
-local_is(window.location.origin, "https://test1.example.com", "Is loaded correctly");
-
-local_expectThisManyTests(4);
-
-// same domain check
-u2f.register("https://test1.example.com/appId", [{
- version: version,
- challenge: bytesToBase64UrlSafe(challenge),
-}], [], function(res){
- local_is(res.errorCode, 0, "AppID should work from a different path of this domain");
- local_completeTest();
-});
-
-// same domain check, but wrong scheme
-u2f.register("http://test1.example.com/appId", [{
- version: version,
- challenge: bytesToBase64UrlSafe(challenge),
-}], [], function(res){
- local_isnot(res.errorCode, 0, "AppID should not work when using a different scheme");
- local_completeTest();
-});
-
-// eTLD+1 subdomain check
-u2f.register("https://example.com/appId", [{
- version: version,
- challenge: bytesToBase64UrlSafe(challenge),
-}], [], function(res){
- local_isnot(res.errorCode, 0, "AppID should not work from another subdomain in this registered domain");
- local_completeTest();
-});
-
-// other domain check
-u2f.register("https://mochi.test:8888/appId", [{
- version: version,
- challenge: bytesToBase64UrlSafe(challenge),
-}], [], function(res){
- local_isnot(res.errorCode, 0, "AppID should not work from other domains");
- local_completeTest();
-});
-
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/u2f/tests/frame_multiple_keys.html
+++ /dev/null
@@ -1,120 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<head>
- <script type="text/javascript" src="u2futil.js"></script>
-</head>
-<body>
-
-<script class="testbody" type="text/javascript">
-"use strict";
-
-function keyHandleFromRegResponse(aRegResponse) {
- // Parse the response data from the U2F token
- var registrationData = base64ToBytesUrlSafe(aRegResponse.registrationData);
- local_is(registrationData[0], 0x05, "Reserved byte is correct")
-
- var keyHandleLength = registrationData[66];
- var keyHandleBytes = registrationData.slice(67, 67 + keyHandleLength);
-
- return {
- version: "U2F_V2",
- keyHandle: bytesToBase64UrlSafe(keyHandleBytes),
- };
-}
-
-local_expectThisManyTests(1);
-
-// Ensure the SpecialPowers push worked properly
-local_isnot(window.u2f, undefined, "U2F API endpoint must exist");
-
-var challenge = new Uint8Array(16);
-window.crypto.getRandomValues(challenge);
-
-var regRequest = {
- version: "U2F_V2",
- challenge: bytesToBase64UrlSafe(challenge),
-};
-
-var testState = {
- key1: null,
- key2: null,
-}
-
-// Get two valid keys and present them
-window.u2f.register(window.location.origin, [regRequest], [], function(aRegResponse) {
- testState.key1 = keyHandleFromRegResponse(aRegResponse);
- registerSecondKey();
-});
-
-// Get the second key...
-// It's OK to repeat the regRequest; not material for this test
-function registerSecondKey() {
- window.u2f.register(window.location.origin, [regRequest], [], function(aRegResponse) {
- testState.key2 = keyHandleFromRegResponse(aRegResponse);
-
- registerWithInvalidAndValidKey();
- });
-}
-
-function registerWithInvalidAndValidKey() {
- window.u2f.register(window.location.origin, [regRequest],
- [invalidKey, testState.key1], function(aRegResponse) {
- // Expect a failure response since key1 is already registered
- local_is(aRegResponse.errorCode, 4, "The register should have skipped since there was a valid key");
-
- testSignSingleKey();
- });
-}
-
-// It should also work with just one key
-function testSignSingleKey() {
- window.u2f.sign(window.location.origin, bytesToBase64UrlSafe(challenge),
- [testState.key1], function(aSignResponse) {
- local_is(aSignResponse.errorCode, 0, "The signing did not error with one key");
- local_isnot(aSignResponse.clientData, undefined, "The signing provided clientData with one key");
-
- testSignDual();
- });
-}
-
-function testSignDual() {
- // It's OK to sign with either one
- window.u2f.sign(window.location.origin, bytesToBase64UrlSafe(challenge),
- [testState.key1, testState.key2], function(aSignResponse) {
- local_is(aSignResponse.errorCode, 0, "The signing did not error with two keys");
- local_isnot(aSignResponse.clientData, undefined, "The signing provided clientData with two keys");
-
- testSignWithInvalidKey();
- });
-}
-
-// Just a key that came from a random profile; syntactically valid but not
-// unwrappable.
-var invalidKey = {
- "version": "U2F_V2",
- "keyHandle": "rQdreHgHrmKfsnGPAElEP9yfTx6eq2eU3_Y8n0RRsGKML0DY2d1_a8_-sOtxDr3"
-};
-
-function testSignWithInvalidKey() {
- window.u2f.sign(window.location.origin, bytesToBase64UrlSafe(challenge),
- [invalidKey, testState.key2], function(aSignResponse) {
- local_is(aSignResponse.errorCode, 0, "The signing did not error when given an invalid key");
- local_isnot(aSignResponse.clientData, undefined, "The signing provided clientData even when given an invalid key");
-
- testSignWithInvalidKeyReverse();
- });
-}
-
-function testSignWithInvalidKeyReverse() {
- window.u2f.sign(window.location.origin, bytesToBase64UrlSafe(challenge),
- [testState.key2, invalidKey], function(aSignResponse) {
- local_is(aSignResponse.errorCode, 0, "The signing did not error when given an invalid key");
- local_isnot(aSignResponse.clientData, undefined, "The signing provided clientData even when given an invalid key");
-
- local_completeTest();
- });
-}
-</script>
-
-</body>
-</html>
\ No newline at end of file
deleted file mode 100644
--- a/dom/u2f/tests/frame_no_token.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<head>
- <title>Test for FIDO Universal Second Factor No Token</title>
- <script src="u2futil.js"></script>
-</head>
-<body>
-
-<script class="testbody" type="text/javascript">
-
-var challenge = new Uint8Array(16);
-window.crypto.getRandomValues(challenge);
-
-var regRequest = {
- version: "U2F_V2",
- challenge: bytesToBase64UrlSafe(challenge),
-};
-
-local_expectThisManyTests(1);
-
-u2f.register(window.location.origin, [regRequest], [], function (res) {
- local_isnot(res.errorCode, 0, "The registration should be rejected.");
- local_completeTest();
-});
-
-</script>
-
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/u2f/tests/frame_register.html
+++ /dev/null
@@ -1,81 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<head>
- <script src="u2futil.js"></script>
-</head>
-<body>
-<p>Test for Register behavior for FIDO Universal Second Factor</p>
-<script class="testbody" type="text/javascript">
-"use strict";
-
-var version = "U2F_V2";
-var challenge = new Uint8Array(16);
-
-local_is(window.location.origin, "https://example.com", "Is loaded correctly");
-
-local_expectThisManyTests(7);
-
-// basic check
-u2f.register("https://example.com/appId", [{
- version: version,
- challenge: bytesToBase64UrlSafe(challenge),
-}], [], function(res){
- local_is(res.errorCode, 0, "AppID should work from the domain");
- local_completeTest();
-});
-
-u2f.register("https://example.net/appId", [{
- version: version,
- challenge: bytesToBase64UrlSafe(challenge),
-}], [], function(res){
- local_is(res.errorCode, 2, "AppID should not work from other domains");
- local_completeTest();
-});
-
-u2f.register("", [], [], function(res){
- local_is(res.errorCode, 2, "Empty register requests");
- local_completeTest();
-});
-
-local_doesThrow(function(){
- u2f.register("", null, [], null);
-}, "Non-array register requests");
-
-local_doesThrow(function(){
- u2f.register("", [], null, null);
-}, "Non-array sign requests");
-
-local_doesThrow(function(){
- u2f.register("", null, null, null);
-}, "Non-array for both arguments");
-
-u2f.register("", [{}], [], function(res){
- local_is(res.errorCode, 2, "Empty request");
- local_completeTest();
-});
-
-u2f.register("https://example.net/appId", [{
- version: version,
- }], [], function(res){
- local_is(res.errorCode, 2, "Missing challenge");
- local_completeTest();
-});
-
-u2f.register("https://example.net/appId", [{
- challenge: bytesToBase64UrlSafe(challenge),
- }], [], function(res){
- local_is(res.errorCode, 2, "Missing version");
- local_completeTest();
-});
-
-u2f.register("https://example.net/appId", [{
- version: "a_version_00",
- challenge: bytesToBase64UrlSafe(challenge),
- }], [], function(res){
- local_is(res.errorCode, 2, "Invalid version");
- local_completeTest();
-});
-
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/u2f/tests/frame_register_sign.html
+++ /dev/null
@@ -1,201 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<head>
- <script type="text/javascript" src="u2futil.js"></script>
- <script type="text/javascript" src="pkijs/common.js"></script>
- <script type="text/javascript" src="pkijs/asn1.js"></script>
- <script type="text/javascript" src="pkijs/x509_schema.js"></script>
- <script type="text/javascript" src="pkijs/x509_simpl.js"></script>
-</head>
-<body>
-<p>Register and Sign Test for FIDO Universal Second Factor</p>
-<script class="testbody" type="text/javascript">
-"use strict";
-
-var state = {
- // Raw messages
- regRequest: null,
- regResponse: null,
-
- regKey: null,
- signChallenge: null,
- signResponse: null,
-
- // Parsed values
- publicKey: null,
- keyHandle: null,
-
- // Constants
- version: "U2F_V2",
- appId: window.location.origin,
-};
-
-SpecialPowers.pushPrefEnv({"set": [["security.webauth.u2f", true],
- ["security.webauth.u2f_enable_softtoken", true]]},
-function() {
- local_isnot(window.u2f, undefined, "U2F API endpoint must exist");
- local_isnot(window.u2f.register, undefined, "U2F Register API endpoint must exist");
- local_isnot(window.u2f.sign, undefined, "U2F Sign API endpoint must exist");
-
- testRegistering();
-
- function testRegistering() {
- var challenge = new Uint8Array(16);
- window.crypto.getRandomValues(challenge);
-
- state.regRequest = {
- version: state.version,
- challenge: bytesToBase64UrlSafe(challenge),
- };
-
- u2f.register(state.appId, [state.regRequest], [], function(regResponse) {
- state.regResponse = regResponse;
-
- local_is(regResponse.errorCode, 0, "The registration did not error");
- local_isnot(regResponse.registrationData, undefined, "The registration did not provide registration data");
- if (regResponse.errorCode > 0) {
- local_finished();
- return;
- }
-
- // Parse the response data from the U2F token
- var registrationData = base64ToBytesUrlSafe(regResponse.registrationData);
- local_is(registrationData[0], 0x05, "Reserved byte is correct")
-
- state.publicKeyBytes = registrationData.slice(1, 66);
- var keyHandleLength = registrationData[66];
- state.keyHandleBytes = registrationData.slice(67, 67 + keyHandleLength);
- state.keyHandle = bytesToBase64UrlSafe(state.keyHandleBytes);
- state.attestation = registrationData.slice(67 + keyHandleLength);
-
- local_is(state.attestation[0], 0x30, "Attestation Certificate has correct starting byte");
- var asn1 = org.pkijs.fromBER(state.attestation.buffer);
- console.log(asn1);
- state.attestationCert = new org.pkijs.simpl.CERT({ schema: asn1.result });
- console.log(state.attestationCert);
- state.attestationSig = state.attestation.slice(asn1.offset);
- local_is(state.attestationCert.subject.types_and_values[0].value.value_block.value, "Firefox U2F Soft Token", "Expected Subject");
- local_is(state.attestationCert.issuer.types_and_values[0].value.value_block.value, "Firefox U2F Soft Token", "Expected Issuer");
- local_is(state.attestationCert.notAfter.value - state.attestationCert.notBefore.value, 1000*60*60*48, "Valid 48 hours (in millis)");
-
- // Verify that the clientData from the U2F token makes sense
- var clientDataJSON = "";
- base64ToBytesUrlSafe(regResponse.clientData).map(x => clientDataJSON += String.fromCharCode(x));
- var clientData = JSON.parse(clientDataJSON);
- local_is(clientData.typ, "navigator.id.finishEnrollment", "Register - Data type matches");
- local_is(clientData.challenge, state.regRequest.challenge, "Register - Challenge matches");
- local_is(clientData.origin, window.location.origin, "Register - Origins are the same");
-
- // Verify the signature from the attestation certificate
- deriveAppAndChallengeParam(state.appId, string2buffer(clientDataJSON))
- .then(function(params){
- state.appParam = params.appParam;
- state.challengeParam = params.challengeParam;
- return state.attestationCert.getPublicKey();
- }).then(function(attestationPublicKey) {
- var signedData = assembleRegistrationSignedData(state.appParam, state.challengeParam, state.keyHandleBytes, state.publicKeyBytes);
- return verifySignature(attestationPublicKey, signedData, state.attestationSig);
- }).then(function(verified) {
- console.log("No error verifying signature");
- local_ok(verified, "Attestation Certificate signature verified")
- // Import the public key of the U2F token into WebCrypto
- return importPublicKey(state.publicKeyBytes)
- }).then(function(key) {
- state.publicKey = key;
- local_ok(true, "Imported public key")
-
- // Ensure the attestation certificate is properly self-signed
- return state.attestationCert.verify()
- }).then(function(){
- local_ok(true, "Attestation Certificate verification successful");
-
- // Continue test
- testReRegister()
- }).catch(function(err){
- console.log(err);
- local_ok(false, "Attestation Certificate verification failed");
- local_finished();
- });
- });
- }
-
- function testReRegister() {
- state.regKey = {
- version: state.version,
- keyHandle: state.keyHandle,
- };
-
- // Test that we don't re-register if we provide regKey as an
- // "already known" key handle. The U2F module should recognize regKey
- // as being usable and, thus, give back errorCode 4.
- u2f.register(state.appId, [state.regRequest], [state.regKey], function(regResponse) {
- // Since we attempted to register with state.regKey as a known key, expect
- // ineligible (=4).
- local_is(regResponse.errorCode, 4, "The re-registration should show device ineligible");
- local_is(regResponse.registrationData, undefined, "The re-registration did not provide registration data");
-
- // Continue test
- testSigning();
- });
- }
-
- function testSigning() {
- var challenge = new Uint8Array(16);
- window.crypto.getRandomValues(challenge);
- state.signChallenge = bytesToBase64UrlSafe(challenge);
-
- // Now try to sign the signature challenge
- u2f.sign(state.appId, state.signChallenge, [state.regKey], function(signResponse) {
- state.signResponse = signResponse;
-
- // Make sure this signature op worked, bailing early if it failed.
- local_is(signResponse.errorCode, 0, "The signing did not error");
- local_isnot(signResponse.clientData, undefined, "The signing did not provide client data");
-
- if (signResponse.errorCode > 0) {
- local_finished();
- return;
- }
-
- // Decode the clientData that was returned from the module
- var clientDataJSON = "";
- base64ToBytesUrlSafe(signResponse.clientData).map(x => clientDataJSON += String.fromCharCode(x));
- var clientData = JSON.parse(clientDataJSON);
- local_is(clientData.typ, "navigator.id.getAssertion", "Sign - Data type matches");
- local_is(clientData.challenge, state.signChallenge, "Sign - Challenge matches");
- local_is(clientData.origin, window.location.origin, "Sign - Origins are the same");
-
- // Parse the signature data
- var signatureData = base64ToBytesUrlSafe(signResponse.signatureData);
- if (signatureData[0] != 0x01) {
- throw "User presence byte not set";
- }
- var presenceAndCounter = signatureData.slice(0,5);
- var signatureValue = signatureData.slice(5);
-
- // Assemble the signed data and verify the signature
- deriveAppAndChallengeParam(state.appId, string2buffer(clientDataJSON))
- .then(function(params){
- return assembleSignedData(params.appParam, presenceAndCounter, params.challengeParam);
- })
- .then(function(signedData) {
- return verifySignature(state.publicKey, signedData, signatureValue);
- })
- .then(function(verified) {
- console.log("No error verifying signing signature");
- local_ok(verified, "Signing signature verified")
-
- local_finished();
- })
- .catch(function(err) {
- console.log(err);
- local_ok(false, "Signing signature invalid");
- local_finished();
- });
- });
- }
-});
-
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/u2f/tests/test_appid_facet.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<head>
- <title>Test for AppID / FacetID behavior for FIDO Universal Second Factor</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script src="u2futil.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1231681">Mozilla Bug 1231681</a>
-
-<div id="framediv">
- <iframe id="testing_frame"></iframe>
-</div>
-
-<pre id="log"></pre>
-
-<script class="testbody" type="text/javascript">
-
-SimpleTest.waitForExplicitFinish();
-
-SpecialPowers.pushPrefEnv({"set": [["security.webauth.u2f", true],
- ["security.webauth.u2f_enable_softtoken", true],
- ["security.webauth.u2f_enable_usbtoken", false]]},
-function() {
- // listen for messages from the test harness
- window.addEventListener("message", handleEventMessage);
- document.getElementById('testing_frame').src = "https://example.com/tests/dom/u2f/tests/frame_appid_facet.html";
-});
-
-</script>
-
-</body>
-</html>
deleted file mode 100644
--- a/dom/u2f/tests/test_appid_facet_insecure.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<head>
- <title>Test for AppID / FacetID behavior for FIDO Universal Second Factor</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script src="u2futil.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1231681">Mozilla Bug 1231681</a>
-
-<div id="framediv">
- <iframe id="testing_frame"></iframe>
-</div>
-
-<pre id="log"></pre>
-
-<script class="testbody" type="text/javascript">
-
-SimpleTest.waitForExplicitFinish();
-
-SpecialPowers.pushPrefEnv({"set": [["security.webauth.u2f", true],
- ["security.webauth.u2f_enable_softtoken", true],
- ["security.webauth.u2f_enable_usbtoken", false]]},
-function() {
- // listen for messages from the test harness
- window.addEventListener("message", handleEventMessage);
- document.getElementById('testing_frame').src = "http://mochi.test:8888/tests/dom/u2f/tests/frame_appid_facet_insecure.html";
-});
-
-</script>
-
-</body>
-</html>
deleted file mode 100644
--- a/dom/u2f/tests/test_appid_facet_subdomain.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<head>
- <title>Test for AppID / FacetID behavior for FIDO Universal Second Factor</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script src="u2futil.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1231681">Mozilla Bug 1231681</a>
-
-<div id="framediv">
- <iframe id="testing_frame"></iframe>
-</div>
-
-<pre id="log"></pre>
-
-<script class="testbody" type="text/javascript">
-
-SimpleTest.waitForExplicitFinish();
-
-SpecialPowers.pushPrefEnv({"set": [["security.webauth.u2f", true],
- ["security.webauth.u2f_enable_softtoken", true],
- ["security.webauth.u2f_enable_usbtoken", false]]},
-function() {
- // listen for messages from the test harness
- window.addEventListener("message", handleEventMessage);
- document.getElementById('testing_frame').src = "https://test1.example.com/tests/dom/u2f/tests/frame_appid_facet_subdomain.html";
-});
-
-</script>
-
-</body>
-</html>
deleted file mode 100644
--- a/dom/u2f/tests/test_multiple_keys.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<head>
- <title>Test for Multiple Keys for FIDO U2F</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script src="u2futil.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-
-<h1>Test Multiple Keys for FIDO U2F</h1>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1333592">Mozilla Bug 1333592</a>
-
-<script class="testbody" type="text/javascript">
-"use strict";
-
- /** Test for XBL scope behavior. **/
-SimpleTest.waitForExplicitFinish();
-
-// Embed the real test. It will take care of everything else.
-//
-// This is necessary since the U2F object on window is hidden behind a preference
-// and window won't pick up changes by pref without a reload.
-SpecialPowers.pushPrefEnv({"set": [["security.webauth.u2f", true],
- ["security.webauth.u2f_enable_softtoken", true],
- ["security.webauth.u2f_enable_usbtoken", false]]},
-function() {
- // listen for messages from the test harness
- window.addEventListener("message", handleEventMessage);
- document.getElementById('testing_frame').src = "https://example.com/tests/dom/u2f/tests/frame_multiple_keys.html";
-});
-</script>
-
-<div id="framediv">
- <iframe id="testing_frame"></iframe>
-</div>
-
-</body>
-</html>
deleted file mode 100644
--- a/dom/u2f/tests/test_no_token.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<head>
- <title>Test for FIDO Universal Second Factor No Token</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script src="u2futil.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1231681">Mozilla Bug 1231681</a>
-
-<div id="framediv">
- <iframe id="testing_frame"></iframe>
-</div>
-
-<script class="testbody" type="text/javascript">
-
-SimpleTest.waitForExplicitFinish();
-
-SpecialPowers.pushPrefEnv({"set": [["security.webauth.u2f", true],
- ["security.webauth.u2f_enable_softtoken", false],
- ["security.webauth.u2f_enable_usbtoken", false]]},
-function() {
- // listen for messages from the test harness
- window.addEventListener("message", handleEventMessage);
- document.getElementById('testing_frame').src = 'frame_no_token.html';
-});
-
-</script>
-
-</body>
-</html>
deleted file mode 100644
--- a/dom/u2f/tests/test_register.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<head>
- <title>Test for Register behavior for FIDO Universal Second Factor</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script src="u2futil.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1231681">Mozilla Bug 1231681</a>
-
-<div id="framediv">
- <iframe id="testing_frame"></iframe>
-</div>
-
-<pre id="log"></pre>
-
-<script class="testbody" type="text/javascript">
-
-SimpleTest.waitForExplicitFinish();
-
-SpecialPowers.pushPrefEnv({"set": [["security.webauth.u2f", true],
- ["security.webauth.u2f_enable_softtoken", true],
- ["security.webauth.u2f_enable_usbtoken", false]]},
-function() {
- // listen for messages from the test harness
- window.addEventListener("message", handleEventMessage);
- document.getElementById('testing_frame').src = "https://example.com/tests/dom/u2f/tests/frame_register.html";
-});
-
-</script>
-
-</body>
-</html>
deleted file mode 100644
--- a/dom/u2f/tests/test_register_sign.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<head>
- <title>Register and Sign Test for FIDO Universal Second Factor</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script src="u2futil.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1231681">Mozilla Bug 1231681</a>
-
-<div id="framediv">
- <iframe id="testing_frame"></iframe>
-</div>
-
-<pre id="log"></pre>
-
-<script class="testbody" type="text/javascript">
-
-SimpleTest.waitForExplicitFinish();
-
-SpecialPowers.pushPrefEnv({"set": [["security.webauth.u2f", true],
- ["security.webauth.u2f_enable_softtoken", true],
- ["security.webauth.u2f_enable_usbtoken", false]]},
-function() {
- // listen for messages from the test harness
- window.addEventListener("message", handleEventMessage);
- document.getElementById('testing_frame').src = "https://example.com/tests/dom/u2f/tests/frame_appid_facet.html";
-});
-
-</script>
-
-</body>
-</html>
deleted file mode 100644
--- a/dom/u2f/tests/test_util_methods.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<head>
- <title>Test for Utility Methods for other FIDO Universal Second Factor tests</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/dom/u2f/tests/u2futil.js"></script>
- <script type="text/javascript" src="pkijs/common.js"></script>
- <script type="text/javascript" src="pkijs/asn1.js"></script>
- <script type="text/javascript" src="pkijs/x509_schema.js"></script>
- <script type="text/javascript" src="pkijs/x509_simpl.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1231681">Mozilla Bug 1231681</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-SimpleTest.waitForExplicitFinish();
-
-SpecialPowers.pushPrefEnv({"set": [["security.webauth.u2f", true],
- ["security.webauth.u2f_enable_softtoken", true],
- ["security.webauth.u2f_enable_usbtoken", false]]},
-function() {
- // Example from:
- // https://fidoalliance.org/specs/fido-u2f-v1.0-nfc-bt-amendment-20150514/fido-u2f-raw-message-formats.html
- //
- // Run this example from the console to check that the u2futil methods work
- var pubKey = hexDecode("04d368f1b665bade3c33a20f1e429c7750d5033660c019119d29aa4ba7abc04aa7c80a46bbe11ca8cb5674d74f31f8a903f6bad105fb6ab74aefef4db8b0025e1d");
- var appId = "https://gstatic.com/securitykey/a/example.com";
- var clientData = string2buffer('{"typ":"navigator.id.getAssertion","challenge":"opsXqUifDriAAmWclinfbS0e-USY0CgyJHe_Otd7z8o","cid_pubkey":{"kty":"EC","crv":"P-256","x":"HzQwlfXX7Q4S5MtCCnZUNBw3RMzPO9tOyWjBqRl4tJ8","y":"XVguGFLIZx1fXg3wNqfdbn75hi4-_7-BxhMljw42Ht4"},"origin":"http://example.com"}');
- var presenceAndCounter = hexDecode("0100000001");
- var signature = hexDecode("304402204b5f0cd17534cedd8c34ee09570ef542a353df4436030ce43d406de870b847780220267bb998fac9b7266eb60e7cb0b5eabdfd5ba9614f53c7b22272ec10047a923f");
-
- // Import the key
- // Assemble the client data
- // Verify
- Promise.all([
- importPublicKey(pubKey),
- deriveAppAndChallengeParam(appId, clientData)
- ])
- .then(function(results) {
- var importedKey = results[0];
- var params = results[1];
- var signedData = new Uint8Array(assembleSignedData(params.appParam, presenceAndCounter, params.challengeParam));
- return verifySignature(importedKey, signedData, signature);
- })
- .then(function(verified) {
- console.log("verified:", verified);
- ok(true, "Utility methods work")
- SimpleTest.finish();
- })
- .catch(function(err) {
- console.log("error:", err);
- ok(false, "Utility methods failed")
- SimpleTest.finish();
- });
-});
-
-</script>
-</pre>
-</body>
-</html>