Commit dfbcc8a5 authored by Martin Kreichgauer's avatar Martin Kreichgauer Committed by Commit Bot

fido/win: gate Windows WebAuthn API availability on a minimum version

There are versions of webauthn.dll that ship without BLE support. On
platforms where that is the case, direct access to FIDO token is not
blocked by the OS and so we don't want to integrate with webauthn.dll
there. This changes WinWebAuthnApi to call WebAuthNGetApiVersion on
initialization and mark the API as unavailable if the version number is
 not at least the current version (1).

The check may be overridden by a flag while we wait for
WebAuthNGetApiVersion function to ship.

Bug: 898718
Change-Id: Ic20e55a416d858214b9f444031f4700567933eb4
Reviewed-on: https://chromium-review.googlesource.com/c/1327885
Commit-Queue: Martin Kreichgauer <martinkr@chromium.org>
Reviewed-by: default avatarAdam Langley <agl@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607005}
parent 504013e7
...@@ -14,6 +14,14 @@ namespace device { ...@@ -14,6 +14,14 @@ namespace device {
// native WebAuthentication API, where available. // native WebAuthentication API, where available.
const base::Feature kWebAuthUseNativeWinApi{"WebAuthenticationUseNativeWinApi", const base::Feature kWebAuthUseNativeWinApi{"WebAuthenticationUseNativeWinApi",
base::FEATURE_DISABLED_BY_DEFAULT}; base::FEATURE_DISABLED_BY_DEFAULT};
// If true, the minimum API version check for integration with the native
// Windows WebAuthentication API is disabled. This is an interim solution for
// for manual testing while we await the release of a DLL that implements the
// version check.
const base::Feature kWebAuthDisableWinApiVersionCheckForTesting{
"WebAuthenticationDisableWinApiVersionCheckForTesting",
base::FEATURE_DISABLED_BY_DEFAULT};
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
extern const base::Feature kWebAuthProxyCryptotoken{ extern const base::Feature kWebAuthProxyCryptotoken{
......
...@@ -14,6 +14,9 @@ namespace device { ...@@ -14,6 +14,9 @@ namespace device {
#if defined(OS_WIN) #if defined(OS_WIN)
COMPONENT_EXPORT(DEVICE_FIDO) COMPONENT_EXPORT(DEVICE_FIDO)
extern const base::Feature kWebAuthUseNativeWinApi; extern const base::Feature kWebAuthUseNativeWinApi;
COMPONENT_EXPORT(DEVICE_FIDO)
extern const base::Feature kWebAuthDisableWinApiVersionCheckForTesting;
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
// Controls the proxying of Cryptotoken requests through WebAuthn. // Controls the proxying of Cryptotoken requests through WebAuthn.
......
...@@ -4,15 +4,22 @@ ...@@ -4,15 +4,22 @@
#include "device/fido/win/webauthn_api.h" #include "device/fido/win/webauthn_api.h"
#include "base/feature_list.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/native_library.h" #include "base/native_library.h"
#include "base/no_destructor.h" #include "base/no_destructor.h"
#include "device/fido/features.h"
namespace device { namespace device {
// We do not integrate with older API versions of webauthn.dll because they
// don't support BLE and direct device access to USB and BLE FIDO devices is
// not yet blocked on those platforms.
constexpr uint32_t kMinWinWebAuthnApiVersion = WEBAUTHN_API_VERSION_1;
// WinWebAuthnApiImpl is the default implementation of WinWebAuthnApi, which // WinWebAuthnApiImpl is the default implementation of WinWebAuthnApi, which
// attempts to load webauthn.dll on intialization. // attempts to load webauthn.dll on intialization.
class WinWebAuthnApiImpl : public WinWebAuthnApi { class WinWebAuthnApiImpl : public WinWebAuthnApi {
...@@ -26,32 +33,48 @@ class WinWebAuthnApiImpl : public WinWebAuthnApi { ...@@ -26,32 +33,48 @@ class WinWebAuthnApiImpl : public WinWebAuthnApi {
#define BIND_FN(fn_pointer, lib_handle, fn_name) \ #define BIND_FN(fn_pointer, lib_handle, fn_name) \
DCHECK(!fn_pointer); \ DCHECK(!fn_pointer); \
fn_pointer = reinterpret_cast<decltype(fn_pointer)>( \ fn_pointer = reinterpret_cast<decltype(fn_pointer)>( \
GetProcAddress(lib_handle, fn_name)); \ GetProcAddress(lib_handle, fn_name));
if (!fn_pointer) { \
DLOG(ERROR) << "failed to bind " << fn_name; \ #define BIND_FN_OR_RETURN(fn_pointer, lib_handle, fn_name) \
return; \ BIND_FN(fn_pointer, lib_handle, fn_name); \
if (!fn_pointer) { \
DLOG(ERROR) << "failed to bind " << fn_name; \
return; \
} }
BIND_FN(is_user_verifying_platform_authenticator_available_, webauthn_dll, BIND_FN_OR_RETURN(is_user_verifying_platform_authenticator_available_,
"WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable"); webauthn_dll,
BIND_FN(authenticator_make_credential_, webauthn_dll, "WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable");
"WebAuthNAuthenticatorMakeCredential"); BIND_FN_OR_RETURN(authenticator_make_credential_, webauthn_dll,
BIND_FN(authenticator_get_assertion_, webauthn_dll, "WebAuthNAuthenticatorMakeCredential");
"WebAuthNAuthenticatorGetAssertion"); BIND_FN_OR_RETURN(authenticator_get_assertion_, webauthn_dll,
BIND_FN(cancel_current_operation_, webauthn_dll, "WebAuthNAuthenticatorGetAssertion");
"WebAuthNCancelCurrentOperation"); BIND_FN_OR_RETURN(cancel_current_operation_, webauthn_dll,
BIND_FN(get_error_name_, webauthn_dll, "WebAuthNGetErrorName"); "WebAuthNCancelCurrentOperation");
BIND_FN(free_credential_attestation_, webauthn_dll, BIND_FN_OR_RETURN(get_error_name_, webauthn_dll, "WebAuthNGetErrorName");
"WebAuthNFreeCredentialAttestation"); BIND_FN_OR_RETURN(free_credential_attestation_, webauthn_dll,
BIND_FN(free_assertion_, webauthn_dll, "WebAuthNFreeAssertion"); "WebAuthNFreeCredentialAttestation");
BIND_FN_OR_RETURN(free_assertion_, webauthn_dll, "WebAuthNFreeAssertion");
is_bound_ = true; is_bound_ = true;
// Determine the API version of webauthn.dll. There is a version currently
// shipping with Windows RS5 from before WebAuthNGetApiVersionNumber was
// added (i.e., before WEBAUTHN_API_VERSION_1). Therefore we allow this
// function to be missing.
BIND_FN(get_api_version_number_, webauthn_dll,
"WebAuthNGetApiVersionNumber");
api_version_ = get_api_version_number_ ? get_api_version_number_() : 0;
} }
~WinWebAuthnApiImpl() override {} ~WinWebAuthnApiImpl() override {}
// WinWebAuthnApi: // WinWebAuthnApi:
bool IsAvailable() const override { return is_bound_; } bool IsAvailable() const override {
return is_bound_ && (api_version_ >= kMinWinWebAuthnApiVersion ||
base::FeatureList::IsEnabled(
kWebAuthDisableWinApiVersionCheckForTesting));
}
HRESULT IsUserVerifyingPlatformAuthenticatorAvailable(BOOL* result) override { HRESULT IsUserVerifyingPlatformAuthenticatorAvailable(BOOL* result) override {
DCHECK(is_bound_); DCHECK(is_bound_);
...@@ -113,7 +136,11 @@ class WinWebAuthnApiImpl : public WinWebAuthnApi { ...@@ -113,7 +136,11 @@ class WinWebAuthnApiImpl : public WinWebAuthnApi {
nullptr; nullptr;
decltype(&WebAuthNFreeAssertion) free_assertion_ = nullptr; decltype(&WebAuthNFreeAssertion) free_assertion_ = nullptr;
// This method is not available in all versions of webauthn.dll.
decltype(&WebAuthNGetApiVersionNumber) get_api_version_number_ = nullptr;
bool is_bound_ = false; bool is_bound_ = false;
uint32_t api_version_ = 0;
}; };
static WinWebAuthnApi* kDefaultForTesting = nullptr; static WinWebAuthnApi* kDefaultForTesting = nullptr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment