зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 58b6164020f0 (bug 1858799) for causing build bustage on dom/webauthn/winwebauthn/webauthn.h
This commit is contained in:
Родитель
5bad8fb623
Коммит
10a73a45ac
|
@ -16,7 +16,7 @@
|
|||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
# include "WinWebAuthnService.h"
|
||||
# include "WinWebAuthnManager.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
@ -129,7 +129,7 @@ PublicKeyCredential::IsUserVerifyingPlatformAuthenticatorAvailable(
|
|||
// have other UVPAAs available at this time.
|
||||
#ifdef XP_WIN
|
||||
|
||||
if (WinWebAuthnService::IsUserVerifyingPlatformAuthenticatorAvailable()) {
|
||||
if (WinWebAuthnManager::IsUserVerifyingPlatformAuthenticatorAvailable()) {
|
||||
promise->MaybeResolve(true);
|
||||
return promise.forget();
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ PublicKeyCredential::IsExternalCTAP2SecurityKeySupported(GlobalObject& aGlobal,
|
|||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (WinWebAuthnService::AreWebAuthNApisAvailable()) {
|
||||
if (WinWebAuthnManager::AreWebAuthNApisAvailable()) {
|
||||
promise->MaybeResolve(true);
|
||||
} else {
|
||||
promise->MaybeResolve(StaticPrefs::security_webauthn_ctap2());
|
||||
|
|
|
@ -25,12 +25,6 @@ WebAuthnRegisterArgs::GetChallenge(nsTArray<uint8_t>& aChallenge) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebAuthnRegisterArgs::GetClientDataJSON(nsACString& aClientDataJSON) {
|
||||
aClientDataJSON = mInfo.ClientDataJSON();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebAuthnRegisterArgs::GetClientDataHash(nsTArray<uint8_t>& aClientDataHash) {
|
||||
nsresult rv = HashCString(mInfo.ClientDataJSON(), aClientDataHash);
|
||||
|
@ -179,12 +173,6 @@ WebAuthnSignArgs::GetChallenge(nsTArray<uint8_t>& aChallenge) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebAuthnSignArgs::GetClientDataJSON(nsACString& aClientDataJSON) {
|
||||
aClientDataJSON = mInfo.ClientDataJSON();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebAuthnSignArgs::GetClientDataHash(nsTArray<uint8_t>& aClientDataHash) {
|
||||
nsresult rv = HashCString(mInfo.ClientDataJSON(), aClientDataHash);
|
||||
|
@ -229,11 +217,14 @@ WebAuthnSignArgs::GetHmacCreateSecret(bool* aHmacCreateSecret) {
|
|||
|
||||
NS_IMETHODIMP
|
||||
WebAuthnSignArgs::GetAppId(nsAString& aAppId) {
|
||||
if (mAppId.isNothing()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
for (const WebAuthnExtension& ext : mInfo.Extensions()) {
|
||||
if (ext.type() == WebAuthnExtension::TWebAuthnExtensionAppId) {
|
||||
aAppId = ext.get_WebAuthnExtensionAppId().appIdentifier();
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
aAppId = mAppId.ref();
|
||||
return NS_OK;
|
||||
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -61,29 +61,12 @@ class WebAuthnSignArgs final : public nsIWebAuthnSignArgs {
|
|||
NS_DECL_NSIWEBAUTHNSIGNARGS
|
||||
|
||||
explicit WebAuthnSignArgs(const WebAuthnGetAssertionInfo& aInfo)
|
||||
: mInfo(aInfo) {
|
||||
for (const WebAuthnExtension& ext : mInfo.Extensions()) {
|
||||
switch (ext.type()) {
|
||||
case WebAuthnExtension::TWebAuthnExtensionAppId:
|
||||
mAppId = Some(ext.get_WebAuthnExtensionAppId().appIdentifier());
|
||||
break;
|
||||
case WebAuthnExtension::TWebAuthnExtensionCredProps:
|
||||
break;
|
||||
case WebAuthnExtension::TWebAuthnExtensionHmacSecret:
|
||||
break;
|
||||
case WebAuthnExtension::TWebAuthnExtensionMinPinLength:
|
||||
break;
|
||||
case WebAuthnExtension::T__None:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
: mInfo(aInfo) {}
|
||||
|
||||
private:
|
||||
~WebAuthnSignArgs() = default;
|
||||
|
||||
const WebAuthnGetAssertionInfo mInfo;
|
||||
Maybe<nsString> mAppId;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "mozilla/ipc/PBackgroundChild.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
# include "WinWebAuthnService.h"
|
||||
# include "WinWebAuthnManager.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
@ -461,7 +461,7 @@ already_AddRefed<Promise> WebAuthnManager::MakeCredential(
|
|||
// initialized the only valid ways to end the transaction are
|
||||
// CancelTransaction, RejectTransaction, and FinishMakeCredential.
|
||||
#ifdef XP_WIN
|
||||
if (!WinWebAuthnService::AreWebAuthNApisAvailable()) {
|
||||
if (!WinWebAuthnManager::AreWebAuthNApisAvailable()) {
|
||||
ListenForVisibilityEvents();
|
||||
}
|
||||
#else
|
||||
|
@ -678,7 +678,7 @@ already_AddRefed<Promise> WebAuthnManager::GetAssertion(
|
|||
// initialized the only valid ways to end the transaction are
|
||||
// CancelTransaction, RejectTransaction, and FinishGetAssertion.
|
||||
#ifdef XP_WIN
|
||||
if (!WinWebAuthnService::AreWebAuthNApisAvailable()) {
|
||||
if (!WinWebAuthnManager::AreWebAuthNApisAvailable()) {
|
||||
ListenForVisibilityEvents();
|
||||
}
|
||||
#else
|
||||
|
|
|
@ -2,11 +2,8 @@
|
|||
* 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 "AuthrsBridge_ffi.h"
|
||||
#include "WebAuthnResult.h"
|
||||
#include "nsIWebAuthnAttObj.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "WebAuthnResult.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
namespace mozilla::jni {
|
||||
|
@ -65,15 +62,6 @@ WebAuthnRegisterResult::GetTransports(nsTArray<nsString>& aTransports) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebAuthnRegisterResult::GetHmacCreateSecret(bool* aHmacCreateSecret) {
|
||||
if (mHmacCreateSecret.isSome()) {
|
||||
*aHmacCreateSecret = mHmacCreateSecret.ref();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebAuthnRegisterResult::GetCredPropsRk(bool* aCredPropsRk) {
|
||||
if (mCredPropsRk.isSome()) {
|
||||
|
@ -99,27 +87,6 @@ WebAuthnRegisterResult::GetAuthenticatorAttachment(
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsresult WebAuthnRegisterResult::Anonymize() {
|
||||
// The anonymize flag in the nsIWebAuthnAttObj constructor causes the
|
||||
// attestation statement to be removed during deserialization. It also
|
||||
// causes the AAGUID to be zeroed out. If we can't deserialize the
|
||||
// existing attestation, then we can't ensure that it is anonymized, so we
|
||||
// act as though the user denied consent and we return NotAllowed.
|
||||
nsCOMPtr<nsIWebAuthnAttObj> anonymizedAttObj;
|
||||
nsresult rv = authrs_webauthn_att_obj_constructor(
|
||||
mAttestationObject,
|
||||
/* anonymize */ true, getter_AddRefs(anonymizedAttObj));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
mAttestationObject.Clear();
|
||||
rv = anonymizedAttObj->GetAttestationObject(mAttestationObject);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(WebAuthnSignResult, nsIWebAuthnSignResult)
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -160,17 +127,7 @@ WebAuthnSignResult::GetUserName(nsACString& aUserName) {
|
|||
|
||||
NS_IMETHODIMP
|
||||
WebAuthnSignResult::GetUsedAppId(bool* aUsedAppId) {
|
||||
if (mUsedAppId.isNothing()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
*aUsedAppId = mUsedAppId.ref();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebAuthnSignResult::SetUsedAppId(bool aUsedAppId) {
|
||||
mUsedAppId = Some(aUsedAppId);
|
||||
return NS_OK;
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -7,17 +7,10 @@
|
|||
|
||||
#include "nsIWebAuthnResult.h"
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
# include "mozilla/java/WebAuthnTokenManagerNatives.h"
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
# include "winwebauthn/webauthn.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class WebAuthnRegisterResult final : public nsIWebAuthnRegisterResult {
|
||||
|
@ -64,74 +57,6 @@ class WebAuthnRegisterResult final : public nsIWebAuthnRegisterResult {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
WebAuthnRegisterResult(nsACString& aClientDataJSON,
|
||||
PCWEBAUTHN_CREDENTIAL_ATTESTATION aResponse)
|
||||
: mClientDataJSON(aClientDataJSON) {
|
||||
mCredentialId.AppendElements(aResponse->pbCredentialId,
|
||||
aResponse->cbCredentialId);
|
||||
|
||||
mAttestationObject.AppendElements(aResponse->pbAttestationObject,
|
||||
aResponse->cbAttestationObject);
|
||||
|
||||
nsTArray<WebAuthnExtensionResult> extensions;
|
||||
if (aResponse->dwVersion >= WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_2) {
|
||||
PCWEBAUTHN_EXTENSIONS pExtensionList = &aResponse->Extensions;
|
||||
if (pExtensionList->cExtensions != 0 &&
|
||||
pExtensionList->pExtensions != NULL) {
|
||||
for (DWORD dwIndex = 0; dwIndex < pExtensionList->cExtensions;
|
||||
dwIndex++) {
|
||||
PWEBAUTHN_EXTENSION pExtension =
|
||||
&pExtensionList->pExtensions[dwIndex];
|
||||
if (pExtension->pwszExtensionIdentifier &&
|
||||
(0 == _wcsicmp(pExtension->pwszExtensionIdentifier,
|
||||
WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET)) &&
|
||||
pExtension->cbExtension == sizeof(BOOL)) {
|
||||
BOOL* pCredentialCreatedWithHmacSecret =
|
||||
(BOOL*)pExtension->pvExtension;
|
||||
if (*pCredentialCreatedWithHmacSecret) {
|
||||
mHmacCreateSecret = Some(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aResponse->dwVersion >= WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_3) {
|
||||
if (aResponse->dwUsedTransport & WEBAUTHN_CTAP_TRANSPORT_USB) {
|
||||
mTransports.AppendElement(u"usb"_ns);
|
||||
}
|
||||
if (aResponse->dwUsedTransport & WEBAUTHN_CTAP_TRANSPORT_NFC) {
|
||||
mTransports.AppendElement(u"nfc"_ns);
|
||||
}
|
||||
if (aResponse->dwUsedTransport & WEBAUTHN_CTAP_TRANSPORT_BLE) {
|
||||
mTransports.AppendElement(u"ble"_ns);
|
||||
}
|
||||
if (aResponse->dwUsedTransport & WEBAUTHN_CTAP_TRANSPORT_INTERNAL) {
|
||||
mTransports.AppendElement(u"internal"_ns);
|
||||
}
|
||||
}
|
||||
// WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_5 corresponds to
|
||||
// WEBAUTHN_API_VERSION_6 which is where WEBAUTHN_CTAP_TRANSPORT_HYBRID was
|
||||
// defined.
|
||||
if (aResponse->dwVersion >= WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_5) {
|
||||
if (aResponse->dwUsedTransport & WEBAUTHN_CTAP_TRANSPORT_HYBRID) {
|
||||
mTransports.AppendElement(u"hybrid"_ns);
|
||||
}
|
||||
}
|
||||
|
||||
if (aResponse->dwVersion >= WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_3) {
|
||||
if (aResponse->dwUsedTransport & WEBAUTHN_CTAP_TRANSPORT_INTERNAL) {
|
||||
mAuthenticatorAttachment = Some(u"platform"_ns);
|
||||
} else {
|
||||
mAuthenticatorAttachment = Some(u"cross-platform"_ns);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult Anonymize();
|
||||
|
||||
private:
|
||||
~WebAuthnRegisterResult() = default;
|
||||
|
||||
|
@ -140,7 +65,6 @@ class WebAuthnRegisterResult final : public nsIWebAuthnRegisterResult {
|
|||
nsTArray<nsString> mTransports;
|
||||
nsCString mClientDataJSON;
|
||||
Maybe<bool> mCredPropsRk;
|
||||
Maybe<bool> mHmacCreateSecret;
|
||||
Maybe<nsString> mAuthenticatorAttachment;
|
||||
};
|
||||
|
||||
|
@ -192,24 +116,6 @@ class WebAuthnSignResult final : public nsIWebAuthnSignResult {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
WebAuthnSignResult(nsACString& aClientDataJSON,
|
||||
PCWEBAUTHN_ASSERTION aResponse)
|
||||
: mClientDataJSON(aClientDataJSON) {
|
||||
mSignature.AppendElements(aResponse->pbSignature, aResponse->cbSignature);
|
||||
|
||||
mCredentialId.AppendElements(aResponse->Credential.pbId,
|
||||
aResponse->Credential.cbId);
|
||||
|
||||
mUserHandle.AppendElements(aResponse->pbUserId, aResponse->cbUserId);
|
||||
|
||||
mAuthenticatorData.AppendElements(aResponse->pbAuthenticatorData,
|
||||
aResponse->cbAuthenticatorData);
|
||||
|
||||
mAuthenticatorAttachment = Nothing(); // not available
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
~WebAuthnSignResult() = default;
|
||||
|
||||
|
@ -219,7 +125,6 @@ class WebAuthnSignResult final : public nsIWebAuthnSignResult {
|
|||
nsTArray<uint8_t> mSignature;
|
||||
nsTArray<uint8_t> mUserHandle;
|
||||
Maybe<nsString> mAuthenticatorAttachment;
|
||||
Maybe<bool> mUsedAppId;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -12,10 +12,6 @@
|
|||
# include "AndroidWebAuthnService.h"
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
# include "WinWebAuthnService.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
already_AddRefed<nsIWebAuthnService> NewWebAuthnService();
|
||||
|
@ -27,13 +23,7 @@ class WebAuthnService final : public nsIWebAuthnService {
|
|||
|
||||
WebAuthnService() {
|
||||
Unused << authrs_service_constructor(getter_AddRefs(mTestService));
|
||||
#if defined(XP_WIN)
|
||||
if (WinWebAuthnService::AreWebAuthNApisAvailable()) {
|
||||
mPlatformService = new WinWebAuthnService();
|
||||
} else {
|
||||
mPlatformService = mTestService;
|
||||
}
|
||||
#elif defined(MOZ_WIDGET_ANDROID)
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
mPlatformService = new AndroidWebAuthnService();
|
||||
#else
|
||||
mPlatformService = mTestService;
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
#include "nsThreadUtils.h"
|
||||
#include "WebAuthnArgs.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
# include "WinWebAuthnManager.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
mozilla::ipc::IPCResult WebAuthnTransactionParent::RecvRequestRegister(
|
||||
|
@ -20,6 +24,18 @@ mozilla::ipc::IPCResult WebAuthnTransactionParent::RecvRequestRegister(
|
|||
const WebAuthnMakeCredentialInfo& aTransactionInfo) {
|
||||
::mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
#ifdef XP_WIN
|
||||
bool usingTestToken =
|
||||
StaticPrefs::security_webauth_webauthn_enable_softtoken();
|
||||
if (!usingTestToken && WinWebAuthnManager::AreWebAuthNApisAvailable()) {
|
||||
WinWebAuthnManager* mgr = WinWebAuthnManager::Get();
|
||||
if (mgr) {
|
||||
mgr->Register(this, aTransactionId, aTransactionInfo);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
#endif
|
||||
|
||||
// If there's an ongoing transaction, abort it.
|
||||
if (mTransactionId.isSome()) {
|
||||
mRegisterPromiseRequest.DisconnectIfExists();
|
||||
|
@ -101,18 +117,6 @@ mozilla::ipc::IPCResult WebAuthnTransactionParent::RecvRequestRegister(
|
|||
WebAuthnExtensionResultCredProps(credPropsRk));
|
||||
}
|
||||
|
||||
bool hmacCreateSecret;
|
||||
rv = aValue->GetHmacCreateSecret(&hmacCreateSecret);
|
||||
if (rv != NS_ERROR_NOT_AVAILABLE) {
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
Unused << parent->SendAbort(aTransactionId,
|
||||
NS_ERROR_DOM_NOT_ALLOWED_ERR);
|
||||
return;
|
||||
}
|
||||
extensions.AppendElement(
|
||||
WebAuthnExtensionResultHmacSecret(hmacCreateSecret));
|
||||
}
|
||||
|
||||
WebAuthnMakeCredentialResult result(
|
||||
clientData, attObj, credentialId, transports, extensions,
|
||||
authenticatorAttachment);
|
||||
|
@ -147,6 +151,18 @@ mozilla::ipc::IPCResult WebAuthnTransactionParent::RecvRequestSign(
|
|||
const WebAuthnGetAssertionInfo& aTransactionInfo) {
|
||||
::mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
#ifdef XP_WIN
|
||||
bool usingTestToken =
|
||||
StaticPrefs::security_webauth_webauthn_enable_softtoken();
|
||||
if (!usingTestToken && WinWebAuthnManager::AreWebAuthNApisAvailable()) {
|
||||
WinWebAuthnManager* mgr = WinWebAuthnManager::Get();
|
||||
if (mgr) {
|
||||
mgr->Sign(this, aTransactionId, aTransactionInfo);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mTransactionId.isSome()) {
|
||||
mRegisterPromiseRequest.DisconnectIfExists();
|
||||
mSignPromiseRequest.DisconnectIfExists();
|
||||
|
@ -262,6 +278,16 @@ mozilla::ipc::IPCResult WebAuthnTransactionParent::RecvRequestCancel(
|
|||
const Tainted<uint64_t>& aTransactionId) {
|
||||
::mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (WinWebAuthnManager::AreWebAuthNApisAvailable()) {
|
||||
WinWebAuthnManager* mgr = WinWebAuthnManager::Get();
|
||||
if (mgr) {
|
||||
mgr->Cancel(this, aTransactionId);
|
||||
}
|
||||
}
|
||||
// fall through in case the virtual token was used.
|
||||
#endif
|
||||
|
||||
if (mTransactionId.isNothing() ||
|
||||
!MOZ_IS_VALID(aTransactionId, mTransactionId.ref() == aTransactionId)) {
|
||||
return IPC_OK();
|
||||
|
@ -304,6 +330,16 @@ void WebAuthnTransactionParent::ActorDestroy(ActorDestroyReason aWhy) {
|
|||
// Called either by Send__delete__() in RecvDestroyMe() above, or when
|
||||
// the channel disconnects. Ensure the token manager forgets about us.
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (WinWebAuthnManager::AreWebAuthNApisAvailable()) {
|
||||
WinWebAuthnManager* mgr = WinWebAuthnManager::Get();
|
||||
if (mgr) {
|
||||
mgr->MaybeClearTransaction(this);
|
||||
}
|
||||
}
|
||||
// fall through in case the virtual token was used.
|
||||
#endif
|
||||
|
||||
if (mTransactionId.isSome()) {
|
||||
mRegisterPromiseRequest.DisconnectIfExists();
|
||||
mSignPromiseRequest.DisconnectIfExists();
|
||||
|
|
|
@ -0,0 +1,803 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/PWebAuthnTransactionParent.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsIWebAuthnAttObj.h"
|
||||
#include "nsTextFormatter.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
#include "AuthrsBridge_ffi.h"
|
||||
#include "WebAuthnEnumStrings.h"
|
||||
#include "WebAuthnTransportIdentifiers.h"
|
||||
#include "winwebauthn/webauthn.h"
|
||||
#include "WinWebAuthnManager.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
namespace {
|
||||
static mozilla::LazyLogModule gWinWebAuthnManagerLog("winwebauthnkeymanager");
|
||||
StaticAutoPtr<WinWebAuthnManager> gWinWebAuthnManager;
|
||||
static HMODULE gWinWebAuthnModule = 0;
|
||||
|
||||
static decltype(WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable)*
|
||||
gWinWebauthnIsUVPAA = nullptr;
|
||||
static decltype(WebAuthNAuthenticatorMakeCredential)*
|
||||
gWinWebauthnMakeCredential = nullptr;
|
||||
static decltype(WebAuthNFreeCredentialAttestation)*
|
||||
gWinWebauthnFreeCredentialAttestation = nullptr;
|
||||
static decltype(WebAuthNAuthenticatorGetAssertion)* gWinWebauthnGetAssertion =
|
||||
nullptr;
|
||||
static decltype(WebAuthNFreeAssertion)* gWinWebauthnFreeAssertion = nullptr;
|
||||
static decltype(WebAuthNGetCancellationId)* gWinWebauthnGetCancellationId =
|
||||
nullptr;
|
||||
static decltype(WebAuthNCancelCurrentOperation)*
|
||||
gWinWebauthnCancelCurrentOperation = nullptr;
|
||||
static decltype(WebAuthNGetErrorName)* gWinWebauthnGetErrorName = nullptr;
|
||||
static decltype(WebAuthNGetApiVersionNumber)* gWinWebauthnGetApiVersionNumber =
|
||||
nullptr;
|
||||
|
||||
} // namespace
|
||||
|
||||
/***********************************************************************
|
||||
* WinWebAuthnManager Implementation
|
||||
**********************************************************************/
|
||||
|
||||
constexpr uint32_t kMinWinWebAuthNApiVersion = WEBAUTHN_API_VERSION_1;
|
||||
|
||||
WinWebAuthnManager::WinWebAuthnManager() {
|
||||
// Create on the main thread to make sure ClearOnShutdown() works.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!gWinWebAuthnModule);
|
||||
|
||||
gWinWebAuthnModule = LoadLibrarySystem32(L"webauthn.dll");
|
||||
|
||||
if (gWinWebAuthnModule) {
|
||||
gWinWebauthnIsUVPAA = reinterpret_cast<
|
||||
decltype(WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable)*>(
|
||||
GetProcAddress(
|
||||
gWinWebAuthnModule,
|
||||
"WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable"));
|
||||
gWinWebauthnMakeCredential =
|
||||
reinterpret_cast<decltype(WebAuthNAuthenticatorMakeCredential)*>(
|
||||
GetProcAddress(gWinWebAuthnModule,
|
||||
"WebAuthNAuthenticatorMakeCredential"));
|
||||
gWinWebauthnFreeCredentialAttestation =
|
||||
reinterpret_cast<decltype(WebAuthNFreeCredentialAttestation)*>(
|
||||
GetProcAddress(gWinWebAuthnModule,
|
||||
"WebAuthNFreeCredentialAttestation"));
|
||||
gWinWebauthnGetAssertion =
|
||||
reinterpret_cast<decltype(WebAuthNAuthenticatorGetAssertion)*>(
|
||||
GetProcAddress(gWinWebAuthnModule,
|
||||
"WebAuthNAuthenticatorGetAssertion"));
|
||||
gWinWebauthnFreeAssertion =
|
||||
reinterpret_cast<decltype(WebAuthNFreeAssertion)*>(
|
||||
GetProcAddress(gWinWebAuthnModule, "WebAuthNFreeAssertion"));
|
||||
gWinWebauthnGetCancellationId =
|
||||
reinterpret_cast<decltype(WebAuthNGetCancellationId)*>(
|
||||
GetProcAddress(gWinWebAuthnModule, "WebAuthNGetCancellationId"));
|
||||
gWinWebauthnCancelCurrentOperation =
|
||||
reinterpret_cast<decltype(WebAuthNCancelCurrentOperation)*>(
|
||||
GetProcAddress(gWinWebAuthnModule,
|
||||
"WebAuthNCancelCurrentOperation"));
|
||||
gWinWebauthnGetErrorName =
|
||||
reinterpret_cast<decltype(WebAuthNGetErrorName)*>(
|
||||
GetProcAddress(gWinWebAuthnModule, "WebAuthNGetErrorName"));
|
||||
gWinWebauthnGetApiVersionNumber =
|
||||
reinterpret_cast<decltype(WebAuthNGetApiVersionNumber)*>(
|
||||
GetProcAddress(gWinWebAuthnModule, "WebAuthNGetApiVersionNumber"));
|
||||
|
||||
if (gWinWebauthnIsUVPAA && gWinWebauthnMakeCredential &&
|
||||
gWinWebauthnFreeCredentialAttestation && gWinWebauthnGetAssertion &&
|
||||
gWinWebauthnFreeAssertion && gWinWebauthnGetCancellationId &&
|
||||
gWinWebauthnCancelCurrentOperation && gWinWebauthnGetErrorName &&
|
||||
gWinWebauthnGetApiVersionNumber) {
|
||||
mWinWebAuthNApiVersion = gWinWebauthnGetApiVersionNumber();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WinWebAuthnManager::~WinWebAuthnManager() {
|
||||
if (gWinWebAuthnModule) {
|
||||
FreeLibrary(gWinWebAuthnModule);
|
||||
}
|
||||
gWinWebAuthnModule = 0;
|
||||
}
|
||||
|
||||
// static
|
||||
void WinWebAuthnManager::Initialize() {
|
||||
if (!gWinWebAuthnManager) {
|
||||
gWinWebAuthnManager = new WinWebAuthnManager();
|
||||
ClearOnShutdown(&gWinWebAuthnManager);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
WinWebAuthnManager* WinWebAuthnManager::Get() {
|
||||
MOZ_ASSERT(gWinWebAuthnManager);
|
||||
return gWinWebAuthnManager;
|
||||
}
|
||||
|
||||
uint32_t WinWebAuthnManager::GetWebAuthNApiVersion() {
|
||||
return mWinWebAuthNApiVersion;
|
||||
}
|
||||
|
||||
// static
|
||||
bool WinWebAuthnManager::AreWebAuthNApisAvailable() {
|
||||
WinWebAuthnManager* mgr = WinWebAuthnManager::Get();
|
||||
return mgr->GetWebAuthNApiVersion() >= kMinWinWebAuthNApiVersion;
|
||||
}
|
||||
|
||||
bool WinWebAuthnManager::
|
||||
IsUserVerifyingPlatformAuthenticatorAvailableInternal() {
|
||||
BOOL isUVPAA = FALSE;
|
||||
return (gWinWebauthnIsUVPAA(&isUVPAA) == S_OK && isUVPAA == TRUE);
|
||||
}
|
||||
|
||||
// static
|
||||
bool WinWebAuthnManager::IsUserVerifyingPlatformAuthenticatorAvailable() {
|
||||
if (WinWebAuthnManager::AreWebAuthNApisAvailable()) {
|
||||
return WinWebAuthnManager::Get()
|
||||
->IsUserVerifyingPlatformAuthenticatorAvailableInternal();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void WinWebAuthnManager::AbortTransaction(const uint64_t& aTransactionId,
|
||||
const nsresult& aError) {
|
||||
Unused << mTransactionParent->SendAbort(aTransactionId, aError);
|
||||
ClearTransaction();
|
||||
}
|
||||
|
||||
void WinWebAuthnManager::MaybeClearTransaction(
|
||||
PWebAuthnTransactionParent* aParent) {
|
||||
// Only clear if we've been requested to do so by our current transaction
|
||||
// parent.
|
||||
if (mTransactionParent == aParent) {
|
||||
ClearTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
void WinWebAuthnManager::ClearTransaction() { mTransactionParent = nullptr; }
|
||||
|
||||
void WinWebAuthnManager::Register(
|
||||
PWebAuthnTransactionParent* aTransactionParent,
|
||||
const uint64_t& aTransactionId, const WebAuthnMakeCredentialInfo& aInfo) {
|
||||
MOZ_LOG(gWinWebAuthnManagerLog, LogLevel::Debug, ("WinWebAuthNRegister"));
|
||||
|
||||
ClearTransaction();
|
||||
mTransactionParent = aTransactionParent;
|
||||
|
||||
BOOL HmacCreateSecret = FALSE;
|
||||
BOOL MinPinLength = FALSE;
|
||||
|
||||
// RP Information
|
||||
WEBAUTHN_RP_ENTITY_INFORMATION rpInfo = {
|
||||
WEBAUTHN_RP_ENTITY_INFORMATION_CURRENT_VERSION, aInfo.RpId().get(),
|
||||
nullptr, nullptr};
|
||||
|
||||
// User Information
|
||||
WEBAUTHN_USER_ENTITY_INFORMATION userInfo = {
|
||||
WEBAUTHN_USER_ENTITY_INFORMATION_CURRENT_VERSION,
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr};
|
||||
|
||||
// Client Data
|
||||
WEBAUTHN_CLIENT_DATA WebAuthNClientData = {
|
||||
WEBAUTHN_CLIENT_DATA_CURRENT_VERSION,
|
||||
(DWORD)aInfo.ClientDataJSON().Length(),
|
||||
(BYTE*)(aInfo.ClientDataJSON().get()), WEBAUTHN_HASH_ALGORITHM_SHA_256};
|
||||
|
||||
// Algorithms
|
||||
nsTArray<WEBAUTHN_COSE_CREDENTIAL_PARAMETER> coseParams;
|
||||
|
||||
// User Verification Requirement
|
||||
DWORD winUserVerificationReq = WEBAUTHN_USER_VERIFICATION_REQUIREMENT_ANY;
|
||||
|
||||
// Attachment
|
||||
DWORD winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_ANY;
|
||||
|
||||
// Resident Key
|
||||
BOOL winRequireResidentKey = FALSE;
|
||||
BOOL winPreferResidentKey = FALSE;
|
||||
|
||||
// AttestationConveyance
|
||||
DWORD winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_ANY;
|
||||
|
||||
rpInfo.pwszName = aInfo.Rp().Name().get();
|
||||
rpInfo.pwszIcon = nullptr;
|
||||
|
||||
userInfo.cbId = static_cast<DWORD>(aInfo.User().Id().Length());
|
||||
userInfo.pbId = const_cast<unsigned char*>(aInfo.User().Id().Elements());
|
||||
userInfo.pwszName = aInfo.User().Name().get();
|
||||
userInfo.pwszIcon = nullptr;
|
||||
userInfo.pwszDisplayName = aInfo.User().DisplayName().get();
|
||||
|
||||
for (const auto& coseAlg : aInfo.coseAlgs()) {
|
||||
WEBAUTHN_COSE_CREDENTIAL_PARAMETER coseAlgorithm = {
|
||||
WEBAUTHN_COSE_CREDENTIAL_PARAMETER_CURRENT_VERSION,
|
||||
WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY, coseAlg.alg()};
|
||||
coseParams.AppendElement(coseAlgorithm);
|
||||
}
|
||||
|
||||
const auto& sel = aInfo.AuthenticatorSelection();
|
||||
|
||||
const nsString& userVerificationRequirement =
|
||||
sel.userVerificationRequirement();
|
||||
// This mapping needs to be reviewed if values are added to the
|
||||
// UserVerificationRequirement enum.
|
||||
static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 2);
|
||||
if (userVerificationRequirement.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED)) {
|
||||
winUserVerificationReq = WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED;
|
||||
} else if (userVerificationRequirement.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED)) {
|
||||
winUserVerificationReq = WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED;
|
||||
} else if (userVerificationRequirement.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_DISCOURAGED)) {
|
||||
winUserVerificationReq = WEBAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED;
|
||||
} else {
|
||||
winUserVerificationReq = WEBAUTHN_USER_VERIFICATION_REQUIREMENT_ANY;
|
||||
}
|
||||
|
||||
if (sel.authenticatorAttachment().isSome()) {
|
||||
const nsString& authenticatorAttachment =
|
||||
sel.authenticatorAttachment().value();
|
||||
// This mapping needs to be reviewed if values are added to the
|
||||
// AuthenticatorAttachement enum.
|
||||
static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 2);
|
||||
if (authenticatorAttachment.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM)) {
|
||||
winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM;
|
||||
} else if (authenticatorAttachment.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM)) {
|
||||
winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM;
|
||||
} else {
|
||||
winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_ANY;
|
||||
}
|
||||
}
|
||||
|
||||
const nsString& residentKey = sel.residentKey();
|
||||
// This mapping needs to be reviewed if values are added to the
|
||||
// ResidentKeyRequirement enum.
|
||||
static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 2);
|
||||
if (residentKey.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_REQUIRED)) {
|
||||
winRequireResidentKey = TRUE;
|
||||
winPreferResidentKey = TRUE;
|
||||
} else if (residentKey.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_PREFERRED)) {
|
||||
winRequireResidentKey = FALSE;
|
||||
winPreferResidentKey = TRUE;
|
||||
} else if (residentKey.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_DISCOURAGED)) {
|
||||
winRequireResidentKey = FALSE;
|
||||
winPreferResidentKey = FALSE;
|
||||
} else {
|
||||
// WebAuthnManager::MakeCredential is supposed to assign one of the above
|
||||
// values, so this shouldn't happen.
|
||||
MOZ_ASSERT_UNREACHABLE();
|
||||
MaybeAbortRegister(aTransactionId, NS_ERROR_DOM_UNKNOWN_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
// AttestationConveyance
|
||||
const nsString& attestation = aInfo.attestationConveyancePreference();
|
||||
// This mapping needs to be reviewed if values are added to the
|
||||
// AttestationConveyancePreference enum.
|
||||
static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 2);
|
||||
if (attestation.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE)) {
|
||||
winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE;
|
||||
} else if (attestation.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT)) {
|
||||
winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT;
|
||||
} else if (attestation.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT)) {
|
||||
winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT;
|
||||
} else {
|
||||
winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_ANY;
|
||||
}
|
||||
|
||||
bool requestedCredProps = FALSE;
|
||||
|
||||
// The number of entries in rgExtension should match the number of supported
|
||||
// extensions.
|
||||
// Supported extensions: credProps, hmac-secret, minPinLength.
|
||||
WEBAUTHN_EXTENSION rgExtension[3] = {};
|
||||
DWORD cExtensions = 0;
|
||||
if (aInfo.Extensions().Length() >
|
||||
(int)(sizeof(rgExtension) / sizeof(rgExtension[0]))) {
|
||||
nsresult aError = NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
MaybeAbortRegister(aTransactionId, aError);
|
||||
return;
|
||||
}
|
||||
for (const WebAuthnExtension& ext : aInfo.Extensions()) {
|
||||
if (ext.type() == WebAuthnExtension::TWebAuthnExtensionCredProps) {
|
||||
requestedCredProps = ext.get_WebAuthnExtensionCredProps().credProps();
|
||||
}
|
||||
if (ext.type() == WebAuthnExtension::TWebAuthnExtensionHmacSecret) {
|
||||
HmacCreateSecret =
|
||||
ext.get_WebAuthnExtensionHmacSecret().hmacCreateSecret() == true;
|
||||
if (HmacCreateSecret) {
|
||||
rgExtension[cExtensions].pwszExtensionIdentifier =
|
||||
WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET;
|
||||
rgExtension[cExtensions].cbExtension = sizeof(BOOL);
|
||||
rgExtension[cExtensions].pvExtension = &HmacCreateSecret;
|
||||
cExtensions++;
|
||||
}
|
||||
}
|
||||
if (ext.type() == WebAuthnExtension::TWebAuthnExtensionMinPinLength) {
|
||||
MinPinLength =
|
||||
ext.get_WebAuthnExtensionMinPinLength().minPinLength() == true;
|
||||
if (MinPinLength) {
|
||||
rgExtension[cExtensions].pwszExtensionIdentifier =
|
||||
WEBAUTHN_EXTENSIONS_IDENTIFIER_MIN_PIN_LENGTH;
|
||||
rgExtension[cExtensions].cbExtension = sizeof(BOOL);
|
||||
rgExtension[cExtensions].pvExtension = &MinPinLength;
|
||||
cExtensions++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WEBAUTHN_COSE_CREDENTIAL_PARAMETERS WebAuthNCredentialParameters = {
|
||||
static_cast<DWORD>(coseParams.Length()), coseParams.Elements()};
|
||||
|
||||
// Exclude Credentials
|
||||
nsTArray<WEBAUTHN_CREDENTIAL_EX> excludeCredentials;
|
||||
WEBAUTHN_CREDENTIAL_EX* pExcludeCredentials = nullptr;
|
||||
nsTArray<WEBAUTHN_CREDENTIAL_EX*> excludeCredentialsPtrs;
|
||||
WEBAUTHN_CREDENTIAL_LIST excludeCredentialList = {0};
|
||||
WEBAUTHN_CREDENTIAL_LIST* pExcludeCredentialList = nullptr;
|
||||
|
||||
for (auto& cred : aInfo.ExcludeList()) {
|
||||
uint8_t transports = cred.transports();
|
||||
DWORD winTransports = 0;
|
||||
if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_USB) {
|
||||
winTransports |= WEBAUTHN_CTAP_TRANSPORT_USB;
|
||||
}
|
||||
if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_NFC) {
|
||||
winTransports |= WEBAUTHN_CTAP_TRANSPORT_NFC;
|
||||
}
|
||||
if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_BLE) {
|
||||
winTransports |= WEBAUTHN_CTAP_TRANSPORT_BLE;
|
||||
}
|
||||
if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_INTERNAL) {
|
||||
winTransports |= WEBAUTHN_CTAP_TRANSPORT_INTERNAL;
|
||||
}
|
||||
|
||||
WEBAUTHN_CREDENTIAL_EX credential = {
|
||||
WEBAUTHN_CREDENTIAL_EX_CURRENT_VERSION,
|
||||
static_cast<DWORD>(cred.id().Length()), (PBYTE)(cred.id().Elements()),
|
||||
WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY, winTransports};
|
||||
excludeCredentials.AppendElement(credential);
|
||||
}
|
||||
|
||||
if (!excludeCredentials.IsEmpty()) {
|
||||
pExcludeCredentials = excludeCredentials.Elements();
|
||||
for (DWORD i = 0; i < excludeCredentials.Length(); i++) {
|
||||
excludeCredentialsPtrs.AppendElement(&pExcludeCredentials[i]);
|
||||
}
|
||||
excludeCredentialList.cCredentials = excludeCredentials.Length();
|
||||
excludeCredentialList.ppCredentials = excludeCredentialsPtrs.Elements();
|
||||
pExcludeCredentialList = &excludeCredentialList;
|
||||
}
|
||||
|
||||
// MakeCredentialOptions
|
||||
WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS WebAuthNCredentialOptions = {
|
||||
WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_7,
|
||||
aInfo.TimeoutMS(),
|
||||
{0, NULL},
|
||||
{0, NULL},
|
||||
winAttachment,
|
||||
winRequireResidentKey,
|
||||
winUserVerificationReq,
|
||||
winAttestation,
|
||||
0, // Flags
|
||||
NULL, // CancellationId
|
||||
pExcludeCredentialList,
|
||||
WEBAUTHN_ENTERPRISE_ATTESTATION_NONE,
|
||||
WEBAUTHN_LARGE_BLOB_SUPPORT_NONE,
|
||||
winPreferResidentKey, // PreferResidentKey
|
||||
FALSE, // BrowserInPrivateMode
|
||||
FALSE, // EnablePrf
|
||||
NULL, // LinkedDevice
|
||||
0, // size of JsonExt
|
||||
NULL, // JsonExt
|
||||
};
|
||||
|
||||
GUID cancellationId = {0};
|
||||
if (gWinWebauthnGetCancellationId(&cancellationId) == S_OK) {
|
||||
WebAuthNCredentialOptions.pCancellationId = &cancellationId;
|
||||
mCancellationIds.emplace(aTransactionId, &cancellationId);
|
||||
}
|
||||
|
||||
if (cExtensions != 0) {
|
||||
WebAuthNCredentialOptions.Extensions.cExtensions = cExtensions;
|
||||
WebAuthNCredentialOptions.Extensions.pExtensions = rgExtension;
|
||||
}
|
||||
|
||||
PWEBAUTHN_CREDENTIAL_ATTESTATION pWebAuthNCredentialAttestation = nullptr;
|
||||
|
||||
// Bug 1518876: Get Window Handle from Content process for Windows WebAuthN
|
||||
// APIs
|
||||
HWND hWnd = GetForegroundWindow();
|
||||
|
||||
HRESULT hr = gWinWebauthnMakeCredential(
|
||||
hWnd, &rpInfo, &userInfo, &WebAuthNCredentialParameters,
|
||||
&WebAuthNClientData, &WebAuthNCredentialOptions,
|
||||
&pWebAuthNCredentialAttestation);
|
||||
|
||||
mCancellationIds.erase(aTransactionId);
|
||||
|
||||
if (hr == S_OK) {
|
||||
nsTArray<uint8_t> credentialId;
|
||||
credentialId.AppendElements(pWebAuthNCredentialAttestation->pbCredentialId,
|
||||
pWebAuthNCredentialAttestation->cbCredentialId);
|
||||
|
||||
nsTArray<uint8_t> authenticatorData;
|
||||
|
||||
authenticatorData.AppendElements(
|
||||
pWebAuthNCredentialAttestation->pbAuthenticatorData,
|
||||
pWebAuthNCredentialAttestation->cbAuthenticatorData);
|
||||
|
||||
nsTArray<uint8_t> attObject;
|
||||
attObject.AppendElements(
|
||||
pWebAuthNCredentialAttestation->pbAttestationObject,
|
||||
pWebAuthNCredentialAttestation->cbAttestationObject);
|
||||
|
||||
if (winAttestation == WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE) {
|
||||
// The anonymize flag in the nsIWebAuthnAttObj constructor causes the
|
||||
// attestation statement to be removed during deserialization. It also
|
||||
// causes the AAGUID to be zeroed out. If we can't deserialize the
|
||||
// existing attestation, then we can't ensure that it is anonymized, so we
|
||||
// act as though the user denied consent and we return NotAllowed.
|
||||
nsCOMPtr<nsIWebAuthnAttObj> anonymizedAttObj;
|
||||
nsresult rv = authrs_webauthn_att_obj_constructor(
|
||||
attObject,
|
||||
/* anonymize */ true, getter_AddRefs(anonymizedAttObj));
|
||||
if (NS_FAILED(rv)) {
|
||||
MaybeAbortRegister(aTransactionId, NS_ERROR_DOM_NOT_ALLOWED_ERR);
|
||||
return;
|
||||
}
|
||||
attObject.Clear();
|
||||
rv = anonymizedAttObj->GetAttestationObject(attObject);
|
||||
if (NS_FAILED(rv)) {
|
||||
MaybeAbortRegister(aTransactionId, NS_ERROR_DOM_NOT_ALLOWED_ERR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nsTArray<WebAuthnExtensionResult> extensions;
|
||||
if (pWebAuthNCredentialAttestation->dwVersion >=
|
||||
WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_2) {
|
||||
PCWEBAUTHN_EXTENSIONS pExtensionList =
|
||||
&pWebAuthNCredentialAttestation->Extensions;
|
||||
if (pExtensionList->cExtensions != 0 &&
|
||||
pExtensionList->pExtensions != NULL) {
|
||||
for (DWORD dwIndex = 0; dwIndex < pExtensionList->cExtensions;
|
||||
dwIndex++) {
|
||||
PWEBAUTHN_EXTENSION pExtension =
|
||||
&pExtensionList->pExtensions[dwIndex];
|
||||
if (pExtension->pwszExtensionIdentifier &&
|
||||
(0 == _wcsicmp(pExtension->pwszExtensionIdentifier,
|
||||
WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET)) &&
|
||||
pExtension->cbExtension == sizeof(BOOL)) {
|
||||
BOOL* pCredentialCreatedWithHmacSecret =
|
||||
(BOOL*)pExtension->pvExtension;
|
||||
if (*pCredentialCreatedWithHmacSecret) {
|
||||
extensions.AppendElement(WebAuthnExtensionResultHmacSecret(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WEBAUTHN_CREDENTIAL_ATTESTATION structs of version >= 4 always include a
|
||||
// flag to indicate whether a resident key was created. We copy that flag to
|
||||
// the credProps extension output only if the RP requested the credProps
|
||||
// extension.
|
||||
if (requestedCredProps && pWebAuthNCredentialAttestation->dwVersion >=
|
||||
WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_4) {
|
||||
BOOL rk = pWebAuthNCredentialAttestation->bResidentKey;
|
||||
extensions.AppendElement(WebAuthnExtensionResultCredProps(rk == TRUE));
|
||||
}
|
||||
|
||||
nsTArray<nsString> transports;
|
||||
if (pWebAuthNCredentialAttestation->dwVersion >=
|
||||
WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_3) {
|
||||
if (pWebAuthNCredentialAttestation->dwUsedTransport &
|
||||
WEBAUTHN_CTAP_TRANSPORT_USB) {
|
||||
transports.AppendElement(u"usb"_ns);
|
||||
}
|
||||
if (pWebAuthNCredentialAttestation->dwUsedTransport &
|
||||
WEBAUTHN_CTAP_TRANSPORT_NFC) {
|
||||
transports.AppendElement(u"nfc"_ns);
|
||||
}
|
||||
if (pWebAuthNCredentialAttestation->dwUsedTransport &
|
||||
WEBAUTHN_CTAP_TRANSPORT_BLE) {
|
||||
transports.AppendElement(u"ble"_ns);
|
||||
}
|
||||
if (pWebAuthNCredentialAttestation->dwUsedTransport &
|
||||
WEBAUTHN_CTAP_TRANSPORT_INTERNAL) {
|
||||
transports.AppendElement(u"internal"_ns);
|
||||
}
|
||||
}
|
||||
// WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_5 corresponds to
|
||||
// WEBAUTHN_API_VERSION_6 which is where WEBAUTHN_CTAP_TRANSPORT_HYBRID was
|
||||
// defined.
|
||||
if (pWebAuthNCredentialAttestation->dwVersion >=
|
||||
WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_5) {
|
||||
if (pWebAuthNCredentialAttestation->dwUsedTransport &
|
||||
WEBAUTHN_CTAP_TRANSPORT_HYBRID) {
|
||||
transports.AppendElement(u"hybrid"_ns);
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<nsString> authenticatorAttachment;
|
||||
if (pWebAuthNCredentialAttestation->dwVersion >=
|
||||
WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_3) {
|
||||
if (pWebAuthNCredentialAttestation->dwUsedTransport &
|
||||
WEBAUTHN_CTAP_TRANSPORT_INTERNAL) {
|
||||
authenticatorAttachment = Some(u"platform"_ns);
|
||||
} else {
|
||||
authenticatorAttachment = Some(u"cross-platform"_ns);
|
||||
}
|
||||
}
|
||||
|
||||
WebAuthnMakeCredentialResult result(aInfo.ClientDataJSON(), attObject,
|
||||
credentialId, transports, extensions,
|
||||
authenticatorAttachment);
|
||||
|
||||
Unused << mTransactionParent->SendConfirmRegister(aTransactionId, result);
|
||||
ClearTransaction();
|
||||
gWinWebauthnFreeCredentialAttestation(pWebAuthNCredentialAttestation);
|
||||
|
||||
} else {
|
||||
PCWSTR errorName = gWinWebauthnGetErrorName(hr);
|
||||
nsresult aError = NS_ERROR_DOM_ABORT_ERR;
|
||||
|
||||
if (_wcsicmp(errorName, L"InvalidStateError") == 0) {
|
||||
aError = NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
} else if (_wcsicmp(errorName, L"ConstraintError") == 0 ||
|
||||
_wcsicmp(errorName, L"UnknownError") == 0) {
|
||||
aError = NS_ERROR_DOM_UNKNOWN_ERR;
|
||||
} else if (_wcsicmp(errorName, L"NotSupportedError") == 0) {
|
||||
aError = NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
} else if (_wcsicmp(errorName, L"NotAllowedError") == 0) {
|
||||
aError = NS_ERROR_DOM_NOT_ALLOWED_ERR;
|
||||
}
|
||||
|
||||
MaybeAbortRegister(aTransactionId, aError);
|
||||
}
|
||||
}
|
||||
|
||||
void WinWebAuthnManager::MaybeAbortRegister(const uint64_t& aTransactionId,
|
||||
const nsresult& aError) {
|
||||
AbortTransaction(aTransactionId, aError);
|
||||
}
|
||||
|
||||
void WinWebAuthnManager::Sign(PWebAuthnTransactionParent* aTransactionParent,
|
||||
const uint64_t& aTransactionId,
|
||||
const WebAuthnGetAssertionInfo& aInfo) {
|
||||
MOZ_LOG(gWinWebAuthnManagerLog, LogLevel::Debug, ("WinWebAuthNSign"));
|
||||
|
||||
ClearTransaction();
|
||||
mTransactionParent = aTransactionParent;
|
||||
|
||||
// User Verification Requirement
|
||||
DWORD winUserVerificationReq = WEBAUTHN_USER_VERIFICATION_REQUIREMENT_ANY;
|
||||
|
||||
// RPID
|
||||
PCWSTR rpID = nullptr;
|
||||
|
||||
// Attachment
|
||||
DWORD winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_ANY;
|
||||
|
||||
// AppId
|
||||
BOOL bU2fAppIdUsed = FALSE;
|
||||
BOOL* pbU2fAppIdUsed = nullptr;
|
||||
PCWSTR winAppIdentifier = nullptr;
|
||||
|
||||
// Client Data
|
||||
WEBAUTHN_CLIENT_DATA WebAuthNClientData = {
|
||||
WEBAUTHN_CLIENT_DATA_CURRENT_VERSION,
|
||||
(DWORD)aInfo.ClientDataJSON().Length(),
|
||||
(BYTE*)(aInfo.ClientDataJSON().get()), WEBAUTHN_HASH_ALGORITHM_SHA_256};
|
||||
|
||||
for (const WebAuthnExtension& ext : aInfo.Extensions()) {
|
||||
if (ext.type() == WebAuthnExtension::TWebAuthnExtensionAppId) {
|
||||
winAppIdentifier = ext.get_WebAuthnExtensionAppId().appIdentifier().get();
|
||||
pbU2fAppIdUsed = &bU2fAppIdUsed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// RPID
|
||||
rpID = aInfo.RpId().get();
|
||||
|
||||
// User Verification Requirement
|
||||
const nsString& userVerificationReq = aInfo.userVerificationRequirement();
|
||||
// This mapping needs to be reviewed if values are added to the
|
||||
// UserVerificationRequirement enum.
|
||||
static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 2);
|
||||
if (userVerificationReq.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED)) {
|
||||
winUserVerificationReq = WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED;
|
||||
} else if (userVerificationReq.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED)) {
|
||||
winUserVerificationReq = WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED;
|
||||
} else if (userVerificationReq.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_DISCOURAGED)) {
|
||||
winUserVerificationReq = WEBAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED;
|
||||
} else {
|
||||
winUserVerificationReq = WEBAUTHN_USER_VERIFICATION_REQUIREMENT_ANY;
|
||||
}
|
||||
|
||||
// allow Credentials
|
||||
nsTArray<WEBAUTHN_CREDENTIAL_EX> allowCredentials;
|
||||
WEBAUTHN_CREDENTIAL_EX* pAllowCredentials = nullptr;
|
||||
nsTArray<WEBAUTHN_CREDENTIAL_EX*> allowCredentialsPtrs;
|
||||
WEBAUTHN_CREDENTIAL_LIST allowCredentialList = {0};
|
||||
WEBAUTHN_CREDENTIAL_LIST* pAllowCredentialList = nullptr;
|
||||
|
||||
for (auto& cred : aInfo.AllowList()) {
|
||||
uint8_t transports = cred.transports();
|
||||
DWORD winTransports = 0;
|
||||
if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_USB) {
|
||||
winTransports |= WEBAUTHN_CTAP_TRANSPORT_USB;
|
||||
}
|
||||
if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_NFC) {
|
||||
winTransports |= WEBAUTHN_CTAP_TRANSPORT_NFC;
|
||||
}
|
||||
if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_BLE) {
|
||||
winTransports |= WEBAUTHN_CTAP_TRANSPORT_BLE;
|
||||
}
|
||||
if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_INTERNAL) {
|
||||
winTransports |= WEBAUTHN_CTAP_TRANSPORT_INTERNAL;
|
||||
}
|
||||
|
||||
WEBAUTHN_CREDENTIAL_EX credential = {
|
||||
WEBAUTHN_CREDENTIAL_EX_CURRENT_VERSION,
|
||||
static_cast<DWORD>(cred.id().Length()), (PBYTE)(cred.id().Elements()),
|
||||
WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY, winTransports};
|
||||
allowCredentials.AppendElement(credential);
|
||||
}
|
||||
|
||||
if (allowCredentials.Length()) {
|
||||
pAllowCredentials = allowCredentials.Elements();
|
||||
for (DWORD i = 0; i < allowCredentials.Length(); i++) {
|
||||
allowCredentialsPtrs.AppendElement(&pAllowCredentials[i]);
|
||||
}
|
||||
allowCredentialList.cCredentials = allowCredentials.Length();
|
||||
allowCredentialList.ppCredentials = allowCredentialsPtrs.Elements();
|
||||
pAllowCredentialList = &allowCredentialList;
|
||||
}
|
||||
|
||||
WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS WebAuthNAssertionOptions = {
|
||||
WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_7,
|
||||
aInfo.TimeoutMS(),
|
||||
{0, NULL},
|
||||
{0, NULL},
|
||||
winAttachment,
|
||||
winUserVerificationReq,
|
||||
0, // dwFlags
|
||||
winAppIdentifier,
|
||||
pbU2fAppIdUsed,
|
||||
nullptr, // pCancellationId
|
||||
pAllowCredentialList,
|
||||
WEBAUTHN_CRED_LARGE_BLOB_OPERATION_NONE,
|
||||
0, // Size of CredLargeBlob
|
||||
NULL, // CredLargeBlob
|
||||
NULL, // HmacSecretSaltValues
|
||||
FALSE, // BrowserInPrivateMode
|
||||
NULL, // LinkedDevice
|
||||
FALSE, // AutoFill
|
||||
0, // Size of JsonExt
|
||||
NULL, // JsonExt
|
||||
};
|
||||
|
||||
GUID cancellationId = {0};
|
||||
if (gWinWebauthnGetCancellationId(&cancellationId) == S_OK) {
|
||||
WebAuthNAssertionOptions.pCancellationId = &cancellationId;
|
||||
mCancellationIds.emplace(aTransactionId, &cancellationId);
|
||||
}
|
||||
|
||||
PWEBAUTHN_ASSERTION pWebAuthNAssertion = nullptr;
|
||||
|
||||
// Bug 1518876: Get Window Handle from Content process for Windows WebAuthN
|
||||
// APIs
|
||||
HWND hWnd = GetForegroundWindow();
|
||||
|
||||
HRESULT hr =
|
||||
gWinWebauthnGetAssertion(hWnd, rpID, &WebAuthNClientData,
|
||||
&WebAuthNAssertionOptions, &pWebAuthNAssertion);
|
||||
|
||||
mCancellationIds.erase(aTransactionId);
|
||||
|
||||
if (hr == S_OK) {
|
||||
nsTArray<uint8_t> signature;
|
||||
signature.AppendElements(pWebAuthNAssertion->pbSignature,
|
||||
pWebAuthNAssertion->cbSignature);
|
||||
|
||||
nsTArray<uint8_t> keyHandle;
|
||||
keyHandle.AppendElements(pWebAuthNAssertion->Credential.pbId,
|
||||
pWebAuthNAssertion->Credential.cbId);
|
||||
|
||||
nsTArray<uint8_t> userHandle;
|
||||
userHandle.AppendElements(pWebAuthNAssertion->pbUserId,
|
||||
pWebAuthNAssertion->cbUserId);
|
||||
|
||||
nsTArray<uint8_t> authenticatorData;
|
||||
authenticatorData.AppendElements(pWebAuthNAssertion->pbAuthenticatorData,
|
||||
pWebAuthNAssertion->cbAuthenticatorData);
|
||||
|
||||
nsTArray<WebAuthnExtensionResult> extensions;
|
||||
|
||||
if (pbU2fAppIdUsed && *pbU2fAppIdUsed) {
|
||||
extensions.AppendElement(WebAuthnExtensionResultAppId(true));
|
||||
}
|
||||
|
||||
Maybe<nsString> authenticatorAttachment = Nothing(); // not available
|
||||
|
||||
WebAuthnGetAssertionResult result(aInfo.ClientDataJSON(), keyHandle,
|
||||
signature, authenticatorData, extensions,
|
||||
userHandle, authenticatorAttachment);
|
||||
|
||||
Unused << mTransactionParent->SendConfirmSign(aTransactionId, result);
|
||||
ClearTransaction();
|
||||
|
||||
gWinWebauthnFreeAssertion(pWebAuthNAssertion);
|
||||
|
||||
} else {
|
||||
PCWSTR errorName = gWinWebauthnGetErrorName(hr);
|
||||
nsresult aError = NS_ERROR_DOM_ABORT_ERR;
|
||||
|
||||
if (_wcsicmp(errorName, L"InvalidStateError") == 0) {
|
||||
aError = NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
} else if (_wcsicmp(errorName, L"ConstraintError") == 0 ||
|
||||
_wcsicmp(errorName, L"UnknownError") == 0) {
|
||||
aError = NS_ERROR_DOM_UNKNOWN_ERR;
|
||||
} else if (_wcsicmp(errorName, L"NotSupportedError") == 0) {
|
||||
aError = NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
} else if (_wcsicmp(errorName, L"NotAllowedError") == 0) {
|
||||
aError = NS_ERROR_DOM_NOT_ALLOWED_ERR;
|
||||
}
|
||||
|
||||
MaybeAbortSign(aTransactionId, aError);
|
||||
}
|
||||
}
|
||||
|
||||
void WinWebAuthnManager::MaybeAbortSign(const uint64_t& aTransactionId,
|
||||
const nsresult& aError) {
|
||||
AbortTransaction(aTransactionId, aError);
|
||||
}
|
||||
|
||||
void WinWebAuthnManager::Cancel(PWebAuthnTransactionParent* aParent,
|
||||
const Tainted<uint64_t>& aTransactionId) {
|
||||
if (mTransactionParent != aParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
ClearTransaction();
|
||||
|
||||
auto iter = mCancellationIds.find(
|
||||
MOZ_NO_VALIDATE(aTransactionId,
|
||||
"Transaction ID is checked against a global container, "
|
||||
"so an invalid entry can affect another origin's "
|
||||
"request. This issue is filed as Bug 1696159."));
|
||||
if (iter != mCancellationIds.end()) {
|
||||
gWinWebauthnCancelCurrentOperation(iter->second);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
|
@ -0,0 +1,52 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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_WinWebAuthnManager_h
|
||||
#define mozilla_dom_WinWebAuthnManager_h
|
||||
|
||||
#include "mozilla/dom/PWebAuthnTransaction.h"
|
||||
#include "mozilla/Tainting.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class WebAuthnTransactionParent;
|
||||
|
||||
class WinWebAuthnManager final {
|
||||
public:
|
||||
static WinWebAuthnManager* Get();
|
||||
void Register(PWebAuthnTransactionParent* aTransactionParent,
|
||||
const uint64_t& aTransactionId,
|
||||
const WebAuthnMakeCredentialInfo& aTransactionInfo);
|
||||
void Sign(PWebAuthnTransactionParent* aTransactionParent,
|
||||
const uint64_t& aTransactionId,
|
||||
const WebAuthnGetAssertionInfo& aTransactionInfo);
|
||||
void Cancel(PWebAuthnTransactionParent* aTransactionParent,
|
||||
const Tainted<uint64_t>& aTransactionId);
|
||||
void MaybeClearTransaction(PWebAuthnTransactionParent* aParent);
|
||||
static void Initialize();
|
||||
static bool IsUserVerifyingPlatformAuthenticatorAvailable();
|
||||
static bool AreWebAuthNApisAvailable();
|
||||
|
||||
WinWebAuthnManager();
|
||||
~WinWebAuthnManager();
|
||||
|
||||
private:
|
||||
void AbortTransaction(const uint64_t& aTransactionId, const nsresult& aError);
|
||||
void ClearTransaction();
|
||||
void MaybeAbortRegister(const uint64_t& aTransactionId,
|
||||
const nsresult& aError);
|
||||
void MaybeAbortSign(const uint64_t& aTransactionId, const nsresult& aError);
|
||||
bool IsUserVerifyingPlatformAuthenticatorAvailableInternal();
|
||||
uint32_t GetWebAuthNApiVersion();
|
||||
|
||||
PWebAuthnTransactionParent* mTransactionParent;
|
||||
uint32_t mWinWebAuthNApiVersion = 0;
|
||||
std::map<uint64_t, GUID*> mCancellationIds;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
#endif // mozilla_dom_WinWebAuthnManager_h
|
|
@ -1,814 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 "mozilla/dom/PWebAuthnTransactionParent.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
#include "nsTextFormatter.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
#include "WebAuthnEnumStrings.h"
|
||||
#include "WebAuthnTransportIdentifiers.h"
|
||||
#include "winwebauthn/webauthn.h"
|
||||
#include "WinWebAuthnService.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
namespace {
|
||||
StaticRWLock gWinWebAuthnModuleLock;
|
||||
|
||||
static HMODULE gWinWebAuthnModule = 0;
|
||||
|
||||
static decltype(WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable)*
|
||||
gWinWebauthnIsUVPAA = nullptr;
|
||||
static decltype(WebAuthNAuthenticatorMakeCredential)*
|
||||
gWinWebauthnMakeCredential = nullptr;
|
||||
static decltype(WebAuthNFreeCredentialAttestation)*
|
||||
gWinWebauthnFreeCredentialAttestation = nullptr;
|
||||
static decltype(WebAuthNAuthenticatorGetAssertion)* gWinWebauthnGetAssertion =
|
||||
nullptr;
|
||||
static decltype(WebAuthNFreeAssertion)* gWinWebauthnFreeAssertion = nullptr;
|
||||
static decltype(WebAuthNGetCancellationId)* gWinWebauthnGetCancellationId =
|
||||
nullptr;
|
||||
static decltype(WebAuthNCancelCurrentOperation)*
|
||||
gWinWebauthnCancelCurrentOperation = nullptr;
|
||||
static decltype(WebAuthNGetErrorName)* gWinWebauthnGetErrorName = nullptr;
|
||||
static decltype(WebAuthNGetApiVersionNumber)* gWinWebauthnGetApiVersionNumber =
|
||||
nullptr;
|
||||
|
||||
} // namespace
|
||||
|
||||
/***********************************************************************
|
||||
* WinWebAuthnService Implementation
|
||||
**********************************************************************/
|
||||
|
||||
constexpr uint32_t kMinWinWebAuthNApiVersion = WEBAUTHN_API_VERSION_1;
|
||||
|
||||
NS_IMPL_ISUPPORTS(WinWebAuthnService, nsIWebAuthnService)
|
||||
|
||||
/* static */
|
||||
nsresult WinWebAuthnService::EnsureWinWebAuthnModuleLoaded() {
|
||||
{
|
||||
StaticAutoReadLock lock(gWinWebAuthnModuleLock);
|
||||
if (gWinWebAuthnModule) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
StaticAutoWriteLock lock(gWinWebAuthnModuleLock);
|
||||
if (gWinWebAuthnModule) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
gWinWebAuthnModule = LoadLibrarySystem32(L"webauthn.dll");
|
||||
if (!gWinWebAuthnModule) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
gWinWebauthnIsUVPAA = reinterpret_cast<
|
||||
decltype(WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable)*>(
|
||||
GetProcAddress(gWinWebAuthnModule,
|
||||
"WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable"));
|
||||
gWinWebauthnMakeCredential =
|
||||
reinterpret_cast<decltype(WebAuthNAuthenticatorMakeCredential)*>(
|
||||
GetProcAddress(gWinWebAuthnModule,
|
||||
"WebAuthNAuthenticatorMakeCredential"));
|
||||
gWinWebauthnFreeCredentialAttestation =
|
||||
reinterpret_cast<decltype(WebAuthNFreeCredentialAttestation)*>(
|
||||
GetProcAddress(gWinWebAuthnModule,
|
||||
"WebAuthNFreeCredentialAttestation"));
|
||||
gWinWebauthnGetAssertion =
|
||||
reinterpret_cast<decltype(WebAuthNAuthenticatorGetAssertion)*>(
|
||||
GetProcAddress(gWinWebAuthnModule,
|
||||
"WebAuthNAuthenticatorGetAssertion"));
|
||||
gWinWebauthnFreeAssertion =
|
||||
reinterpret_cast<decltype(WebAuthNFreeAssertion)*>(
|
||||
GetProcAddress(gWinWebAuthnModule, "WebAuthNFreeAssertion"));
|
||||
gWinWebauthnGetCancellationId =
|
||||
reinterpret_cast<decltype(WebAuthNGetCancellationId)*>(
|
||||
GetProcAddress(gWinWebAuthnModule, "WebAuthNGetCancellationId"));
|
||||
gWinWebauthnCancelCurrentOperation =
|
||||
reinterpret_cast<decltype(WebAuthNCancelCurrentOperation)*>(
|
||||
GetProcAddress(gWinWebAuthnModule, "WebAuthNCancelCurrentOperation"));
|
||||
gWinWebauthnGetErrorName = reinterpret_cast<decltype(WebAuthNGetErrorName)*>(
|
||||
GetProcAddress(gWinWebAuthnModule, "WebAuthNGetErrorName"));
|
||||
gWinWebauthnGetApiVersionNumber =
|
||||
reinterpret_cast<decltype(WebAuthNGetApiVersionNumber)*>(
|
||||
GetProcAddress(gWinWebAuthnModule, "WebAuthNGetApiVersionNumber"));
|
||||
|
||||
if (!(gWinWebauthnIsUVPAA && gWinWebauthnMakeCredential &&
|
||||
gWinWebauthnFreeCredentialAttestation && gWinWebauthnGetAssertion &&
|
||||
gWinWebauthnFreeAssertion && gWinWebauthnGetCancellationId &&
|
||||
gWinWebauthnCancelCurrentOperation && gWinWebauthnGetErrorName &&
|
||||
gWinWebauthnGetApiVersionNumber)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
WinWebAuthnService::~WinWebAuthnService() {
|
||||
StaticAutoWriteLock lock(gWinWebAuthnModuleLock);
|
||||
if (gWinWebAuthnModule) {
|
||||
FreeLibrary(gWinWebAuthnModule);
|
||||
}
|
||||
gWinWebAuthnModule = 0;
|
||||
}
|
||||
|
||||
// static
|
||||
bool WinWebAuthnService::AreWebAuthNApisAvailable() {
|
||||
nsresult rv = EnsureWinWebAuthnModuleLoaded();
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
StaticAutoReadLock lock(gWinWebAuthnModuleLock);
|
||||
return gWinWebAuthnModule &&
|
||||
gWinWebauthnGetApiVersionNumber() >= kMinWinWebAuthNApiVersion;
|
||||
}
|
||||
|
||||
// static
|
||||
bool WinWebAuthnService::IsUserVerifyingPlatformAuthenticatorAvailable() {
|
||||
nsresult rv = EnsureWinWebAuthnModuleLoaded();
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
if (WinWebAuthnService::AreWebAuthNApisAvailable()) {
|
||||
BOOL isUVPAA = FALSE;
|
||||
StaticAutoReadLock lock(gWinWebAuthnModuleLock);
|
||||
return gWinWebAuthnModule && gWinWebauthnIsUVPAA(&isUVPAA) == S_OK &&
|
||||
isUVPAA == TRUE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WinWebAuthnService::Cancel(uint64_t aTransactionId) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WinWebAuthnService::Reset() {
|
||||
// Reset will never be the first function to use gWinWebAuthnModule, so
|
||||
// we shouldn't try to initialize it here.
|
||||
if (mTransactionId.isSome()) {
|
||||
StaticAutoReadLock lock(gWinWebAuthnModuleLock);
|
||||
if (gWinWebAuthnModule) {
|
||||
gWinWebauthnCancelCurrentOperation(&mCancellationId);
|
||||
}
|
||||
mTransactionId.reset();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WinWebAuthnService::MakeCredential(uint64_t aTransactionId,
|
||||
uint64_t browsingContextId,
|
||||
nsIWebAuthnRegisterArgs* aArgs,
|
||||
nsIWebAuthnRegisterPromise* aPromise) {
|
||||
nsresult rv = EnsureWinWebAuthnModuleLoaded();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
Reset();
|
||||
mTransactionId = Some(aTransactionId);
|
||||
{
|
||||
StaticAutoReadLock lock(gWinWebAuthnModuleLock);
|
||||
if (gWinWebauthnGetCancellationId(&mCancellationId) != S_OK) {
|
||||
// caller will reject promise
|
||||
return NS_ERROR_DOM_UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable(NS_NewRunnableFunction(
|
||||
"WinWebAuthnService::MakeCredential",
|
||||
[self = RefPtr{this}, aArgs = RefPtr{aArgs}, aPromise = RefPtr{aPromise},
|
||||
aCancellationId = mCancellationId]() mutable {
|
||||
// Take a read lock on gWinWebAuthnModuleLock to prevent the module from
|
||||
// being unloaded while the operation is in progress. This does not
|
||||
// prevent the operation from being cancelled, so it does not block a
|
||||
// clean shutdown.
|
||||
StaticAutoReadLock lock(gWinWebAuthnModuleLock);
|
||||
if (!gWinWebAuthnModule) {
|
||||
aPromise->Reject(NS_ERROR_DOM_UNKNOWN_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL HmacCreateSecret = FALSE;
|
||||
BOOL MinPinLength = FALSE;
|
||||
|
||||
// RP Information
|
||||
nsString rpId;
|
||||
Unused << aArgs->GetRpId(rpId);
|
||||
WEBAUTHN_RP_ENTITY_INFORMATION rpInfo = {
|
||||
WEBAUTHN_RP_ENTITY_INFORMATION_CURRENT_VERSION, rpId.get(), nullptr,
|
||||
nullptr};
|
||||
|
||||
// User Information
|
||||
WEBAUTHN_USER_ENTITY_INFORMATION userInfo = {
|
||||
WEBAUTHN_USER_ENTITY_INFORMATION_CURRENT_VERSION,
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr};
|
||||
|
||||
// Client Data
|
||||
nsCString clientDataJSON;
|
||||
Unused << aArgs->GetClientDataJSON(clientDataJSON);
|
||||
WEBAUTHN_CLIENT_DATA WebAuthNClientData = {
|
||||
WEBAUTHN_CLIENT_DATA_CURRENT_VERSION,
|
||||
(DWORD)clientDataJSON.Length(), (BYTE*)(clientDataJSON.get()),
|
||||
WEBAUTHN_HASH_ALGORITHM_SHA_256};
|
||||
|
||||
// User Verification Requirement
|
||||
DWORD winUserVerificationReq =
|
||||
WEBAUTHN_USER_VERIFICATION_REQUIREMENT_ANY;
|
||||
|
||||
// Resident Key
|
||||
BOOL winRequireResidentKey = FALSE;
|
||||
BOOL winPreferResidentKey = FALSE;
|
||||
|
||||
// AttestationConveyance
|
||||
DWORD winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_ANY;
|
||||
|
||||
nsString rpName;
|
||||
Unused << aArgs->GetRpName(rpName);
|
||||
rpInfo.pwszName = rpName.get();
|
||||
rpInfo.pwszIcon = nullptr;
|
||||
|
||||
nsTArray<uint8_t> userId;
|
||||
Unused << aArgs->GetUserId(userId);
|
||||
userInfo.cbId = static_cast<DWORD>(userId.Length());
|
||||
userInfo.pbId = const_cast<unsigned char*>(userId.Elements());
|
||||
|
||||
nsString userName;
|
||||
Unused << aArgs->GetUserName(userName);
|
||||
userInfo.pwszName = userName.get();
|
||||
|
||||
userInfo.pwszIcon = nullptr;
|
||||
|
||||
nsString userDisplayName;
|
||||
Unused << aArgs->GetUserDisplayName(userDisplayName);
|
||||
userInfo.pwszDisplayName = userDisplayName.get();
|
||||
|
||||
// Algorithms
|
||||
nsTArray<WEBAUTHN_COSE_CREDENTIAL_PARAMETER> coseParams;
|
||||
nsTArray<int32_t> coseAlgs;
|
||||
Unused << aArgs->GetCoseAlgs(coseAlgs);
|
||||
for (const int32_t& coseAlg : coseAlgs) {
|
||||
WEBAUTHN_COSE_CREDENTIAL_PARAMETER coseAlgorithm = {
|
||||
WEBAUTHN_COSE_CREDENTIAL_PARAMETER_CURRENT_VERSION,
|
||||
WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY, coseAlg};
|
||||
coseParams.AppendElement(coseAlgorithm);
|
||||
}
|
||||
|
||||
nsString userVerificationReq;
|
||||
Unused << aArgs->GetUserVerification(userVerificationReq);
|
||||
// This mapping needs to be reviewed if values are added to the
|
||||
// UserVerificationRequirement enum.
|
||||
static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 2);
|
||||
if (userVerificationReq.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED)) {
|
||||
winUserVerificationReq =
|
||||
WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED;
|
||||
} else if (userVerificationReq.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED)) {
|
||||
winUserVerificationReq =
|
||||
WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED;
|
||||
} else if (userVerificationReq.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_DISCOURAGED)) {
|
||||
winUserVerificationReq =
|
||||
WEBAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED;
|
||||
} else {
|
||||
winUserVerificationReq = WEBAUTHN_USER_VERIFICATION_REQUIREMENT_ANY;
|
||||
}
|
||||
|
||||
// Attachment
|
||||
DWORD winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_ANY;
|
||||
nsString authenticatorAttachment;
|
||||
nsresult rv =
|
||||
aArgs->GetAuthenticatorAttachment(authenticatorAttachment);
|
||||
if (rv != NS_ERROR_NOT_AVAILABLE) {
|
||||
if (NS_FAILED(rv)) {
|
||||
aPromise->Reject(rv);
|
||||
return;
|
||||
}
|
||||
// This mapping needs to be reviewed if values are added to the
|
||||
// AuthenticatorAttachement enum.
|
||||
static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 2);
|
||||
if (authenticatorAttachment.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM)) {
|
||||
winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM;
|
||||
} else if (
|
||||
authenticatorAttachment.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM)) {
|
||||
winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM;
|
||||
} else {
|
||||
winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_ANY;
|
||||
}
|
||||
}
|
||||
|
||||
nsString residentKey;
|
||||
Unused << aArgs->GetResidentKey(residentKey);
|
||||
// This mapping needs to be reviewed if values are added to the
|
||||
// ResidentKeyRequirement enum.
|
||||
static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 2);
|
||||
if (residentKey.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_REQUIRED)) {
|
||||
winRequireResidentKey = TRUE;
|
||||
winPreferResidentKey = TRUE;
|
||||
} else if (residentKey.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_PREFERRED)) {
|
||||
winRequireResidentKey = FALSE;
|
||||
winPreferResidentKey = TRUE;
|
||||
} else if (residentKey.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_DISCOURAGED)) {
|
||||
winRequireResidentKey = FALSE;
|
||||
winPreferResidentKey = FALSE;
|
||||
} else {
|
||||
// WebAuthnManager::MakeCredential is supposed to assign one of the
|
||||
// above values, so this shouldn't happen.
|
||||
MOZ_ASSERT_UNREACHABLE();
|
||||
aPromise->Reject(NS_ERROR_DOM_UNKNOWN_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
// AttestationConveyance
|
||||
nsString attestation;
|
||||
Unused << aArgs->GetAttestationConveyancePreference(attestation);
|
||||
bool anonymize = false;
|
||||
// This mapping needs to be reviewed if values are added to the
|
||||
// AttestationConveyancePreference enum.
|
||||
static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 2);
|
||||
if (attestation.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE)) {
|
||||
winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE;
|
||||
anonymize = true;
|
||||
} else if (
|
||||
attestation.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT)) {
|
||||
winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT;
|
||||
} else if (attestation.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT)) {
|
||||
winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT;
|
||||
} else {
|
||||
winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_ANY;
|
||||
}
|
||||
|
||||
bool requestedCredProps;
|
||||
Unused << aArgs->GetCredProps(&requestedCredProps);
|
||||
|
||||
bool requestedMinPinLength;
|
||||
Unused << aArgs->GetMinPinLength(&requestedMinPinLength);
|
||||
|
||||
bool requestedHmacCreateSecret;
|
||||
Unused << aArgs->GetHmacCreateSecret(&requestedHmacCreateSecret);
|
||||
|
||||
// Extensions that might require an entry: hmac-secret, minPinLength.
|
||||
WEBAUTHN_EXTENSION rgExtension[2] = {};
|
||||
DWORD cExtensions = 0;
|
||||
if (requestedHmacCreateSecret) {
|
||||
HmacCreateSecret = TRUE;
|
||||
rgExtension[cExtensions].pwszExtensionIdentifier =
|
||||
WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET;
|
||||
rgExtension[cExtensions].cbExtension = sizeof(BOOL);
|
||||
rgExtension[cExtensions].pvExtension = &HmacCreateSecret;
|
||||
cExtensions++;
|
||||
}
|
||||
if (requestedMinPinLength) {
|
||||
MinPinLength = TRUE;
|
||||
rgExtension[cExtensions].pwszExtensionIdentifier =
|
||||
WEBAUTHN_EXTENSIONS_IDENTIFIER_MIN_PIN_LENGTH;
|
||||
rgExtension[cExtensions].cbExtension = sizeof(BOOL);
|
||||
rgExtension[cExtensions].pvExtension = &MinPinLength;
|
||||
cExtensions++;
|
||||
}
|
||||
|
||||
WEBAUTHN_COSE_CREDENTIAL_PARAMETERS WebAuthNCredentialParameters = {
|
||||
static_cast<DWORD>(coseParams.Length()), coseParams.Elements()};
|
||||
|
||||
// Exclude Credentials
|
||||
nsTArray<nsTArray<uint8_t>> excludeList;
|
||||
Unused << aArgs->GetExcludeList(excludeList);
|
||||
|
||||
nsTArray<uint8_t> excludeListTransports;
|
||||
Unused << aArgs->GetExcludeListTransports(excludeListTransports);
|
||||
|
||||
if (excludeList.Length() != excludeListTransports.Length()) {
|
||||
aPromise->Reject(NS_ERROR_DOM_UNKNOWN_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<WEBAUTHN_CREDENTIAL_EX> excludeCredentials;
|
||||
WEBAUTHN_CREDENTIAL_EX* pExcludeCredentials = nullptr;
|
||||
nsTArray<WEBAUTHN_CREDENTIAL_EX*> excludeCredentialsPtrs;
|
||||
WEBAUTHN_CREDENTIAL_LIST excludeCredentialList = {0};
|
||||
WEBAUTHN_CREDENTIAL_LIST* pExcludeCredentialList = nullptr;
|
||||
|
||||
for (size_t i = 0; i < excludeList.Length(); i++) {
|
||||
nsTArray<uint8_t>& cred = excludeList[i];
|
||||
uint8_t& transports = excludeListTransports[i];
|
||||
DWORD winTransports = 0;
|
||||
if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_USB) {
|
||||
winTransports |= WEBAUTHN_CTAP_TRANSPORT_USB;
|
||||
}
|
||||
if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_NFC) {
|
||||
winTransports |= WEBAUTHN_CTAP_TRANSPORT_NFC;
|
||||
}
|
||||
if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_BLE) {
|
||||
winTransports |= WEBAUTHN_CTAP_TRANSPORT_BLE;
|
||||
}
|
||||
if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_INTERNAL) {
|
||||
winTransports |= WEBAUTHN_CTAP_TRANSPORT_INTERNAL;
|
||||
}
|
||||
|
||||
WEBAUTHN_CREDENTIAL_EX credential = {
|
||||
WEBAUTHN_CREDENTIAL_EX_CURRENT_VERSION,
|
||||
static_cast<DWORD>(cred.Length()), (PBYTE)(cred.Elements()),
|
||||
WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY, winTransports};
|
||||
excludeCredentials.AppendElement(credential);
|
||||
}
|
||||
|
||||
if (!excludeCredentials.IsEmpty()) {
|
||||
pExcludeCredentials = excludeCredentials.Elements();
|
||||
for (DWORD i = 0; i < excludeCredentials.Length(); i++) {
|
||||
excludeCredentialsPtrs.AppendElement(&pExcludeCredentials[i]);
|
||||
}
|
||||
excludeCredentialList.cCredentials = excludeCredentials.Length();
|
||||
excludeCredentialList.ppCredentials =
|
||||
excludeCredentialsPtrs.Elements();
|
||||
pExcludeCredentialList = &excludeCredentialList;
|
||||
}
|
||||
|
||||
uint32_t timeout_u32;
|
||||
Unused << aArgs->GetTimeoutMS(&timeout_u32);
|
||||
DWORD timeout = timeout_u32;
|
||||
|
||||
// MakeCredentialOptions
|
||||
WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS
|
||||
WebAuthNCredentialOptions = {
|
||||
WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_7,
|
||||
timeout,
|
||||
{0, NULL},
|
||||
{0, NULL},
|
||||
winAttachment,
|
||||
winRequireResidentKey,
|
||||
winUserVerificationReq,
|
||||
winAttestation,
|
||||
0, // Flags
|
||||
&aCancellationId, // CancellationId
|
||||
pExcludeCredentialList,
|
||||
WEBAUTHN_ENTERPRISE_ATTESTATION_NONE,
|
||||
WEBAUTHN_LARGE_BLOB_SUPPORT_NONE,
|
||||
winPreferResidentKey, // PreferResidentKey
|
||||
FALSE, // BrowserInPrivateMode
|
||||
FALSE, // EnablePrf
|
||||
NULL, // LinkedDevice
|
||||
0, // size of JsonExt
|
||||
NULL, // JsonExt
|
||||
};
|
||||
|
||||
if (cExtensions != 0) {
|
||||
WebAuthNCredentialOptions.Extensions.cExtensions = cExtensions;
|
||||
WebAuthNCredentialOptions.Extensions.pExtensions = rgExtension;
|
||||
}
|
||||
|
||||
PWEBAUTHN_CREDENTIAL_ATTESTATION pWebAuthNCredentialAttestation =
|
||||
nullptr;
|
||||
|
||||
// Bug 1518876: Get Window Handle from Content process for Windows
|
||||
// WebAuthN APIs
|
||||
HWND hWnd = GetForegroundWindow();
|
||||
|
||||
HRESULT hr = gWinWebauthnMakeCredential(
|
||||
hWnd, &rpInfo, &userInfo, &WebAuthNCredentialParameters,
|
||||
&WebAuthNClientData, &WebAuthNCredentialOptions,
|
||||
&pWebAuthNCredentialAttestation);
|
||||
|
||||
if (hr == S_OK) {
|
||||
RefPtr<WebAuthnRegisterResult> result = new WebAuthnRegisterResult(
|
||||
clientDataJSON, pWebAuthNCredentialAttestation);
|
||||
|
||||
// WEBAUTHN_CREDENTIAL_ATTESTATION structs of version >= 4 always
|
||||
// include a flag to indicate whether a resident key was created. We
|
||||
// copy that flag to the credProps extension output only if the RP
|
||||
// requested the credProps extension.
|
||||
if (requestedCredProps &&
|
||||
pWebAuthNCredentialAttestation->dwVersion >=
|
||||
WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_4) {
|
||||
BOOL rk = pWebAuthNCredentialAttestation->bResidentKey;
|
||||
Unused << result->SetCredPropsRk(rk == TRUE);
|
||||
}
|
||||
gWinWebauthnFreeCredentialAttestation(pWebAuthNCredentialAttestation);
|
||||
|
||||
if (anonymize) {
|
||||
nsresult rv = result->Anonymize();
|
||||
if (NS_FAILED(rv)) {
|
||||
aPromise->Reject(NS_ERROR_DOM_NOT_ALLOWED_ERR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
aPromise->Resolve(result);
|
||||
} else {
|
||||
PCWSTR errorName = gWinWebauthnGetErrorName(hr);
|
||||
nsresult aError = NS_ERROR_DOM_ABORT_ERR;
|
||||
|
||||
if (_wcsicmp(errorName, L"InvalidStateError") == 0) {
|
||||
aError = NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
} else if (_wcsicmp(errorName, L"ConstraintError") == 0 ||
|
||||
_wcsicmp(errorName, L"UnknownError") == 0) {
|
||||
aError = NS_ERROR_DOM_UNKNOWN_ERR;
|
||||
} else if (_wcsicmp(errorName, L"NotSupportedError") == 0) {
|
||||
aError = NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
} else if (_wcsicmp(errorName, L"NotAllowedError") == 0) {
|
||||
aError = NS_ERROR_DOM_NOT_ALLOWED_ERR;
|
||||
}
|
||||
|
||||
aPromise->Reject(aError);
|
||||
}
|
||||
}));
|
||||
|
||||
NS_DispatchBackgroundTask(runnable, NS_DISPATCH_EVENT_MAY_BLOCK);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WinWebAuthnService::GetAssertion(uint64_t aTransactionId,
|
||||
uint64_t browsingContextId,
|
||||
nsIWebAuthnSignArgs* aArgs,
|
||||
nsIWebAuthnSignPromise* aPromise) {
|
||||
nsresult rv = EnsureWinWebAuthnModuleLoaded();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
Reset();
|
||||
mTransactionId = Some(aTransactionId);
|
||||
{
|
||||
StaticAutoReadLock lock(gWinWebAuthnModuleLock);
|
||||
if (gWinWebauthnGetCancellationId(&mCancellationId) != S_OK) {
|
||||
// caller will reject promise
|
||||
return NS_ERROR_DOM_UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable(NS_NewRunnableFunction(
|
||||
"WinWebAuthnService::MakeCredential",
|
||||
[self = RefPtr{this}, aArgs = RefPtr{aArgs}, aPromise = RefPtr{aPromise},
|
||||
aCancellationId = mCancellationId]() mutable {
|
||||
// Take a read lock on gWinWebAuthnModuleLock to prevent the module from
|
||||
// being unloaded while the operation is in progress. This does not
|
||||
// prevent the operation from being cancelled, so it does not block a
|
||||
// clean shutdown.
|
||||
StaticAutoReadLock lock(gWinWebAuthnModuleLock);
|
||||
if (!gWinWebAuthnModule) {
|
||||
aPromise->Reject(NS_ERROR_DOM_UNKNOWN_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
// Attachment
|
||||
DWORD winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_ANY;
|
||||
|
||||
// AppId
|
||||
BOOL bAppIdUsed = FALSE;
|
||||
BOOL* pbAppIdUsed = nullptr;
|
||||
PCWSTR winAppIdentifier = nullptr;
|
||||
|
||||
// Client Data
|
||||
nsCString clientDataJSON;
|
||||
Unused << aArgs->GetClientDataJSON(clientDataJSON);
|
||||
WEBAUTHN_CLIENT_DATA WebAuthNClientData = {
|
||||
WEBAUTHN_CLIENT_DATA_CURRENT_VERSION,
|
||||
(DWORD)clientDataJSON.Length(), (BYTE*)(clientDataJSON.get()),
|
||||
WEBAUTHN_HASH_ALGORITHM_SHA_256};
|
||||
|
||||
nsString appId;
|
||||
nsresult rv = aArgs->GetAppId(appId);
|
||||
if (rv != NS_ERROR_NOT_AVAILABLE) {
|
||||
if (NS_FAILED(rv)) {
|
||||
aPromise->Reject(rv);
|
||||
return;
|
||||
}
|
||||
winAppIdentifier = appId.get();
|
||||
pbAppIdUsed = &bAppIdUsed;
|
||||
}
|
||||
|
||||
// RPID
|
||||
nsString rpId;
|
||||
Unused << aArgs->GetRpId(rpId);
|
||||
|
||||
// User Verification Requirement
|
||||
nsString userVerificationReq;
|
||||
Unused << aArgs->GetUserVerification(userVerificationReq);
|
||||
DWORD winUserVerificationReq;
|
||||
// This mapping needs to be reviewed if values are added to the
|
||||
// UserVerificationRequirement enum.
|
||||
static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 2);
|
||||
if (userVerificationReq.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED)) {
|
||||
winUserVerificationReq =
|
||||
WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED;
|
||||
} else if (userVerificationReq.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED)) {
|
||||
winUserVerificationReq =
|
||||
WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED;
|
||||
} else if (userVerificationReq.EqualsLiteral(
|
||||
MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_DISCOURAGED)) {
|
||||
winUserVerificationReq =
|
||||
WEBAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED;
|
||||
} else {
|
||||
winUserVerificationReq = WEBAUTHN_USER_VERIFICATION_REQUIREMENT_ANY;
|
||||
}
|
||||
|
||||
// allow Credentials
|
||||
nsTArray<nsTArray<uint8_t>> allowList;
|
||||
Unused << aArgs->GetAllowList(allowList);
|
||||
|
||||
nsTArray<uint8_t> allowListTransports;
|
||||
Unused << aArgs->GetAllowListTransports(allowListTransports);
|
||||
|
||||
if (allowList.Length() != allowListTransports.Length()) {
|
||||
aPromise->Reject(NS_ERROR_DOM_UNKNOWN_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<WEBAUTHN_CREDENTIAL_EX> allowCredentials;
|
||||
WEBAUTHN_CREDENTIAL_EX* pAllowCredentials = nullptr;
|
||||
nsTArray<WEBAUTHN_CREDENTIAL_EX*> allowCredentialsPtrs;
|
||||
WEBAUTHN_CREDENTIAL_LIST allowCredentialList = {0};
|
||||
WEBAUTHN_CREDENTIAL_LIST* pAllowCredentialList = nullptr;
|
||||
|
||||
for (size_t i = 0; i < allowList.Length(); i++) {
|
||||
nsTArray<uint8_t>& cred = allowList[i];
|
||||
uint8_t& transports = allowListTransports[i];
|
||||
DWORD winTransports = 0;
|
||||
if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_USB) {
|
||||
winTransports |= WEBAUTHN_CTAP_TRANSPORT_USB;
|
||||
}
|
||||
if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_NFC) {
|
||||
winTransports |= WEBAUTHN_CTAP_TRANSPORT_NFC;
|
||||
}
|
||||
if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_BLE) {
|
||||
winTransports |= WEBAUTHN_CTAP_TRANSPORT_BLE;
|
||||
}
|
||||
if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_INTERNAL) {
|
||||
winTransports |= WEBAUTHN_CTAP_TRANSPORT_INTERNAL;
|
||||
}
|
||||
|
||||
WEBAUTHN_CREDENTIAL_EX credential = {
|
||||
WEBAUTHN_CREDENTIAL_EX_CURRENT_VERSION,
|
||||
static_cast<DWORD>(cred.Length()), (PBYTE)(cred.Elements()),
|
||||
WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY, winTransports};
|
||||
allowCredentials.AppendElement(credential);
|
||||
}
|
||||
|
||||
if (allowCredentials.Length()) {
|
||||
pAllowCredentials = allowCredentials.Elements();
|
||||
for (DWORD i = 0; i < allowCredentials.Length(); i++) {
|
||||
allowCredentialsPtrs.AppendElement(&pAllowCredentials[i]);
|
||||
}
|
||||
allowCredentialList.cCredentials = allowCredentials.Length();
|
||||
allowCredentialList.ppCredentials = allowCredentialsPtrs.Elements();
|
||||
pAllowCredentialList = &allowCredentialList;
|
||||
}
|
||||
|
||||
uint32_t timeout_u32;
|
||||
Unused << aArgs->GetTimeoutMS(&timeout_u32);
|
||||
DWORD timeout = timeout_u32;
|
||||
|
||||
WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS WebAuthNAssertionOptions =
|
||||
{
|
||||
WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_7,
|
||||
timeout,
|
||||
{0, NULL},
|
||||
{0, NULL},
|
||||
winAttachment,
|
||||
winUserVerificationReq,
|
||||
0, // dwFlags
|
||||
winAppIdentifier,
|
||||
pbAppIdUsed,
|
||||
&aCancellationId, // CancellationId
|
||||
pAllowCredentialList,
|
||||
WEBAUTHN_CRED_LARGE_BLOB_OPERATION_NONE,
|
||||
0, // Size of CredLargeBlob
|
||||
NULL, // CredLargeBlob
|
||||
NULL, // HmacSecretSaltValues
|
||||
FALSE, // BrowserInPrivateMode
|
||||
NULL, // LinkedDevice
|
||||
FALSE, // AutoFill
|
||||
0, // Size of JsonExt
|
||||
NULL, // JsonExt
|
||||
};
|
||||
|
||||
PWEBAUTHN_ASSERTION pWebAuthNAssertion = nullptr;
|
||||
|
||||
// Bug 1518876: Get Window Handle from Content process for Windows
|
||||
// WebAuthN APIs
|
||||
HWND hWnd = GetForegroundWindow();
|
||||
|
||||
HRESULT hr = gWinWebauthnGetAssertion(
|
||||
hWnd, rpId.get(), &WebAuthNClientData, &WebAuthNAssertionOptions,
|
||||
&pWebAuthNAssertion);
|
||||
|
||||
if (hr == S_OK) {
|
||||
RefPtr<WebAuthnSignResult> result =
|
||||
new WebAuthnSignResult(clientDataJSON, pWebAuthNAssertion);
|
||||
gWinWebauthnFreeAssertion(pWebAuthNAssertion);
|
||||
if (winAppIdentifier != nullptr) {
|
||||
// The gWinWebauthnGetAssertion call modified bAppIdUsed through
|
||||
// a pointer provided in WebAuthNAssertionOptions.
|
||||
Unused << result->SetUsedAppId(bAppIdUsed == TRUE);
|
||||
}
|
||||
aPromise->Resolve(result);
|
||||
} else {
|
||||
PCWSTR errorName = gWinWebauthnGetErrorName(hr);
|
||||
nsresult aError = NS_ERROR_DOM_ABORT_ERR;
|
||||
|
||||
if (_wcsicmp(errorName, L"InvalidStateError") == 0) {
|
||||
aError = NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
} else if (_wcsicmp(errorName, L"ConstraintError") == 0 ||
|
||||
_wcsicmp(errorName, L"UnknownError") == 0) {
|
||||
aError = NS_ERROR_DOM_UNKNOWN_ERR;
|
||||
} else if (_wcsicmp(errorName, L"NotSupportedError") == 0) {
|
||||
aError = NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
} else if (_wcsicmp(errorName, L"NotAllowedError") == 0) {
|
||||
aError = NS_ERROR_DOM_NOT_ALLOWED_ERR;
|
||||
}
|
||||
|
||||
aPromise->Reject(aError);
|
||||
}
|
||||
}));
|
||||
|
||||
NS_DispatchBackgroundTask(runnable, NS_DISPATCH_EVENT_MAY_BLOCK);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WinWebAuthnService::PinCallback(uint64_t aTransactionId,
|
||||
const nsACString& aPin) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WinWebAuthnService::ResumeMakeCredential(uint64_t aTransactionId,
|
||||
bool aForceNoneAttestation) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WinWebAuthnService::SelectionCallback(uint64_t aTransactionId,
|
||||
uint64_t aIndex) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WinWebAuthnService::AddVirtualAuthenticator(
|
||||
const nsACString& protocol, const nsACString& transport,
|
||||
bool hasResidentKey, bool hasUserVerification, bool isUserConsenting,
|
||||
bool isUserVerified, uint64_t* _retval) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WinWebAuthnService::RemoveVirtualAuthenticator(uint64_t authenticatorId) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WinWebAuthnService::AddCredential(uint64_t authenticatorId,
|
||||
const nsACString& credentialId,
|
||||
bool isResidentCredential,
|
||||
const nsACString& rpId,
|
||||
const nsACString& privateKey,
|
||||
const nsACString& userHandle,
|
||||
uint32_t signCount) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WinWebAuthnService::GetCredentials(
|
||||
uint64_t authenticatorId,
|
||||
nsTArray<RefPtr<nsICredentialParameters>>& _retval) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WinWebAuthnService::RemoveCredential(uint64_t authenticatorId,
|
||||
const nsACString& credentialId) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WinWebAuthnService::RemoveAllCredentials(uint64_t authenticatorId) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WinWebAuthnService::SetUserVerified(uint64_t authenticatorId,
|
||||
bool isUserVerified) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
|
@ -1,38 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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_WinWebAuthnService_h
|
||||
#define mozilla_dom_WinWebAuthnService_h
|
||||
|
||||
#include "mozilla/dom/PWebAuthnTransaction.h"
|
||||
#include "mozilla/Tainting.h"
|
||||
#include "nsIWebAuthnService.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class WinWebAuthnService final : public nsIWebAuthnService {
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIWEBAUTHNSERVICE
|
||||
|
||||
static bool IsUserVerifyingPlatformAuthenticatorAvailable();
|
||||
static bool AreWebAuthNApisAvailable();
|
||||
static nsresult EnsureWinWebAuthnModuleLoaded();
|
||||
|
||||
WinWebAuthnService() = default;
|
||||
|
||||
private:
|
||||
~WinWebAuthnService();
|
||||
|
||||
uint32_t GetWebAuthNApiVersion();
|
||||
|
||||
Maybe<uint64_t> mTransactionId;
|
||||
GUID mCancellationId;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
#endif // mozilla_dom_WinWebAuthnService_h
|
|
@ -177,14 +177,6 @@ impl WebAuthnRegisterResult {
|
|||
}
|
||||
}
|
||||
|
||||
xpcom_method!(get_hmac_create_secret => GetHmacCreateSecret() -> bool);
|
||||
fn get_hmac_create_secret(&self) -> Result<bool, nsresult> {
|
||||
let Some(hmac_create_secret) = self.result.extensions.hmac_create_secret else {
|
||||
return Err(NS_ERROR_NOT_AVAILABLE);
|
||||
};
|
||||
Ok(hmac_create_secret)
|
||||
}
|
||||
|
||||
xpcom_method!(get_cred_props_rk => GetCredPropsRk() -> bool);
|
||||
fn get_cred_props_rk(&self) -> Result<bool, nsresult> {
|
||||
let Some(cred_props) = &self.result.extensions.cred_props else {
|
||||
|
@ -310,11 +302,6 @@ impl WebAuthnSignResult {
|
|||
fn get_used_app_id(&self) -> Result<bool, nsresult> {
|
||||
self.result.extensions.app_id.ok_or(NS_ERROR_NOT_AVAILABLE)
|
||||
}
|
||||
|
||||
xpcom_method!(set_used_app_id => SetUsedAppId(aUsedAppId: bool));
|
||||
fn set_used_app_id(&self, _used_app_id: bool) -> Result<(), nsresult> {
|
||||
Err(NS_ERROR_NOT_IMPLEMENTED)
|
||||
}
|
||||
}
|
||||
|
||||
// A transaction may create a channel to ask a user for additional input, e.g. a PIN. The Sender
|
||||
|
|
|
@ -76,10 +76,10 @@ if CONFIG["OS_ARCH"] == "WINNT":
|
|||
|
||||
if CONFIG["OS_TARGET"] == "WINNT":
|
||||
EXPORTS.mozilla.dom += [
|
||||
"WinWebAuthnService.h",
|
||||
"WinWebAuthnManager.h",
|
||||
]
|
||||
UNIFIED_SOURCES += [
|
||||
"WinWebAuthnService.cpp",
|
||||
"WinWebAuthnManager.cpp",
|
||||
]
|
||||
|
||||
MOCHITEST_MANIFESTS += ["tests/mochitest.ini"]
|
||||
|
|
|
@ -14,8 +14,6 @@ interface nsIWebAuthnRegisterArgs : nsISupports {
|
|||
|
||||
readonly attribute Array<octet> challenge;
|
||||
|
||||
readonly attribute ACString clientDataJSON;
|
||||
|
||||
readonly attribute Array<octet> clientDataHash;
|
||||
|
||||
// A PublicKeyCredentialRpEntity
|
||||
|
@ -70,8 +68,6 @@ interface nsIWebAuthnSignArgs : nsISupports {
|
|||
|
||||
readonly attribute Array<octet> challenge;
|
||||
|
||||
readonly attribute ACString clientDataJSON;
|
||||
|
||||
readonly attribute Array<octet> clientDataHash;
|
||||
|
||||
// The spec defines this as a sequence<PublicKeyCredentialDescriptor>,
|
||||
|
|
|
@ -23,7 +23,8 @@ interface nsIWebAuthnRegisterResult : nsISupports {
|
|||
|
||||
readonly attribute Array<AString> transports;
|
||||
|
||||
readonly attribute bool hmacCreateSecret;
|
||||
// bug 1593571
|
||||
// readonly attribute bool hmacCreateSecret;
|
||||
|
||||
[must_use] attribute bool credPropsRk;
|
||||
|
||||
|
@ -56,7 +57,7 @@ interface nsIWebAuthnSignResult : nsISupports {
|
|||
[must_use] readonly attribute ACString userName;
|
||||
|
||||
// appId field of AuthenticationExtensionsClientOutputs (Optional)
|
||||
[must_use] attribute bool usedAppId;
|
||||
[must_use] readonly attribute bool usedAppId;
|
||||
|
||||
[must_use] readonly attribute AString authenticatorAttachment;
|
||||
};
|
||||
|
|
|
@ -103,6 +103,9 @@
|
|||
#include "mozilla/dom/AbstractRange.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/WebIDLGlobalNameHash.h"
|
||||
#ifdef XP_WIN
|
||||
# include "mozilla/dom/WinWebAuthnManager.h"
|
||||
#endif
|
||||
#include "mozilla/dom/PointerEventHandler.h"
|
||||
#include "mozilla/dom/RemoteWorkerService.h"
|
||||
#include "mozilla/dom/BlobURLProtocolHandler.h"
|
||||
|
@ -253,6 +256,10 @@ nsresult nsLayoutStatics::Initialize() {
|
|||
// This must be initialized on the main-thread.
|
||||
mozilla::RemoteLazyInputStreamStorage::Initialize();
|
||||
|
||||
#ifdef XP_WIN
|
||||
mozilla::dom::WinWebAuthnManager::Initialize();
|
||||
#endif
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
// On content process we initialize these components when PContentChild is
|
||||
// fully initialized.
|
||||
|
|
Загрузка…
Ссылка в новой задаче