Backed out changeset b462e7b742d8 (bug 1908261) for causing multiple reftest failures...
[gecko.git] / dom / webauthn / WinWebAuthnService.cpp
blob56dfa8c19a387921c6d6cb63793204cf0ad1ddeb
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/dom/PWebAuthnTransactionParent.h"
8 #include "mozilla/ipc/BackgroundParent.h"
9 #include "mozilla/Assertions.h"
10 #include "mozilla/MozPromise.h"
11 #include "mozilla/Preferences.h"
12 #include "mozilla/ScopeExit.h"
13 #include "mozilla/StaticMutex.h"
14 #include "mozilla/Unused.h"
16 #include "nsTextFormatter.h"
17 #include "nsWindowsHelpers.h"
18 #include "WebAuthnAutoFillEntry.h"
19 #include "WebAuthnEnumStrings.h"
20 #include "WebAuthnResult.h"
21 #include "WebAuthnTransportIdentifiers.h"
22 #include "winwebauthn/webauthn.h"
23 #include "WinWebAuthnService.h"
25 namespace mozilla::dom {
27 namespace {
28 StaticRWLock gWinWebAuthnModuleLock;
30 static bool gWinWebAuthnModuleUnusable = false;
31 static HMODULE gWinWebAuthnModule = 0;
33 static decltype(WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable)*
34 gWinWebauthnIsUVPAA = nullptr;
35 static decltype(WebAuthNAuthenticatorMakeCredential)*
36 gWinWebauthnMakeCredential = nullptr;
37 static decltype(WebAuthNFreeCredentialAttestation)*
38 gWinWebauthnFreeCredentialAttestation = nullptr;
39 static decltype(WebAuthNAuthenticatorGetAssertion)* gWinWebauthnGetAssertion =
40 nullptr;
41 static decltype(WebAuthNFreeAssertion)* gWinWebauthnFreeAssertion = nullptr;
42 static decltype(WebAuthNGetCancellationId)* gWinWebauthnGetCancellationId =
43 nullptr;
44 static decltype(WebAuthNCancelCurrentOperation)*
45 gWinWebauthnCancelCurrentOperation = nullptr;
46 static decltype(WebAuthNGetErrorName)* gWinWebauthnGetErrorName = nullptr;
47 static decltype(WebAuthNGetApiVersionNumber)* gWinWebauthnGetApiVersionNumber =
48 nullptr;
49 static decltype(WebAuthNGetPlatformCredentialList)*
50 gWinWebauthnGetPlatformCredentialList = nullptr;
51 static decltype(WebAuthNFreePlatformCredentialList)*
52 gWinWebauthnFreePlatformCredentialList = nullptr;
54 } // namespace
56 /***********************************************************************
57 * WinWebAuthnService Implementation
58 **********************************************************************/
60 constexpr uint32_t kMinWinWebAuthNApiVersion = WEBAUTHN_API_VERSION_1;
62 NS_IMPL_ISUPPORTS(WinWebAuthnService, nsIWebAuthnService)
64 /* static */
65 nsresult WinWebAuthnService::EnsureWinWebAuthnModuleLoaded() {
67 StaticAutoReadLock moduleLock(gWinWebAuthnModuleLock);
68 if (gWinWebAuthnModule) {
69 // The module is already loaded.
70 return NS_OK;
72 if (gWinWebAuthnModuleUnusable) {
73 // A previous attempt to load the module failed.
74 return NS_ERROR_NOT_AVAILABLE;
78 StaticAutoWriteLock lock(gWinWebAuthnModuleLock);
79 if (gWinWebAuthnModule) {
80 // Another thread successfully loaded the module while we were waiting.
81 return NS_OK;
83 if (gWinWebAuthnModuleUnusable) {
84 // Another thread failed to load the module while we were waiting.
85 return NS_ERROR_NOT_AVAILABLE;
88 gWinWebAuthnModule = LoadLibrarySystem32(L"webauthn.dll");
89 auto markModuleUnusable = MakeScopeExit([]() {
90 if (gWinWebAuthnModule) {
91 FreeLibrary(gWinWebAuthnModule);
92 gWinWebAuthnModule = 0;
94 gWinWebAuthnModuleUnusable = true;
95 });
97 if (!gWinWebAuthnModule) {
98 return NS_ERROR_NOT_AVAILABLE;
101 gWinWebauthnIsUVPAA = reinterpret_cast<
102 decltype(WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable)*>(
103 GetProcAddress(gWinWebAuthnModule,
104 "WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable"));
105 gWinWebauthnMakeCredential =
106 reinterpret_cast<decltype(WebAuthNAuthenticatorMakeCredential)*>(
107 GetProcAddress(gWinWebAuthnModule,
108 "WebAuthNAuthenticatorMakeCredential"));
109 gWinWebauthnFreeCredentialAttestation =
110 reinterpret_cast<decltype(WebAuthNFreeCredentialAttestation)*>(
111 GetProcAddress(gWinWebAuthnModule,
112 "WebAuthNFreeCredentialAttestation"));
113 gWinWebauthnGetAssertion =
114 reinterpret_cast<decltype(WebAuthNAuthenticatorGetAssertion)*>(
115 GetProcAddress(gWinWebAuthnModule,
116 "WebAuthNAuthenticatorGetAssertion"));
117 gWinWebauthnFreeAssertion =
118 reinterpret_cast<decltype(WebAuthNFreeAssertion)*>(
119 GetProcAddress(gWinWebAuthnModule, "WebAuthNFreeAssertion"));
120 gWinWebauthnGetCancellationId =
121 reinterpret_cast<decltype(WebAuthNGetCancellationId)*>(
122 GetProcAddress(gWinWebAuthnModule, "WebAuthNGetCancellationId"));
123 gWinWebauthnCancelCurrentOperation =
124 reinterpret_cast<decltype(WebAuthNCancelCurrentOperation)*>(
125 GetProcAddress(gWinWebAuthnModule, "WebAuthNCancelCurrentOperation"));
126 gWinWebauthnGetErrorName = reinterpret_cast<decltype(WebAuthNGetErrorName)*>(
127 GetProcAddress(gWinWebAuthnModule, "WebAuthNGetErrorName"));
128 gWinWebauthnGetApiVersionNumber =
129 reinterpret_cast<decltype(WebAuthNGetApiVersionNumber)*>(
130 GetProcAddress(gWinWebAuthnModule, "WebAuthNGetApiVersionNumber"));
132 if (!(gWinWebauthnIsUVPAA && gWinWebauthnMakeCredential &&
133 gWinWebauthnFreeCredentialAttestation && gWinWebauthnGetAssertion &&
134 gWinWebauthnFreeAssertion && gWinWebauthnGetCancellationId &&
135 gWinWebauthnCancelCurrentOperation && gWinWebauthnGetErrorName &&
136 gWinWebauthnGetApiVersionNumber)) {
137 return NS_ERROR_NOT_AVAILABLE;
140 DWORD version = gWinWebauthnGetApiVersionNumber();
142 if (version >= WEBAUTHN_API_VERSION_4) {
143 gWinWebauthnGetPlatformCredentialList =
144 reinterpret_cast<decltype(WebAuthNGetPlatformCredentialList)*>(
145 GetProcAddress(gWinWebAuthnModule,
146 "WebAuthNGetPlatformCredentialList"));
147 gWinWebauthnFreePlatformCredentialList =
148 reinterpret_cast<decltype(WebAuthNFreePlatformCredentialList)*>(
149 GetProcAddress(gWinWebAuthnModule,
150 "WebAuthNFreePlatformCredentialList"));
151 if (!(gWinWebauthnGetPlatformCredentialList &&
152 gWinWebauthnFreePlatformCredentialList)) {
153 return NS_ERROR_NOT_AVAILABLE;
157 // Bug 1869584: In some of our tests, a content process can end up here due to
158 // a call to WinWebAuthnService::AreWebAuthNApisAvailable. This causes us to
159 // fail an assertion in Preferences::SetBool, which is parent-process only.
160 if (XRE_IsParentProcess()) {
161 NS_DispatchToMainThread(NS_NewRunnableFunction(__func__, [version]() {
162 Preferences::SetBool("security.webauthn.show_ms_settings_link",
163 version >= WEBAUTHN_API_VERSION_7);
164 }));
167 markModuleUnusable.release();
168 return NS_OK;
171 WinWebAuthnService::~WinWebAuthnService() {
172 StaticAutoWriteLock lock(gWinWebAuthnModuleLock);
173 if (gWinWebAuthnModule) {
174 FreeLibrary(gWinWebAuthnModule);
176 gWinWebAuthnModule = 0;
179 // static
180 bool WinWebAuthnService::AreWebAuthNApisAvailable() {
181 nsresult rv = EnsureWinWebAuthnModuleLoaded();
182 NS_ENSURE_SUCCESS(rv, false);
184 StaticAutoReadLock moduleLock(gWinWebAuthnModuleLock);
185 return gWinWebAuthnModule &&
186 gWinWebauthnGetApiVersionNumber() >= kMinWinWebAuthNApiVersion;
189 NS_IMETHODIMP
190 WinWebAuthnService::GetIsUVPAA(bool* aAvailable) {
191 nsresult rv = EnsureWinWebAuthnModuleLoaded();
192 NS_ENSURE_SUCCESS(rv, rv);
194 if (WinWebAuthnService::AreWebAuthNApisAvailable()) {
195 BOOL isUVPAA = FALSE;
196 StaticAutoReadLock moduleLock(gWinWebAuthnModuleLock);
197 *aAvailable = gWinWebAuthnModule && gWinWebauthnIsUVPAA(&isUVPAA) == S_OK &&
198 isUVPAA == TRUE;
199 } else {
200 *aAvailable = false;
202 return NS_OK;
205 NS_IMETHODIMP
206 WinWebAuthnService::Cancel(uint64_t aTransactionId) {
207 return NS_ERROR_NOT_IMPLEMENTED;
210 NS_IMETHODIMP
211 WinWebAuthnService::Reset() {
212 // Reset will never be the first function to use gWinWebAuthnModule, so
213 // we shouldn't try to initialize it here.
214 auto guard = mTransactionState.Lock();
215 if (guard->isSome()) {
216 StaticAutoReadLock moduleLock(gWinWebAuthnModuleLock);
217 if (gWinWebAuthnModule) {
218 const GUID cancellationId = guard->ref().cancellationId;
219 gWinWebauthnCancelCurrentOperation(&cancellationId);
221 if (guard->ref().pendingSignPromise.isSome()) {
222 // This request was never dispatched to the platform API, so
223 // we need to reject the promise ourselves.
224 guard->ref().pendingSignPromise.ref()->Reject(
225 NS_ERROR_DOM_NOT_ALLOWED_ERR);
227 guard->reset();
230 return NS_OK;
233 NS_IMETHODIMP
234 WinWebAuthnService::MakeCredential(uint64_t aTransactionId,
235 uint64_t aBrowsingContextId,
236 nsIWebAuthnRegisterArgs* aArgs,
237 nsIWebAuthnRegisterPromise* aPromise) {
238 nsresult rv = EnsureWinWebAuthnModuleLoaded();
239 NS_ENSURE_SUCCESS(rv, rv);
241 Reset();
242 auto guard = mTransactionState.Lock();
243 StaticAutoReadLock moduleLock(gWinWebAuthnModuleLock);
244 GUID cancellationId;
245 if (gWinWebauthnGetCancellationId(&cancellationId) != S_OK) {
246 // caller will reject promise
247 return NS_ERROR_DOM_UNKNOWN_ERR;
249 *guard = Some(TransactionState{
250 aTransactionId,
251 aBrowsingContextId,
252 Nothing(),
253 Nothing(),
254 cancellationId,
257 nsCOMPtr<nsIRunnable> runnable(NS_NewRunnableFunction(
258 "WinWebAuthnService::MakeCredential",
259 [self = RefPtr{this}, aArgs = RefPtr{aArgs}, aPromise = RefPtr{aPromise},
260 cancellationId]() mutable {
261 // Take a read lock on gWinWebAuthnModuleLock to prevent the module from
262 // being unloaded while the operation is in progress. This does not
263 // prevent the operation from being cancelled, so it does not block a
264 // clean shutdown.
265 StaticAutoReadLock moduleLock(gWinWebAuthnModuleLock);
266 if (!gWinWebAuthnModule) {
267 aPromise->Reject(NS_ERROR_DOM_UNKNOWN_ERR);
268 return;
271 BOOL HmacCreateSecret = FALSE;
272 BOOL MinPinLength = FALSE;
274 // RP Information
275 nsString rpId;
276 Unused << aArgs->GetRpId(rpId);
277 WEBAUTHN_RP_ENTITY_INFORMATION rpInfo = {
278 WEBAUTHN_RP_ENTITY_INFORMATION_CURRENT_VERSION, rpId.get(), nullptr,
279 nullptr};
281 // User Information
282 WEBAUTHN_USER_ENTITY_INFORMATION userInfo = {
283 WEBAUTHN_USER_ENTITY_INFORMATION_CURRENT_VERSION,
285 nullptr,
286 nullptr,
287 nullptr,
288 nullptr};
290 // Client Data
291 nsCString clientDataJSON;
292 Unused << aArgs->GetClientDataJSON(clientDataJSON);
293 WEBAUTHN_CLIENT_DATA WebAuthNClientData = {
294 WEBAUTHN_CLIENT_DATA_CURRENT_VERSION,
295 (DWORD)clientDataJSON.Length(), (BYTE*)(clientDataJSON.get()),
296 WEBAUTHN_HASH_ALGORITHM_SHA_256};
298 // User Verification Requirement
299 DWORD winUserVerificationReq =
300 WEBAUTHN_USER_VERIFICATION_REQUIREMENT_ANY;
302 // Resident Key Requirement.
303 BOOL winRequireResidentKey = FALSE; // Will be set to TRUE if and only
304 // if residentKey = "required"
305 BOOL winPreferResidentKey = FALSE; // Will be set to TRUE if and only
306 // if residentKey = "preferred"
308 // AttestationConveyance
309 DWORD winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_ANY;
311 // Prf
312 BOOL winEnablePrf = FALSE;
314 nsString rpName;
315 Unused << aArgs->GetRpName(rpName);
316 rpInfo.pwszName = rpName.get();
317 rpInfo.pwszIcon = nullptr;
319 nsTArray<uint8_t> userId;
320 Unused << aArgs->GetUserId(userId);
321 userInfo.cbId = static_cast<DWORD>(userId.Length());
322 userInfo.pbId = const_cast<unsigned char*>(userId.Elements());
324 nsString userName;
325 Unused << aArgs->GetUserName(userName);
326 userInfo.pwszName = userName.get();
328 userInfo.pwszIcon = nullptr;
330 nsString userDisplayName;
331 Unused << aArgs->GetUserDisplayName(userDisplayName);
332 userInfo.pwszDisplayName = userDisplayName.get();
334 // Algorithms
335 nsTArray<WEBAUTHN_COSE_CREDENTIAL_PARAMETER> coseParams;
336 nsTArray<int32_t> coseAlgs;
337 Unused << aArgs->GetCoseAlgs(coseAlgs);
338 for (const int32_t& coseAlg : coseAlgs) {
339 WEBAUTHN_COSE_CREDENTIAL_PARAMETER coseAlgorithm = {
340 WEBAUTHN_COSE_CREDENTIAL_PARAMETER_CURRENT_VERSION,
341 WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY, coseAlg};
342 coseParams.AppendElement(coseAlgorithm);
345 nsString userVerificationReq;
346 Unused << aArgs->GetUserVerification(userVerificationReq);
347 // This mapping needs to be reviewed if values are added to the
348 // UserVerificationRequirement enum.
349 static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 3);
350 if (userVerificationReq.EqualsLiteral(
351 MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED)) {
352 winUserVerificationReq =
353 WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED;
354 } else if (userVerificationReq.EqualsLiteral(
355 MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED)) {
356 winUserVerificationReq =
357 WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED;
358 } else if (userVerificationReq.EqualsLiteral(
359 MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_DISCOURAGED)) {
360 winUserVerificationReq =
361 WEBAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED;
362 } else {
363 winUserVerificationReq = WEBAUTHN_USER_VERIFICATION_REQUIREMENT_ANY;
366 // Attachment
367 DWORD winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_ANY;
368 nsString authenticatorAttachment;
369 nsresult rv =
370 aArgs->GetAuthenticatorAttachment(authenticatorAttachment);
371 if (rv != NS_ERROR_NOT_AVAILABLE) {
372 if (NS_FAILED(rv)) {
373 aPromise->Reject(rv);
374 return;
376 // This mapping needs to be reviewed if values are added to the
377 // AuthenticatorAttachement enum.
378 static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 3);
379 if (authenticatorAttachment.EqualsLiteral(
380 MOZ_WEBAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM)) {
381 winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM;
382 } else if (
383 authenticatorAttachment.EqualsLiteral(
384 MOZ_WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM)) {
385 winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM;
386 } else {
387 winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_ANY;
391 nsString residentKey;
392 Unused << aArgs->GetResidentKey(residentKey);
393 // This mapping needs to be reviewed if values are added to the
394 // ResidentKeyRequirement enum.
395 static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 3);
396 if (residentKey.EqualsLiteral(
397 MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_REQUIRED)) {
398 winRequireResidentKey = TRUE;
399 winPreferResidentKey = FALSE;
400 } else if (residentKey.EqualsLiteral(
401 MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_PREFERRED)) {
402 winRequireResidentKey = FALSE;
403 winPreferResidentKey = TRUE;
404 } else if (residentKey.EqualsLiteral(
405 MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_DISCOURAGED)) {
406 winRequireResidentKey = FALSE;
407 winPreferResidentKey = FALSE;
408 } else {
409 // WebAuthnManager::MakeCredential is supposed to assign one of the
410 // above values, so this shouldn't happen.
411 MOZ_ASSERT_UNREACHABLE();
412 aPromise->Reject(NS_ERROR_DOM_UNKNOWN_ERR);
413 return;
416 // AttestationConveyance
417 nsString attestation;
418 Unused << aArgs->GetAttestationConveyancePreference(attestation);
419 // This mapping needs to be reviewed if values are added to the
420 // AttestationConveyancePreference enum.
421 static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 3);
422 if (attestation.EqualsLiteral(
423 MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE)) {
424 winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE;
425 } else if (
426 attestation.EqualsLiteral(
427 MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT)) {
428 winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT;
429 } else if (attestation.EqualsLiteral(
430 MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT)) {
431 winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT;
432 } else {
433 winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_ANY;
436 bool requestedPrf;
437 Unused << aArgs->GetPrf(&requestedPrf);
438 if (requestedPrf) {
439 winEnablePrf = TRUE;
442 bool requestedCredProps;
443 Unused << aArgs->GetCredProps(&requestedCredProps);
445 bool requestedMinPinLength;
446 Unused << aArgs->GetMinPinLength(&requestedMinPinLength);
448 bool requestedHmacCreateSecret;
449 Unused << aArgs->GetHmacCreateSecret(&requestedHmacCreateSecret);
451 // Extensions that might require an entry: hmac-secret, minPinLength.
452 WEBAUTHN_EXTENSION rgExtension[2] = {};
453 DWORD cExtensions = 0;
454 if (requestedPrf || requestedHmacCreateSecret) {
455 HmacCreateSecret = TRUE;
456 rgExtension[cExtensions].pwszExtensionIdentifier =
457 WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET;
458 rgExtension[cExtensions].cbExtension = sizeof(BOOL);
459 rgExtension[cExtensions].pvExtension = &HmacCreateSecret;
460 cExtensions++;
462 if (requestedMinPinLength) {
463 MinPinLength = TRUE;
464 rgExtension[cExtensions].pwszExtensionIdentifier =
465 WEBAUTHN_EXTENSIONS_IDENTIFIER_MIN_PIN_LENGTH;
466 rgExtension[cExtensions].cbExtension = sizeof(BOOL);
467 rgExtension[cExtensions].pvExtension = &MinPinLength;
468 cExtensions++;
471 WEBAUTHN_COSE_CREDENTIAL_PARAMETERS WebAuthNCredentialParameters = {
472 static_cast<DWORD>(coseParams.Length()), coseParams.Elements()};
474 // Exclude Credentials
475 nsTArray<nsTArray<uint8_t>> excludeList;
476 Unused << aArgs->GetExcludeList(excludeList);
478 nsTArray<uint8_t> excludeListTransports;
479 Unused << aArgs->GetExcludeListTransports(excludeListTransports);
481 if (excludeList.Length() != excludeListTransports.Length()) {
482 aPromise->Reject(NS_ERROR_DOM_UNKNOWN_ERR);
483 return;
486 nsTArray<WEBAUTHN_CREDENTIAL_EX> excludeCredentials;
487 WEBAUTHN_CREDENTIAL_EX* pExcludeCredentials = nullptr;
488 nsTArray<WEBAUTHN_CREDENTIAL_EX*> excludeCredentialsPtrs;
489 WEBAUTHN_CREDENTIAL_LIST excludeCredentialList = {0};
490 WEBAUTHN_CREDENTIAL_LIST* pExcludeCredentialList = nullptr;
492 for (size_t i = 0; i < excludeList.Length(); i++) {
493 nsTArray<uint8_t>& cred = excludeList[i];
494 uint8_t& transports = excludeListTransports[i];
495 DWORD winTransports = 0;
496 if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_USB) {
497 winTransports |= WEBAUTHN_CTAP_TRANSPORT_USB;
499 if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_NFC) {
500 winTransports |= WEBAUTHN_CTAP_TRANSPORT_NFC;
502 if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_BLE) {
503 winTransports |= WEBAUTHN_CTAP_TRANSPORT_BLE;
505 if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_INTERNAL) {
506 winTransports |= WEBAUTHN_CTAP_TRANSPORT_INTERNAL;
508 if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_HYBRID) {
509 winTransports |= WEBAUTHN_CTAP_TRANSPORT_HYBRID;
512 WEBAUTHN_CREDENTIAL_EX credential = {
513 WEBAUTHN_CREDENTIAL_EX_CURRENT_VERSION,
514 static_cast<DWORD>(cred.Length()), (PBYTE)(cred.Elements()),
515 WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY, winTransports};
516 excludeCredentials.AppendElement(credential);
519 if (!excludeCredentials.IsEmpty()) {
520 pExcludeCredentials = excludeCredentials.Elements();
521 for (DWORD i = 0; i < excludeCredentials.Length(); i++) {
522 excludeCredentialsPtrs.AppendElement(&pExcludeCredentials[i]);
524 excludeCredentialList.cCredentials = excludeCredentials.Length();
525 excludeCredentialList.ppCredentials =
526 excludeCredentialsPtrs.Elements();
527 pExcludeCredentialList = &excludeCredentialList;
530 uint32_t timeout_u32;
531 Unused << aArgs->GetTimeoutMS(&timeout_u32);
532 DWORD timeout = timeout_u32;
534 // MakeCredentialOptions
535 WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS
536 WebAuthNCredentialOptions = {
537 WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_7,
538 timeout,
539 {0, NULL},
540 {0, NULL},
541 winAttachment,
542 winRequireResidentKey,
543 winUserVerificationReq,
544 winAttestation,
545 0, // Flags
546 &cancellationId, // CancellationId
547 pExcludeCredentialList,
548 WEBAUTHN_ENTERPRISE_ATTESTATION_NONE,
549 WEBAUTHN_LARGE_BLOB_SUPPORT_NONE,
550 winPreferResidentKey, // PreferResidentKey
551 FALSE, // BrowserInPrivateMode
552 winEnablePrf, // EnablePrf
553 NULL, // LinkedDevice
554 0, // size of JsonExt
555 NULL, // JsonExt
558 if (cExtensions != 0) {
559 WebAuthNCredentialOptions.Extensions.cExtensions = cExtensions;
560 WebAuthNCredentialOptions.Extensions.pExtensions = rgExtension;
563 PWEBAUTHN_CREDENTIAL_ATTESTATION pWebAuthNCredentialAttestation =
564 nullptr;
566 // Bug 1518876: Get Window Handle from Content process for Windows
567 // WebAuthN APIs
568 HWND hWnd = GetForegroundWindow();
570 HRESULT hr = gWinWebauthnMakeCredential(
571 hWnd, &rpInfo, &userInfo, &WebAuthNCredentialParameters,
572 &WebAuthNClientData, &WebAuthNCredentialOptions,
573 &pWebAuthNCredentialAttestation);
575 if (hr == S_OK) {
576 RefPtr<WebAuthnRegisterResult> result = new WebAuthnRegisterResult(
577 clientDataJSON, pWebAuthNCredentialAttestation);
579 // WEBAUTHN_CREDENTIAL_ATTESTATION structs of version >= 4 always
580 // include a flag to indicate whether a resident key was created. We
581 // copy that flag to the credProps extension output only if the RP
582 // requested the credProps extension.
583 if (requestedCredProps &&
584 pWebAuthNCredentialAttestation->dwVersion >=
585 WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_4) {
586 BOOL rk = pWebAuthNCredentialAttestation->bResidentKey;
587 Unused << result->SetCredPropsRk(rk == TRUE);
589 gWinWebauthnFreeCredentialAttestation(pWebAuthNCredentialAttestation);
591 aPromise->Resolve(result);
592 } else {
593 PCWSTR errorName = gWinWebauthnGetErrorName(hr);
594 nsresult aError = NS_ERROR_DOM_ABORT_ERR;
596 if (_wcsicmp(errorName, L"InvalidStateError") == 0) {
597 aError = NS_ERROR_DOM_INVALID_STATE_ERR;
598 } else if (_wcsicmp(errorName, L"ConstraintError") == 0 ||
599 _wcsicmp(errorName, L"UnknownError") == 0) {
600 aError = NS_ERROR_DOM_UNKNOWN_ERR;
601 } else if (_wcsicmp(errorName, L"NotSupportedError") == 0) {
602 aError = NS_ERROR_DOM_INVALID_STATE_ERR;
603 } else if (_wcsicmp(errorName, L"NotAllowedError") == 0) {
604 aError = NS_ERROR_DOM_NOT_ALLOWED_ERR;
607 aPromise->Reject(aError);
609 }));
611 NS_DispatchBackgroundTask(runnable, NS_DISPATCH_EVENT_MAY_BLOCK);
612 return NS_OK;
615 NS_IMETHODIMP
616 WinWebAuthnService::GetAssertion(uint64_t aTransactionId,
617 uint64_t aBrowsingContextId,
618 nsIWebAuthnSignArgs* aArgs,
619 nsIWebAuthnSignPromise* aPromise) {
620 nsresult rv = EnsureWinWebAuthnModuleLoaded();
621 NS_ENSURE_SUCCESS(rv, rv);
623 Reset();
625 auto guard = mTransactionState.Lock();
627 GUID cancellationId;
629 StaticAutoReadLock moduleLock(gWinWebAuthnModuleLock);
630 if (gWinWebauthnGetCancellationId(&cancellationId) != S_OK) {
631 // caller will reject promise
632 return NS_ERROR_DOM_UNKNOWN_ERR;
636 *guard = Some(TransactionState{
637 aTransactionId,
638 aBrowsingContextId,
639 Some(RefPtr{aArgs}),
640 Some(RefPtr{aPromise}),
641 cancellationId,
644 bool conditionallyMediated;
645 Unused << aArgs->GetConditionallyMediated(&conditionallyMediated);
646 if (!conditionallyMediated) {
647 DoGetAssertion(Nothing(), guard);
649 return NS_OK;
652 void WinWebAuthnService::DoGetAssertion(
653 Maybe<nsTArray<uint8_t>>&& aSelectedCredentialId,
654 const TransactionStateMutex::AutoLock& aGuard) {
655 if (aGuard->isNothing() || aGuard->ref().pendingSignArgs.isNothing() ||
656 aGuard->ref().pendingSignPromise.isNothing()) {
657 return;
660 // Take the pending Args and Promise to prevent repeated calls to
661 // DoGetAssertion for this transaction.
662 RefPtr<nsIWebAuthnSignArgs> aArgs = aGuard->ref().pendingSignArgs.extract();
663 RefPtr<nsIWebAuthnSignPromise> aPromise =
664 aGuard->ref().pendingSignPromise.extract();
666 nsCOMPtr<nsIRunnable> runnable(NS_NewRunnableFunction(
667 "WinWebAuthnService::MakeCredential",
668 [self = RefPtr{this}, aArgs, aPromise,
669 aSelectedCredentialId = std::move(aSelectedCredentialId),
670 aCancellationId = aGuard->ref().cancellationId]() mutable {
671 // Take a read lock on gWinWebAuthnModuleLock to prevent the module from
672 // being unloaded while the operation is in progress. This does not
673 // prevent the operation from being cancelled, so it does not block a
674 // clean shutdown.
675 StaticAutoReadLock moduleLock(gWinWebAuthnModuleLock);
676 if (!gWinWebAuthnModule) {
677 aPromise->Reject(NS_ERROR_DOM_UNKNOWN_ERR);
678 return;
681 // Attachment
682 DWORD winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_ANY;
684 // AppId
685 BOOL bAppIdUsed = FALSE;
686 BOOL* pbAppIdUsed = nullptr;
687 PCWSTR winAppIdentifier = nullptr;
689 // Client Data
690 nsCString clientDataJSON;
691 Unused << aArgs->GetClientDataJSON(clientDataJSON);
692 WEBAUTHN_CLIENT_DATA WebAuthNClientData = {
693 WEBAUTHN_CLIENT_DATA_CURRENT_VERSION,
694 (DWORD)clientDataJSON.Length(), (BYTE*)(clientDataJSON.get()),
695 WEBAUTHN_HASH_ALGORITHM_SHA_256};
697 nsString appId;
698 nsresult rv = aArgs->GetAppId(appId);
699 if (rv != NS_ERROR_NOT_AVAILABLE) {
700 if (NS_FAILED(rv)) {
701 aPromise->Reject(rv);
702 return;
704 winAppIdentifier = appId.get();
705 pbAppIdUsed = &bAppIdUsed;
708 // RPID
709 nsString rpId;
710 Unused << aArgs->GetRpId(rpId);
712 // User Verification Requirement
713 nsString userVerificationReq;
714 Unused << aArgs->GetUserVerification(userVerificationReq);
715 DWORD winUserVerificationReq;
716 // This mapping needs to be reviewed if values are added to the
717 // UserVerificationRequirement enum.
718 static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 3);
719 if (userVerificationReq.EqualsLiteral(
720 MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED)) {
721 winUserVerificationReq =
722 WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED;
723 } else if (userVerificationReq.EqualsLiteral(
724 MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED)) {
725 winUserVerificationReq =
726 WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED;
727 } else if (userVerificationReq.EqualsLiteral(
728 MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_DISCOURAGED)) {
729 winUserVerificationReq =
730 WEBAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED;
731 } else {
732 winUserVerificationReq = WEBAUTHN_USER_VERIFICATION_REQUIREMENT_ANY;
735 // PRF inputs
736 WEBAUTHN_HMAC_SECRET_SALT_VALUES* pPrfInputs = nullptr;
737 WEBAUTHN_HMAC_SECRET_SALT_VALUES prfInputs = {0};
738 WEBAUTHN_HMAC_SECRET_SALT globalHmacSalt = {0};
739 nsTArray<uint8_t> prfEvalFirst;
740 nsTArray<uint8_t> prfEvalSecond;
741 nsTArray<nsTArray<uint8_t>> prfEvalByCredIds;
742 nsTArray<nsTArray<uint8_t>> prfEvalByCredFirsts;
743 nsTArray<bool> prfEvalByCredSecondMaybes;
744 nsTArray<nsTArray<uint8_t>> prfEvalByCredSeconds;
745 nsTArray<WEBAUTHN_HMAC_SECRET_SALT> hmacSecretSalts;
746 nsTArray<WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT>
747 credWithHmacSecretSaltList;
749 bool requestedPrf;
750 Unused << aArgs->GetPrf(&requestedPrf);
751 if (requestedPrf) {
752 rv = aArgs->GetPrfEvalFirst(prfEvalFirst);
753 if (rv == NS_OK) {
754 globalHmacSalt.cbFirst = prfEvalFirst.Length();
755 globalHmacSalt.pbFirst = prfEvalFirst.Elements();
756 prfInputs.pGlobalHmacSalt = &globalHmacSalt;
758 rv = aArgs->GetPrfEvalSecond(prfEvalSecond);
759 if (rv == NS_OK) {
760 globalHmacSalt.cbSecond = prfEvalSecond.Length();
761 globalHmacSalt.pbSecond = prfEvalSecond.Elements();
763 if (NS_OK ==
764 aArgs->GetPrfEvalByCredentialCredentialId(prfEvalByCredIds) &&
765 NS_OK ==
766 aArgs->GetPrfEvalByCredentialEvalFirst(prfEvalByCredFirsts) &&
767 NS_OK == aArgs->GetPrfEvalByCredentialEvalSecondMaybe(
768 prfEvalByCredSecondMaybes) &&
769 NS_OK == aArgs->GetPrfEvalByCredentialEvalSecond(
770 prfEvalByCredSeconds) &&
771 prfEvalByCredIds.Length() == prfEvalByCredFirsts.Length() &&
772 prfEvalByCredIds.Length() == prfEvalByCredSecondMaybes.Length() &&
773 prfEvalByCredIds.Length() == prfEvalByCredSeconds.Length()) {
774 for (size_t i = 0; i < prfEvalByCredIds.Length(); i++) {
775 WEBAUTHN_HMAC_SECRET_SALT salt = {0};
776 salt.cbFirst = prfEvalByCredFirsts[i].Length();
777 salt.pbFirst = prfEvalByCredFirsts[i].Elements();
778 if (prfEvalByCredSecondMaybes[i]) {
779 salt.cbSecond = prfEvalByCredSeconds[i].Length();
780 salt.pbSecond = prfEvalByCredSeconds[i].Elements();
782 hmacSecretSalts.AppendElement(salt);
784 // The credWithHmacSecretSaltList array will contain raw pointers to
785 // elements of the hmacSecretSalts array, so we must not cause
786 // any re-allocations of hmacSecretSalts from this point.
787 for (size_t i = 0; i < prfEvalByCredIds.Length(); i++) {
788 WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT value = {0};
789 value.cbCredID = prfEvalByCredIds[i].Length();
790 value.pbCredID = prfEvalByCredIds[i].Elements();
791 value.pHmacSecretSalt = &hmacSecretSalts[i];
792 credWithHmacSecretSaltList.AppendElement(value);
794 prfInputs.cCredWithHmacSecretSaltList =
795 credWithHmacSecretSaltList.Length();
796 prfInputs.pCredWithHmacSecretSaltList =
797 credWithHmacSecretSaltList.Elements();
800 pPrfInputs = &prfInputs;
803 // https://w3c.github.io/webauthn/#prf-extension
804 // "The hmac-secret extension provides two PRFs per credential: one
805 // which is used for requests where user verification is performed and
806 // another for all other requests. This extension [PRF] only exposes a
807 // single PRF per credential and, when implementing on top of
808 // hmac-secret, that PRF MUST be the one used for when user verification
809 // is performed. This overrides the UserVerificationRequirement if
810 // neccessary."
811 if (pPrfInputs &&
812 winUserVerificationReq ==
813 WEBAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED) {
814 winUserVerificationReq =
815 WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED;
818 // allow Credentials
819 nsTArray<nsTArray<uint8_t>> allowList;
820 nsTArray<uint8_t> allowListTransports;
821 if (aSelectedCredentialId.isSome()) {
822 allowList.AppendElement(aSelectedCredentialId.extract());
823 allowListTransports.AppendElement(
824 MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_INTERNAL);
825 } else {
826 Unused << aArgs->GetAllowList(allowList);
827 Unused << aArgs->GetAllowListTransports(allowListTransports);
830 if (allowList.Length() != allowListTransports.Length()) {
831 aPromise->Reject(NS_ERROR_DOM_UNKNOWN_ERR);
832 return;
835 nsTArray<WEBAUTHN_CREDENTIAL_EX> allowCredentials;
836 WEBAUTHN_CREDENTIAL_EX* pAllowCredentials = nullptr;
837 nsTArray<WEBAUTHN_CREDENTIAL_EX*> allowCredentialsPtrs;
838 WEBAUTHN_CREDENTIAL_LIST allowCredentialList = {0};
839 WEBAUTHN_CREDENTIAL_LIST* pAllowCredentialList = nullptr;
841 for (size_t i = 0; i < allowList.Length(); i++) {
842 nsTArray<uint8_t>& cred = allowList[i];
843 uint8_t& transports = allowListTransports[i];
844 DWORD winTransports = 0;
845 if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_USB) {
846 winTransports |= WEBAUTHN_CTAP_TRANSPORT_USB;
848 if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_NFC) {
849 winTransports |= WEBAUTHN_CTAP_TRANSPORT_NFC;
851 if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_BLE) {
852 winTransports |= WEBAUTHN_CTAP_TRANSPORT_BLE;
854 if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_INTERNAL) {
855 winTransports |= WEBAUTHN_CTAP_TRANSPORT_INTERNAL;
857 if (transports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_HYBRID) {
858 winTransports |= WEBAUTHN_CTAP_TRANSPORT_HYBRID;
861 WEBAUTHN_CREDENTIAL_EX credential = {
862 WEBAUTHN_CREDENTIAL_EX_CURRENT_VERSION,
863 static_cast<DWORD>(cred.Length()), (PBYTE)(cred.Elements()),
864 WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY, winTransports};
865 allowCredentials.AppendElement(credential);
868 if (allowCredentials.Length()) {
869 pAllowCredentials = allowCredentials.Elements();
870 for (DWORD i = 0; i < allowCredentials.Length(); i++) {
871 allowCredentialsPtrs.AppendElement(&pAllowCredentials[i]);
873 allowCredentialList.cCredentials = allowCredentials.Length();
874 allowCredentialList.ppCredentials = allowCredentialsPtrs.Elements();
875 pAllowCredentialList = &allowCredentialList;
878 uint32_t timeout_u32;
879 Unused << aArgs->GetTimeoutMS(&timeout_u32);
880 DWORD timeout = timeout_u32;
882 WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS WebAuthNAssertionOptions =
884 WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_7,
885 timeout,
886 {0, NULL},
887 {0, NULL},
888 winAttachment,
889 winUserVerificationReq,
890 0, // dwFlags
891 winAppIdentifier,
892 pbAppIdUsed,
893 &aCancellationId, // CancellationId
894 pAllowCredentialList,
895 WEBAUTHN_CRED_LARGE_BLOB_OPERATION_NONE,
896 0, // Size of CredLargeBlob
897 NULL, // CredLargeBlob
898 pPrfInputs, // HmacSecretSaltValues
899 FALSE, // BrowserInPrivateMode
900 NULL, // LinkedDevice
901 FALSE, // AutoFill
902 0, // Size of JsonExt
903 NULL, // JsonExt
906 PWEBAUTHN_ASSERTION pWebAuthNAssertion = nullptr;
908 // Bug 1518876: Get Window Handle from Content process for Windows
909 // WebAuthN APIs
910 HWND hWnd = GetForegroundWindow();
912 HRESULT hr = gWinWebauthnGetAssertion(
913 hWnd, rpId.get(), &WebAuthNClientData, &WebAuthNAssertionOptions,
914 &pWebAuthNAssertion);
916 if (hr == S_OK) {
917 RefPtr<WebAuthnSignResult> result =
918 new WebAuthnSignResult(clientDataJSON, pWebAuthNAssertion);
919 gWinWebauthnFreeAssertion(pWebAuthNAssertion);
920 if (winAppIdentifier != nullptr) {
921 // The gWinWebauthnGetAssertion call modified bAppIdUsed through
922 // a pointer provided in WebAuthNAssertionOptions.
923 Unused << result->SetUsedAppId(bAppIdUsed == TRUE);
925 aPromise->Resolve(result);
926 } else {
927 PCWSTR errorName = gWinWebauthnGetErrorName(hr);
928 nsresult aError = NS_ERROR_DOM_ABORT_ERR;
930 if (_wcsicmp(errorName, L"InvalidStateError") == 0) {
931 aError = NS_ERROR_DOM_INVALID_STATE_ERR;
932 } else if (_wcsicmp(errorName, L"ConstraintError") == 0 ||
933 _wcsicmp(errorName, L"UnknownError") == 0) {
934 aError = NS_ERROR_DOM_UNKNOWN_ERR;
935 } else if (_wcsicmp(errorName, L"NotSupportedError") == 0) {
936 aError = NS_ERROR_DOM_INVALID_STATE_ERR;
937 } else if (_wcsicmp(errorName, L"NotAllowedError") == 0) {
938 aError = NS_ERROR_DOM_NOT_ALLOWED_ERR;
941 aPromise->Reject(aError);
943 }));
945 NS_DispatchBackgroundTask(runnable, NS_DISPATCH_EVENT_MAY_BLOCK);
948 NS_IMETHODIMP
949 WinWebAuthnService::HasPendingConditionalGet(uint64_t aBrowsingContextId,
950 const nsAString& aOrigin,
951 uint64_t* aRv) {
952 auto guard = mTransactionState.Lock();
953 if (guard->isNothing() ||
954 guard->ref().browsingContextId != aBrowsingContextId ||
955 guard->ref().pendingSignArgs.isNothing()) {
956 *aRv = 0;
957 return NS_OK;
960 nsString origin;
961 Unused << guard->ref().pendingSignArgs.ref()->GetOrigin(origin);
962 if (origin != aOrigin) {
963 *aRv = 0;
964 return NS_OK;
967 *aRv = guard->ref().transactionId;
968 return NS_OK;
971 NS_IMETHODIMP
972 WinWebAuthnService::GetAutoFillEntries(
973 uint64_t aTransactionId, nsTArray<RefPtr<nsIWebAuthnAutoFillEntry>>& aRv) {
974 aRv.Clear();
975 nsString rpId;
978 auto guard = mTransactionState.Lock();
979 if (guard->isNothing() || guard->ref().transactionId != aTransactionId ||
980 guard->ref().pendingSignArgs.isNothing()) {
981 return NS_ERROR_NOT_AVAILABLE;
983 Unused << guard->ref().pendingSignArgs.ref()->GetRpId(rpId);
986 StaticAutoReadLock moduleLock(gWinWebAuthnModuleLock);
987 if (!gWinWebAuthnModule) {
988 return NS_ERROR_NOT_AVAILABLE;
991 if (gWinWebauthnGetApiVersionNumber() < WEBAUTHN_API_VERSION_4) {
992 // GetPlatformCredentialList was added in version 4. Earlier versions
993 // can still present a generic "Use a Passkey" autofill entry, so
994 // this isn't an error.
995 return NS_OK;
998 WEBAUTHN_GET_CREDENTIALS_OPTIONS getCredentialsOptions{
999 WEBAUTHN_GET_CREDENTIALS_OPTIONS_VERSION_1,
1000 rpId.get(), // pwszRpId
1001 FALSE, // bBrowserInPrivateMode
1003 PWEBAUTHN_CREDENTIAL_DETAILS_LIST pCredentialList = nullptr;
1004 HRESULT hr = gWinWebauthnGetPlatformCredentialList(&getCredentialsOptions,
1005 &pCredentialList);
1006 // WebAuthNGetPlatformCredentialList has an _Outptr_result_maybenull_
1007 // annotation and a comment "Returns NTE_NOT_FOUND when credentials are
1008 // not found."
1009 if (pCredentialList == nullptr) {
1010 if (hr != NTE_NOT_FOUND) {
1011 return NS_ERROR_FAILURE;
1013 return NS_OK;
1015 MOZ_ASSERT(hr == S_OK);
1016 for (size_t i = 0; i < pCredentialList->cCredentialDetails; i++) {
1017 RefPtr<nsIWebAuthnAutoFillEntry> entry(
1018 new WebAuthnAutoFillEntry(pCredentialList->ppCredentialDetails[i]));
1019 aRv.AppendElement(entry);
1021 gWinWebauthnFreePlatformCredentialList(pCredentialList);
1022 return NS_OK;
1025 NS_IMETHODIMP
1026 WinWebAuthnService::SelectAutoFillEntry(
1027 uint64_t aTransactionId, const nsTArray<uint8_t>& aCredentialId) {
1028 auto guard = mTransactionState.Lock();
1029 if (guard->isNothing() || guard->ref().transactionId != aTransactionId ||
1030 guard->ref().pendingSignArgs.isNothing()) {
1031 return NS_ERROR_NOT_AVAILABLE;
1034 nsTArray<nsTArray<uint8_t>> allowList;
1035 Unused << guard->ref().pendingSignArgs.ref()->GetAllowList(allowList);
1036 if (!allowList.IsEmpty() && !allowList.Contains(aCredentialId)) {
1037 return NS_ERROR_FAILURE;
1040 Maybe<nsTArray<uint8_t>> id;
1041 id.emplace();
1042 id.ref().Assign(aCredentialId);
1043 DoGetAssertion(std::move(id), guard);
1045 return NS_OK;
1048 NS_IMETHODIMP
1049 WinWebAuthnService::ResumeConditionalGet(uint64_t aTransactionId) {
1050 auto guard = mTransactionState.Lock();
1051 if (guard->isNothing() || guard->ref().transactionId != aTransactionId ||
1052 guard->ref().pendingSignArgs.isNothing()) {
1053 return NS_ERROR_NOT_AVAILABLE;
1055 DoGetAssertion(Nothing(), guard);
1056 return NS_OK;
1059 NS_IMETHODIMP
1060 WinWebAuthnService::PinCallback(uint64_t aTransactionId,
1061 const nsACString& aPin) {
1062 return NS_ERROR_NOT_IMPLEMENTED;
1065 NS_IMETHODIMP
1066 WinWebAuthnService::SetHasAttestationConsent(uint64_t aTransactionId,
1067 bool aHasConsent) {
1068 return NS_ERROR_NOT_IMPLEMENTED;
1071 NS_IMETHODIMP
1072 WinWebAuthnService::SelectionCallback(uint64_t aTransactionId,
1073 uint64_t aIndex) {
1074 return NS_ERROR_NOT_IMPLEMENTED;
1077 NS_IMETHODIMP
1078 WinWebAuthnService::AddVirtualAuthenticator(
1079 const nsACString& protocol, const nsACString& transport,
1080 bool hasResidentKey, bool hasUserVerification, bool isUserConsenting,
1081 bool isUserVerified, uint64_t* _retval) {
1082 return NS_ERROR_NOT_IMPLEMENTED;
1085 NS_IMETHODIMP
1086 WinWebAuthnService::RemoveVirtualAuthenticator(uint64_t authenticatorId) {
1087 return NS_ERROR_NOT_IMPLEMENTED;
1090 NS_IMETHODIMP
1091 WinWebAuthnService::AddCredential(uint64_t authenticatorId,
1092 const nsACString& credentialId,
1093 bool isResidentCredential,
1094 const nsACString& rpId,
1095 const nsACString& privateKey,
1096 const nsACString& userHandle,
1097 uint32_t signCount) {
1098 return NS_ERROR_NOT_IMPLEMENTED;
1101 NS_IMETHODIMP
1102 WinWebAuthnService::GetCredentials(
1103 uint64_t authenticatorId,
1104 nsTArray<RefPtr<nsICredentialParameters>>& _retval) {
1105 return NS_ERROR_NOT_IMPLEMENTED;
1108 NS_IMETHODIMP
1109 WinWebAuthnService::RemoveCredential(uint64_t authenticatorId,
1110 const nsACString& credentialId) {
1111 return NS_ERROR_NOT_IMPLEMENTED;
1114 NS_IMETHODIMP
1115 WinWebAuthnService::RemoveAllCredentials(uint64_t authenticatorId) {
1116 return NS_ERROR_NOT_IMPLEMENTED;
1119 NS_IMETHODIMP
1120 WinWebAuthnService::SetUserVerified(uint64_t authenticatorId,
1121 bool isUserVerified) {
1122 return NS_ERROR_NOT_IMPLEMENTED;
1125 NS_IMETHODIMP
1126 WinWebAuthnService::Listen() { return NS_ERROR_NOT_IMPLEMENTED; }
1128 NS_IMETHODIMP
1129 WinWebAuthnService::RunCommand(const nsACString& cmd) {
1130 return NS_ERROR_NOT_IMPLEMENTED;
1133 } // namespace mozilla::dom