diff --git a/dom/webauthn/AndroidWebAuthnTokenManager.cpp b/dom/webauthn/AndroidWebAuthnTokenManager.cpp index 7c465104c26e..767bb59bb317 100644 --- a/dom/webauthn/AndroidWebAuthnTokenManager.cpp +++ b/dom/webauthn/AndroidWebAuthnTokenManager.cpp @@ -13,7 +13,6 @@ #include "JavaExceptions.h" #include "mozilla/java/WebAuthnTokenManagerWrappers.h" #include "mozilla/jni/Conversions.h" -#include "WebAuthnEnumStrings.h" namespace mozilla { namespace jni { @@ -144,17 +143,20 @@ RefPtr AndroidWebAuthnTokenManager::Register( java::sdk::Integer::ValueOf(1)); // Get the attestation preference and override if the user asked + AttestationConveyancePreference attestation = + extra.attestationConveyancePreference(); + if (aForceNoneAttestation) { // Add UI support to trigger this, bug 1550164 - GECKOBUNDLE_PUT(authSelBundle, "attestationPreference", - jni::StringParam(u"none"_ns)); - } else { - const nsString& attestation = - extra.attestationConveyancePreference(); - GECKOBUNDLE_PUT(authSelBundle, "attestationPreference", - jni::StringParam(attestation)); + attestation = AttestationConveyancePreference::None; } + nsString attestPref; + attestPref.AssignASCII( + AttestationConveyancePreferenceValues::GetString(attestation)); + GECKOBUNDLE_PUT(authSelBundle, "attestationPreference", + jni::StringParam(attestPref)); + const WebAuthnAuthenticatorSelection& sel = extra.AuthenticatorSelection(); if (sel.requireResidentKey()) { @@ -162,22 +164,20 @@ RefPtr AndroidWebAuthnTokenManager::Register( java::sdk::Integer::ValueOf(1)); } - if (sel.userVerificationRequirement().EqualsLiteral( - MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED)) { + if (sel.userVerificationRequirement() == + UserVerificationRequirement::Required) { GECKOBUNDLE_PUT(authSelBundle, "requireUserVerification", java::sdk::Integer::ValueOf(1)); } if (sel.authenticatorAttachment().isSome()) { - const nsString& authenticatorAttachment = + const AuthenticatorAttachment authenticatorAttachment = sel.authenticatorAttachment().value(); - if (authenticatorAttachment.EqualsLiteral( - MOZ_WEBAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM)) { + if (authenticatorAttachment == AuthenticatorAttachment::Platform) { GECKOBUNDLE_PUT(authSelBundle, "requirePlatformAttachment", java::sdk::Integer::ValueOf(1)); - } else if ( - authenticatorAttachment.EqualsLiteral( - MOZ_WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM)) { + } else if (authenticatorAttachment == + AuthenticatorAttachment::Cross_platform) { GECKOBUNDLE_PUT(authSelBundle, "requireCrossPlatformAttachment", java::sdk::Integer::ValueOf(1)); } diff --git a/dom/webauthn/CTAPHIDTokenManager.cpp b/dom/webauthn/CTAPHIDTokenManager.cpp index a19d5c426cb2..7739d3deb0d9 100644 --- a/dom/webauthn/CTAPHIDTokenManager.cpp +++ b/dom/webauthn/CTAPHIDTokenManager.cpp @@ -5,7 +5,6 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "WebAuthnCoseIdentifiers.h" -#include "WebAuthnEnumStrings.h" #include "mozilla/dom/CTAPHIDTokenManager.h" #include "mozilla/dom/U2FHIDTokenManager.h" #include "mozilla/dom/WebAuthnUtil.h" @@ -142,16 +141,17 @@ RefPtr CTAPHIDTokenManager::Register( const auto& extra = aInfo.Extra().ref(); const WebAuthnAuthenticatorSelection& sel = extra.AuthenticatorSelection(); + UserVerificationRequirement userVerificationRequirement = + sel.userVerificationRequirement(); + bool requireUserVerification = - sel.userVerificationRequirement().EqualsLiteral( - MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED); + userVerificationRequirement == UserVerificationRequirement::Required; bool requirePlatformAttachment = false; if (sel.authenticatorAttachment().isSome()) { - const nsString& authenticatorAttachment = + const AuthenticatorAttachment authenticatorAttachment = sel.authenticatorAttachment().value(); - if (authenticatorAttachment.EqualsLiteral( - MOZ_WEBAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM)) { + if (authenticatorAttachment == AuthenticatorAttachment::Platform) { requirePlatformAttachment = true; } } @@ -272,9 +272,11 @@ RefPtr CTAPHIDTokenManager::Sign( if (aInfo.Extra().isSome()) { const auto& extra = aInfo.Extra().ref(); + UserVerificationRequirement userVerificationReq = + extra.userVerificationRequirement(); + // Set flags for credential requests. - if (extra.userVerificationRequirement().EqualsLiteral( - MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED)) { + if (userVerificationReq == UserVerificationRequirement::Required) { signFlags |= U2F_FLAG_REQUIRE_USER_VERIFICATION; } diff --git a/dom/webauthn/PWebAuthnTransaction.ipdl b/dom/webauthn/PWebAuthnTransaction.ipdl index 2571ac83c1b5..0892948080ae 100644 --- a/dom/webauthn/PWebAuthnTransaction.ipdl +++ b/dom/webauthn/PWebAuthnTransaction.ipdl @@ -16,15 +16,18 @@ include protocol PBackground; +using mozilla::dom::AttestationConveyancePreference from "mozilla/dom/WebAuthnUtil.h"; +using mozilla::dom::AuthenticatorAttachment from "mozilla/dom/WebAuthnUtil.h"; using mozilla::dom::MaybeDiscardedBrowsingContext from "mozilla/dom/BrowsingContext.h"; +using mozilla::dom::UserVerificationRequirement from "mozilla/dom/WebAuthnUtil.h"; namespace mozilla { namespace dom { struct WebAuthnAuthenticatorSelection { bool requireResidentKey; - nsString userVerificationRequirement; - nsString? authenticatorAttachment; + UserVerificationRequirement userVerificationRequirement; + AuthenticatorAttachment? authenticatorAttachment; }; struct WebAuthnScopedCredential { @@ -81,7 +84,7 @@ struct WebAuthnMakeCredentialExtraInfo { CoseAlg[] coseAlgs; WebAuthnExtension[] Extensions; WebAuthnAuthenticatorSelection AuthenticatorSelection; - nsString attestationConveyancePreference; + AttestationConveyancePreference attestationConveyancePreference; }; struct WebAuthnMakeCredentialInfo { @@ -106,7 +109,7 @@ struct WebAuthnMakeCredentialResult { struct WebAuthnGetAssertionExtraInfo { WebAuthnExtension[] Extensions; - nsString userVerificationRequirement; + UserVerificationRequirement userVerificationRequirement; }; struct WebAuthnGetAssertionInfo { diff --git a/dom/webauthn/U2FHIDTokenManager.cpp b/dom/webauthn/U2FHIDTokenManager.cpp index 49d04e924c35..e17f8a6ea990 100644 --- a/dom/webauthn/U2FHIDTokenManager.cpp +++ b/dom/webauthn/U2FHIDTokenManager.cpp @@ -5,7 +5,6 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "WebAuthnCoseIdentifiers.h" -#include "WebAuthnEnumStrings.h" #include "mozilla/dom/U2FHIDTokenManager.h" #include "mozilla/dom/WebAuthnUtil.h" #include "mozilla/ipc/BackgroundParent.h" @@ -114,12 +113,17 @@ RefPtr U2FHIDTokenManager::Register( const auto& extra = aInfo.Extra().ref(); const WebAuthnAuthenticatorSelection& sel = extra.AuthenticatorSelection(); + UserVerificationRequirement userVerificaitonRequirement = + sel.userVerificationRequirement(); + + bool requireUserVerification = + userVerificaitonRequirement == UserVerificationRequirement::Required; + bool requirePlatformAttachment = false; if (sel.authenticatorAttachment().isSome()) { - const nsString& authenticatorAttachment = + const AuthenticatorAttachment authenticatorAttachment = sel.authenticatorAttachment().value(); - if (authenticatorAttachment.EqualsLiteral( - MOZ_WEBAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM)) { + if (authenticatorAttachment == AuthenticatorAttachment::Platform) { requirePlatformAttachment = true; } } @@ -128,8 +132,7 @@ RefPtr U2FHIDTokenManager::Register( if (sel.requireResidentKey()) { registerFlags |= U2F_FLAG_REQUIRE_RESIDENT_KEY; } - if (sel.userVerificationRequirement().EqualsLiteral( - MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED)) { + if (requireUserVerification) { registerFlags |= U2F_FLAG_REQUIRE_USER_VERIFICATION; } if (requirePlatformAttachment) { @@ -228,9 +231,11 @@ RefPtr U2FHIDTokenManager::Sign( if (aInfo.Extra().isSome()) { const auto& extra = aInfo.Extra().ref(); + UserVerificationRequirement userVerificaitonReq = + extra.userVerificationRequirement(); + // Set flags for credential requests. - if (extra.userVerificationRequirement().EqualsLiteral( - MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED)) { + if (userVerificaitonReq == UserVerificationRequirement::Required) { signFlags |= U2F_FLAG_REQUIRE_USER_VERIFICATION; } diff --git a/dom/webauthn/U2FSoftTokenManager.cpp b/dom/webauthn/U2FSoftTokenManager.cpp index 5f407e7d8279..eceaf2aae88b 100644 --- a/dom/webauthn/U2FSoftTokenManager.cpp +++ b/dom/webauthn/U2FSoftTokenManager.cpp @@ -5,7 +5,6 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "WebAuthnCoseIdentifiers.h" -#include "WebAuthnEnumStrings.h" #include "mozilla/dom/U2FSoftTokenManager.h" #include "CryptoBuffer.h" #include "mozilla/Base64.h" @@ -582,16 +581,17 @@ RefPtr U2FSoftTokenManager::Register( const auto& extra = aInfo.Extra().ref(); const WebAuthnAuthenticatorSelection& sel = extra.AuthenticatorSelection(); + UserVerificationRequirement userVerificaitonRequirement = + sel.userVerificationRequirement(); + bool requireUserVerification = - sel.userVerificationRequirement().EqualsLiteral( - MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED); + userVerificaitonRequirement == UserVerificationRequirement::Required; bool requirePlatformAttachment = false; if (sel.authenticatorAttachment().isSome()) { - const nsString& authenticatorAttachment = + const AuthenticatorAttachment authenticatorAttachment = sel.authenticatorAttachment().value(); - if (authenticatorAttachment.EqualsLiteral( - MOZ_WEBAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM)) { + if (authenticatorAttachment == AuthenticatorAttachment::Platform) { requirePlatformAttachment = true; } } @@ -824,9 +824,11 @@ RefPtr U2FSoftTokenManager::Sign( if (aInfo.Extra().isSome()) { const auto& extra = aInfo.Extra().ref(); + UserVerificationRequirement userVerificaitonReq = + extra.userVerificationRequirement(); + // The U2F softtoken doesn't support user verification. - if (extra.userVerificationRequirement().EqualsLiteral( - MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED)) { + if (userVerificaitonReq == UserVerificationRequirement::Required) { return U2FSignPromise::CreateAndReject(NS_ERROR_DOM_NOT_ALLOWED_ERR, __func__); } diff --git a/dom/webauthn/U2FTokenManager.cpp b/dom/webauthn/U2FTokenManager.cpp index 893df98b4a4e..2e6af632ea79 100644 --- a/dom/webauthn/U2FTokenManager.cpp +++ b/dom/webauthn/U2FTokenManager.cpp @@ -23,7 +23,6 @@ #include "nsIThread.h" #include "nsTextFormatter.h" #include "mozilla/Telemetry.h" -#include "WebAuthnEnumStrings.h" #ifdef MOZ_WIDGET_ANDROID # include "mozilla/dom/AndroidWebAuthnTokenManager.h" @@ -468,20 +467,11 @@ void U2FTokenManager::Register( if (aTransactionInfo.Extra().isSome()) { const auto& extra = aTransactionInfo.Extra().ref(); - // The default attestation type is "none", so set - // noneAttestationRequested=false only if the RP's preference matches one of - // the other known types. This needs to be reviewed if values are added to - // the AttestationConveyancePreference enum. - const nsString& attestation = extra.attestationConveyancePreference(); - static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 2); - if (attestation.EqualsLiteral( - MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT) || - attestation.EqualsLiteral( - MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT) || - attestation.EqualsLiteral( - MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_ENTERPRISE)) { - noneAttestationRequested = false; - } + AttestationConveyancePreference attestation = + extra.attestationConveyancePreference(); + + noneAttestationRequested = + attestation == AttestationConveyancePreference::None; } #endif // not MOZ_WIDGET_ANDROID diff --git a/dom/webauthn/WebAuthnEnumStrings.h b/dom/webauthn/WebAuthnEnumStrings.h deleted file mode 100644 index a572dfb0d547..000000000000 --- a/dom/webauthn/WebAuthnEnumStrings.h +++ /dev/null @@ -1,49 +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_WebAuthnEnumStrings_h -#define mozilla_dom_WebAuthnEnumStrings_h - -// WARNING: This version number must match the WebAuthn level where the strings -// below are defined. -#define MOZ_WEBAUTHN_ENUM_STRINGS_VERSION 2 - -// https://www.w3.org/TR/webauthn-2/#enum-attestation-convey -#define MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE "none" -#define MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT "indirect" -#define MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT "direct" -#define MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_ENTERPRISE "enterprise" -// WARNING: Change version number when adding new values! - -// https://www.w3.org/TR/webauthn-2/#enum-attachment -#define MOZ_WEBAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM "platform" -#define MOZ_WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM "cross-platform" -// WARNING: Change version number when adding new values! - -// https://www.w3.org/TR/webauthn-2/#enum-credentialType -#define MOZ_WEBAUTHN_PUBLIC_KEY_CREDENTIAL_TYPE_PUBLIC_KEY "public-key" -// WARNING: Change version number when adding new values! - -// https://www.w3.org/TR/webauthn-2/#enum-residentKeyRequirement -#define MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_REQUIRED "required" -#define MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_PREFERRED "preferred" -#define MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_DISCOURAGED "discouraged" -// WARNING: Change version number when adding new values! - -// https://www.w3.org/TR/webauthn-2/#enum-userVerificationRequirement -#define MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED "required" -#define MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED "preferred" -#define MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED "discouraged" -// WARNING: Change version number when adding new values! - -// https://www.w3.org/TR/webauthn-2/#enum-transport -#define MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_USB "usb" -#define MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_NFC "nfc" -#define MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_BLE "ble" -#define MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_INTERNAL "internal" -// WARNING: Change version number when adding new values! - -#endif // mozilla_dom_WebAuthnEnumStrings_h diff --git a/dom/webauthn/WebAuthnManager.cpp b/dom/webauthn/WebAuthnManager.cpp index f85b3b9fd0cb..113b334814ba 100644 --- a/dom/webauthn/WebAuthnManager.cpp +++ b/dom/webauthn/WebAuthnManager.cpp @@ -9,7 +9,6 @@ #include "nsIURIMutator.h" #include "nsThreadUtils.h" #include "WebAuthnCoseIdentifiers.h" -#include "WebAuthnEnumStrings.h" #include "mozilla/BasePrincipal.h" #include "mozilla/dom/AuthenticatorAssertionResponse.h" #include "mozilla/dom/AuthenticatorAttestationResponse.h" @@ -314,8 +313,8 @@ already_AddRefed WebAuthnManager::MakeCredential( // If current.type does not contain a PublicKeyCredentialType // supported by this implementation, then stop processing current and move // on to the next element in mPubKeyCredParams. - if (!aOptions.mPubKeyCredParams[a].mType.EqualsLiteral( - MOZ_WEBAUTHN_PUBLIC_KEY_CREDENTIAL_TYPE_PUBLIC_KEY)) { + if (aOptions.mPubKeyCredParams[a].mType != + PublicKeyCredentialType::Public_key) { continue; } @@ -386,10 +385,10 @@ already_AddRefed WebAuthnManager::MakeCredential( const auto& selection = aOptions.mAuthenticatorSelection; const auto& attachment = selection.mAuthenticatorAttachment; - const nsString& attestation = aOptions.mAttestation; + const AttestationConveyancePreference& attestation = aOptions.mAttestation; // Attachment - Maybe authenticatorAttachment; + Maybe authenticatorAttachment; if (attachment.WasPassed()) { authenticatorAttachment.emplace(attachment.Value()); } @@ -548,8 +547,7 @@ already_AddRefed WebAuthnManager::GetAssertion( nsTArray allowList; for (const auto& s : aOptions.mAllowCredentials) { - if (s.mType.EqualsLiteral( - MOZ_WEBAUTHN_PUBLIC_KEY_CREDENTIAL_TYPE_PUBLIC_KEY)) { + if (s.mType == PublicKeyCredentialType::Public_key) { WebAuthnScopedCredential c; CryptoBuffer cb; cb.Assign(s.mId); @@ -559,21 +557,27 @@ already_AddRefed WebAuthnManager::GetAssertion( if (s.mTransports.WasPassed()) { uint8_t transports = 0; - // We ignore unknown transports for forward-compatibility, but this - // needs to be reviewed if values are added to the - // AuthenticatorTransport enum. - static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 2); + // Transports is a string, but we match it to an enumeration so + // that we have forward-compatibility, ignoring unknown transports. for (const nsAString& str : s.mTransports.Value()) { - if (str.EqualsLiteral(MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_USB)) { + NS_ConvertUTF16toUTF8 cStr(str); + int i = FindEnumStringIndexImpl( + cStr.get(), cStr.Length(), AuthenticatorTransportValues::strings); + if (i < 0) { + continue; // Unknown enum + } + AuthenticatorTransport t = static_cast(i); + + if (t == AuthenticatorTransport::Usb) { transports |= U2F_AUTHENTICATOR_TRANSPORT_USB; - } else if (str.EqualsLiteral( - MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_NFC)) { + } + if (t == AuthenticatorTransport::Nfc) { transports |= U2F_AUTHENTICATOR_TRANSPORT_NFC; - } else if (str.EqualsLiteral( - MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_BLE)) { + } + if (t == AuthenticatorTransport::Ble) { transports |= U2F_AUTHENTICATOR_TRANSPORT_BLE; - } else if (str.EqualsLiteral( - MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_INTERNAL)) { + } + if (t == AuthenticatorTransport::Internal) { transports |= CTAP_AUTHENTICATOR_TRANSPORT_INTERNAL; } } @@ -735,7 +739,7 @@ void WebAuthnManager::FinishMakeCredential( credential->SetResponse(attestation); // Forward client extension results. - for (const auto& ext : aResult.Extensions()) { + for (auto& ext : aResult.Extensions()) { if (ext.type() == WebAuthnExtensionResult::TWebAuthnExtensionResultHmacSecret) { bool hmacCreateSecret = @@ -814,7 +818,7 @@ void WebAuthnManager::FinishGetAssertion( credential->SetResponse(assertion); // Forward client extension results. - for (const auto& ext : aResult.Extensions()) { + for (auto& ext : aResult.Extensions()) { if (ext.type() == WebAuthnExtensionResult::TWebAuthnExtensionResultAppId) { bool appid = ext.get_WebAuthnExtensionResultAppId().AppId(); credential->SetClientExtensionResultAppId(appid); diff --git a/dom/webauthn/WebAuthnUtil.h b/dom/webauthn/WebAuthnUtil.h index 175ed8517ed7..b0c61139dbdd 100644 --- a/dom/webauthn/WebAuthnUtil.h +++ b/dom/webauthn/WebAuthnUtil.h @@ -62,4 +62,29 @@ nsresult BuildTransactionHashes(const nsCString& aRpId, } // namespace mozilla::dom +namespace IPC { + +template <> +struct ParamTraits + : public ContiguousEnumSerializer< + mozilla::dom::AuthenticatorAttachment, + mozilla::dom::AuthenticatorAttachment::Platform, + mozilla::dom::AuthenticatorAttachment::EndGuard_> {}; + +template <> +struct ParamTraits + : public ContiguousEnumSerializer< + mozilla::dom::UserVerificationRequirement, + mozilla::dom::UserVerificationRequirement::Required, + mozilla::dom::UserVerificationRequirement::EndGuard_> {}; + +template <> +struct ParamTraits + : public ContiguousEnumSerializer< + mozilla::dom::AttestationConveyancePreference, + mozilla::dom::AttestationConveyancePreference::None, + mozilla::dom::AttestationConveyancePreference::EndGuard_> {}; + +} // namespace IPC + #endif // mozilla_dom_WebAuthnUtil_h diff --git a/dom/webauthn/WinWebAuthnManager.cpp b/dom/webauthn/WinWebAuthnManager.cpp index 5eb16fcb9884..cf5c662b6ed7 100644 --- a/dom/webauthn/WinWebAuthnManager.cpp +++ b/dom/webauthn/WinWebAuthnManager.cpp @@ -11,7 +11,6 @@ #include "mozilla/Unused.h" #include "nsTextFormatter.h" #include "nsWindowsHelpers.h" -#include "WebAuthnEnumStrings.h" #include "winwebauthn/webauthn.h" #include "WinWebAuthnManager.h" @@ -232,60 +231,59 @@ void WinWebAuthnManager::Register( const auto& sel = extra.AuthenticatorSelection(); - const nsString& userVerificationRequirement = + UserVerificationRequirement userVerificationReq = 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; + switch (userVerificationReq) { + case UserVerificationRequirement::Required: + winUserVerificationReq = + WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED; + break; + case UserVerificationRequirement::Preferred: + winUserVerificationReq = + WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED; + break; + case UserVerificationRequirement::Discouraged: + winUserVerificationReq = + WEBAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED; + break; + default: + winUserVerificationReq = WEBAUTHN_USER_VERIFICATION_REQUIREMENT_ANY; + break; } if (sel.authenticatorAttachment().isSome()) { - const nsString& authenticatorAttachment = + const AuthenticatorAttachment 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; + switch (authenticatorAttachment) { + case AuthenticatorAttachment::Platform: + winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM; + break; + case AuthenticatorAttachment::Cross_platform: + winAttachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM; + break; + default: + break; } } winRequireResidentKey = sel.requireResidentKey(); // AttestationConveyance - const nsString& attestation = extra.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; + AttestationConveyancePreference attestation = + extra.attestationConveyancePreference(); + switch (attestation) { + case AttestationConveyancePreference::Direct: + winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT; + break; + case AttestationConveyancePreference::Indirect: + winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT; + break; + case AttestationConveyancePreference::None: + winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE; + break; + default: + winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_ANY; + break; } if (extra.Extensions().Length() > @@ -576,22 +574,25 @@ void WinWebAuthnManager::Sign(PWebAuthnTransactionParent* aTransactionParent, rpID = aInfo.RpId().get(); // User Verification Requirement - const nsString& userVerificationReq = extra.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; + UserVerificationRequirement userVerificationReq = + extra.userVerificationRequirement(); + + switch (userVerificationReq) { + case UserVerificationRequirement::Required: + winUserVerificationReq = + WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED; + break; + case UserVerificationRequirement::Preferred: + winUserVerificationReq = + WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED; + break; + case UserVerificationRequirement::Discouraged: + winUserVerificationReq = + WEBAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED; + break; + default: + winUserVerificationReq = WEBAUTHN_USER_VERIFICATION_REQUIREMENT_ANY; + break; } } else { rpID = aInfo.Origin().get(); diff --git a/dom/webauthn/tests/test_webauthn_attestation_conveyance.html b/dom/webauthn/tests/test_webauthn_attestation_conveyance.html index f4a3c3934926..02cd2c6564c8 100644 --- a/dom/webauthn/tests/test_webauthn_attestation_conveyance.html +++ b/dom/webauthn/tests/test_webauthn_attestation_conveyance.html @@ -83,11 +83,6 @@ .then(verifyAnonymizedCertificate) .catch(arrivingHereIsBad); - // Request an unknown attestation type. This should be treated as "none". - await requestMakeCredential("unknown") - .then(verifyAnonymizedCertificate) - .catch(arrivingHereIsBad); - // Request no attestation. await requestMakeCredential("none") .then(verifyAnonymizedCertificate) @@ -117,6 +112,14 @@ }) .catch(arrivingHereIsBad); }); + + // Test failure cases for make credential. + add_task(async function test_make_credential_failures() { + // Request a platform authenticator. + await requestMakeCredential("unknown") + .then(arrivingHereIsBad) + .catch(expectTypeError); + }); diff --git a/dom/webauthn/tests/test_webauthn_make_credential.html b/dom/webauthn/tests/test_webauthn_make_credential.html index b6819acaffbc..cc45e1517328 100644 --- a/dom/webauthn/tests/test_webauthn_make_credential.html +++ b/dom/webauthn/tests/test_webauthn_make_credential.html @@ -29,7 +29,7 @@ let user; let param; let unsupportedParam; - let unknownParam; + let badParam; // Setup test env add_task(() => { @@ -40,7 +40,7 @@ user = {id: new Uint8Array(64), name: "none", icon: "none", displayName: "none"}; param = {type: "public-key", alg: cose_alg_ECDSA_w_SHA256}; unsupportedParam = {type: "public-key", alg: cose_alg_ECDSA_w_SHA512}; - unknownParam = {type: "SimplePassword", alg: "MaxLength=2"}; + badParam = {type: "SimplePassword", alg: "MaxLength=2"}; credm = navigator.credentials; }); // Add tests @@ -55,8 +55,8 @@ add_task(test_without_parameters); add_task(test_unsupported_parameter); add_task(test_unsupported_but_one_param); - add_task(test_one_unknown_parameter); - add_task(test_one_unknown_one_unsupported_param); + add_task(test_one_bad_parameter); + add_task(test_one_bad_one_unsupported_param); add_task(test_one_of_each_parameters); add_task(test_without_challenge); add_task(test_invalid_challenge); @@ -69,8 +69,6 @@ add_task(test_complete_account); add_task(test_too_large_user_id); add_task(test_excluding_unknown_transports); - add_task(test_unknown_attestation_type); - add_task(test_unknown_selection_criteria); function arrivingHereIsGood(aResult) { ok(true, "Good result! Received a: " + aResult); @@ -214,37 +212,37 @@ .catch(arrivingHereIsBad); } - // Test with one unknown parameter. - async function test_one_unknown_parameter() { + // Test with a bad parameter + async function test_one_bad_parameter() { let makeCredentialOptions = { - rp, user, challenge: gCredentialChallenge, pubKeyCredParams: [unknownParam] + rp, user, challenge: gCredentialChallenge, pubKeyCredParams: [badParam] }; return credm.create({publicKey: makeCredentialOptions}) .then(arrivingHereIsBad) - .catch(expectNotSupportedError); + .catch(expectTypeError); } - // Test with an unsupported parameter, and an unknown one - async function test_one_unknown_one_unsupported_param() { + // Test with an unsupported parameter, and a bad one + async function test_one_bad_one_unsupported_param() { let makeCredentialOptions = { rp, user, challenge: gCredentialChallenge, - pubKeyCredParams: [unsupportedParam, unknownParam] + pubKeyCredParams: [unsupportedParam, badParam] }; return credm.create({publicKey: makeCredentialOptions}) .then(arrivingHereIsBad) - .catch(expectNotSupportedError); + .catch(expectTypeError); } - // Test with an unsupported parameter, an unknown one, and a good one. This - // should succeed, as the unsupported and unknown should be ignored. + // Test with an unsupported parameter, a bad one, and a good one. This + // should still fail, as anything with a badParam should fail. async function test_one_of_each_parameters() { let makeCredentialOptions = { rp, user, challenge: gCredentialChallenge, - pubKeyCredParams: [param, unsupportedParam, unknownParam] + pubKeyCredParams: [param, unsupportedParam, badParam] }; return credm.create({publicKey: makeCredentialOptions}) - .then(arrivingHereIsGood) - .catch(arrivingHereIsBad); + .then(arrivingHereIsBad) + .catch(expectTypeError); } // Test without a challenge @@ -382,31 +380,7 @@ return credm.create({publicKey: makeCredentialOptions}) .then(arrivingHereIsGood) .catch(arrivingHereIsBad); - } - - async function test_unknown_attestation_type() { - let makeCredentialOptions = { - rp, user, challenge: gCredentialChallenge, pubKeyCredParams: [param], - attestation: "unknown" - }; - return credm.create({publicKey: makeCredentialOptions }) - .then(arrivingHereIsGood) - .catch(arrivingHereIsBad); - } - - async function test_unknown_selection_criteria() { - let makeCredentialOptions = { - rp, user, challenge: gCredentialChallenge, pubKeyCredParams: [param], - authenticatorSelection: { - userVerificationRequirement: "unknown UV requirement", - authenticatorAttachment: "unknown authenticator attachment type" - }, - }; - return credm.create({publicKey: makeCredentialOptions }) - .then(arrivingHereIsGood) - .catch(arrivingHereIsBad); - } - + }; diff --git a/dom/webauthn/tests/u2f/test_webauthn_attestation_conveyance.html b/dom/webauthn/tests/u2f/test_webauthn_attestation_conveyance.html index 892d91accdb9..d173e6db90ac 100644 --- a/dom/webauthn/tests/u2f/test_webauthn_attestation_conveyance.html +++ b/dom/webauthn/tests/u2f/test_webauthn_attestation_conveyance.html @@ -83,11 +83,6 @@ .then(verifyAnonymizedCertificate) .catch(arrivingHereIsBad); - // Request an unknown attestation type. This should be treated as "none". - await requestMakeCredential("unknown") - .then(verifyAnonymizedCertificate) - .catch(arrivingHereIsBad); - // Request no attestation. await requestMakeCredential("none") .then(verifyAnonymizedCertificate) @@ -117,6 +112,14 @@ }) .catch(arrivingHereIsBad); }); + + // Test failure cases for make credential. + add_task(async function test_make_credential_failures() { + // Request a platform authenticator. + await requestMakeCredential("unknown") + .then(arrivingHereIsBad) + .catch(expectTypeError); + }); diff --git a/dom/webauthn/tests/u2f/test_webauthn_make_credential.html b/dom/webauthn/tests/u2f/test_webauthn_make_credential.html index b0725cd0da9a..9c5e5ec457a7 100644 --- a/dom/webauthn/tests/u2f/test_webauthn_make_credential.html +++ b/dom/webauthn/tests/u2f/test_webauthn_make_credential.html @@ -29,7 +29,7 @@ let user; let param; let unsupportedParam; - let unknownParam; + let badParam; // Setup test env add_task(() => { @@ -40,7 +40,7 @@ user = {id: new Uint8Array(64), name: "none", icon: "none", displayName: "none"}; param = {type: "public-key", alg: cose_alg_ECDSA_w_SHA256}; unsupportedParam = {type: "public-key", alg: cose_alg_ECDSA_w_SHA512}; - unknownParam = {type: "SimplePassword", alg: "MaxLength=2"}; + badParam = {type: "SimplePassword", alg: "MaxLength=2"}; credm = navigator.credentials; }); // Add tests @@ -55,8 +55,8 @@ add_task(test_without_parameters); add_task(test_unsupported_parameter); add_task(test_unsupported_but_one_param); - add_task(test_one_unknown_parameter); - add_task(test_one_unknown_one_unsupported_param); + add_task(test_one_bad_parameter); + add_task(test_one_bad_one_unsupported_param); add_task(test_one_of_each_parameters); add_task(test_without_challenge); add_task(test_invalid_challenge); @@ -212,37 +212,37 @@ .catch(arrivingHereIsBad); } - // Test with one unknown parameter. - async function test_one_unknown_parameter() { + // Test with a bad parameter + async function test_one_bad_parameter() { let makeCredentialOptions = { - rp, user, challenge: gCredentialChallenge, pubKeyCredParams: [unknownParam] + rp, user, challenge: gCredentialChallenge, pubKeyCredParams: [badParam] }; return credm.create({publicKey: makeCredentialOptions}) .then(arrivingHereIsBad) - .catch(expectNotSupportedError); + .catch(expectTypeError); } - // Test with an unsupported parameter, and an unknown one - async function test_one_unknown_one_unsupported_param() { + // Test with an unsupported parameter, and a bad one + async function test_one_bad_one_unsupported_param() { let makeCredentialOptions = { rp, user, challenge: gCredentialChallenge, - pubKeyCredParams: [unsupportedParam, unknownParam] + pubKeyCredParams: [unsupportedParam, badParam] }; return credm.create({publicKey: makeCredentialOptions}) .then(arrivingHereIsBad) - .catch(expectNotSupportedError); + .catch(expectTypeError); } - // Test with an unsupported parameter, an unknown one, and a good one. This - // should succeed, as the unsupported and unknown should be ignored. + // Test with an unsupported parameter, a bad one, and a good one. This + // should still fail, as anything with a badParam should fail. async function test_one_of_each_parameters() { let makeCredentialOptions = { rp, user, challenge: gCredentialChallenge, - pubKeyCredParams: [param, unsupportedParam, unknownParam] + pubKeyCredParams: [param, unsupportedParam, badParam] }; return credm.create({publicKey: makeCredentialOptions}) - .then(arrivingHereIsGood) - .catch(arrivingHereIsBad); + .then(arrivingHereIsBad) + .catch(expectTypeError); } // Test without a challenge @@ -380,31 +380,7 @@ return credm.create({publicKey: makeCredentialOptions}) .then(arrivingHereIsGood) .catch(arrivingHereIsBad); - } - - async function test_unknown_attestation_type() { - let makeCredentialOptions = { - rp, user, challenge: gCredentialChallenge, pubKeyCredParams: [param], - attestation: "unknown" - }; - return credm.create({publicKey: makeCredentialOptions }) - .then(arrivingHereIsGood) - .catch(arrivingHereIsBad); - } - - async function test_unknown_selection_criteria() { - let makeCredentialOptions = { - rp, user, challenge: gCredentialChallenge, pubKeyCredParams: [param], - authenticatorSelection: { - userVerificationRequirement: "unknown UV requirement", - authenticatorAttachment: "unknown authenticator attachment type" - }, - }; - return credm.create({publicKey: makeCredentialOptions }) - .then(arrivingHereIsGood) - .catch(arrivingHereIsBad); - } - + }; diff --git a/dom/webidl/WebAuthentication.webidl b/dom/webidl/WebAuthentication.webidl index 46025680faca..f7d9c7af22d1 100644 --- a/dom/webidl/WebAuthentication.webidl +++ b/dom/webidl/WebAuthentication.webidl @@ -45,7 +45,7 @@ interface AuthenticatorAssertionResponse : AuthenticatorResponse { }; dictionary PublicKeyCredentialParameters { - required DOMString type; + required PublicKeyCredentialType type; required COSEAlgorithmIdentifier alg; }; @@ -60,7 +60,7 @@ dictionary PublicKeyCredentialCreationOptions { sequence excludeCredentials = []; // FIXME: bug 1493860: should this "= {}" be here? AuthenticatorSelectionCriteria authenticatorSelection = {}; - DOMString attestation = "none"; + AttestationConveyancePreference attestation = "none"; // FIXME: bug 1493860: should this "= {}" be here? AuthenticationExtensionsClientInputs extensions = {}; }; @@ -80,9 +80,26 @@ dictionary PublicKeyCredentialUserEntity : PublicKeyCredentialEntity { }; dictionary AuthenticatorSelectionCriteria { - DOMString authenticatorAttachment; + AuthenticatorAttachment authenticatorAttachment; boolean requireResidentKey = false; - DOMString userVerification = "preferred"; + UserVerificationRequirement userVerification = "preferred"; +}; + +enum AuthenticatorAttachment { + "platform", // Platform attachment + "cross-platform" // Cross-platform attachment +}; + +enum AttestationConveyancePreference { + "none", + "indirect", + "direct" +}; + +enum UserVerificationRequirement { + "required", + "preferred", + "discouraged" }; dictionary PublicKeyCredentialRequestOptions { @@ -90,7 +107,7 @@ dictionary PublicKeyCredentialRequestOptions { unsigned long timeout; USVString rpId; sequence allowCredentials = []; - DOMString userVerification = "preferred"; + UserVerificationRequirement userVerification = "preferred"; // FIXME: bug 1493860: should this "= {}" be here? AuthenticationExtensionsClientInputs extensions = {}; }; @@ -131,14 +148,27 @@ dictionary TokenBinding { DOMString id; }; +enum TokenBindingStatus { "present", "supported" }; + +enum PublicKeyCredentialType { + "public-key" +}; + dictionary PublicKeyCredentialDescriptor { - required DOMString type; + required PublicKeyCredentialType type; required BufferSource id; // Transports is a string that is matched against the AuthenticatorTransport // enumeration so that we have forward-compatibility for new transports. sequence transports; }; +enum AuthenticatorTransport { + "usb", + "nfc", + "ble", + "internal" +}; + typedef long COSEAlgorithmIdentifier; typedef sequence AuthenticatorSelectionList;