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

device/fido/mac: integrate with browsing data deletion

This updates browsing data deletion for DATA_TYPE_PASSWORDS to call
device::fido::mac::DeleteWebAuthnCredentials, which deletes credentials
created by the macOS platform authenticator from the OS keychain.

Also combine the two Touch ID specific configuration methods in
{Chrome,}AuthenticatorRequestDelegate and introduce a static variant for
Chrome.

Bug: 678128
Change-Id: I0034e0815da068fb27c1ea60cad95f958956838e
Reviewed-on: https://chromium-review.googlesource.com/1125177
Commit-Queue: Martin Kreichgauer <martinkr@google.com>
Reviewed-by: default avatarKim Paulhamus <kpaulhamus@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Reviewed-by: default avatarChristian Dullweber <dullweber@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#574697}
parent 460febcb
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/sessions/tab_restore_service_factory.h" #include "chrome/browser/sessions/tab_restore_service_factory.h"
#include "chrome/browser/web_data_service_factory.h" #include "chrome/browser/web_data_service_factory.h"
#include "chrome/browser/webauthn/chrome_authenticator_request_delegate.h"
#include "chrome/common/buildflags.h" #include "chrome/common/buildflags.h"
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h" #include "chrome/common/url_constants.h"
...@@ -129,6 +130,10 @@ ...@@ -129,6 +130,10 @@
#include "components/user_manager/user.h" #include "components/user_manager/user.h"
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
#if defined(OS_MACOSX)
#include "device/fido/mac/browsing_data_deletion.h"
#endif // defined(OS_MACOSX)
#if BUILDFLAG(ENABLE_PLUGINS) #if BUILDFLAG(ENABLE_PLUGINS)
#include "chrome/browser/browsing_data/browsing_data_flash_lso_helper.h" #include "chrome/browser/browsing_data/browsing_data_flash_lso_helper.h"
#endif // BUILDFLAG(ENABLE_PLUGINS) #endif // BUILDFLAG(ENABLE_PLUGINS)
...@@ -782,6 +787,14 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData( ...@@ -782,6 +787,14 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData(
->GetNetworkContext() ->GetNetworkContext()
->ClearHttpAuthCache(delete_begin_, ->ClearHttpAuthCache(delete_begin_,
CreatePendingTaskCompletionClosureForMojo()); CreatePendingTaskCompletionClosureForMojo());
#if defined(OS_MACOSX)
auto authenticator_config = ChromeAuthenticatorRequestDelegate::
TouchIdAuthenticatorConfigForProfile(profile_);
device::fido::mac::DeleteWebAuthnCredentials(
authenticator_config.keychain_access_group,
authenticator_config.metadata_secret, delete_begin_, delete_end_);
#endif // defined(OS_MACOSX)
} }
if (remove_mask & content::BrowsingDataRemover::DATA_TYPE_COOKIES) { if (remove_mask & content::BrowsingDataRemover::DATA_TYPE_COOKIES) {
......
...@@ -178,21 +178,13 @@ bool ChromeAuthenticatorRequestDelegate::IsFocused() { ...@@ -178,21 +178,13 @@ bool ChromeAuthenticatorRequestDelegate::IsFocused() {
} }
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
std::string static constexpr char kTouchIdKeychainAccessGroup[] =
ChromeAuthenticatorRequestDelegate::TouchIdAuthenticatorKeychainAccessGroup() { "EQHXZ8M8AV.com.google.Chrome.webauthn";
// This exact value must be whitelisted in the keychain-access-group section
// of the entitlements plist file with which Chrome is signed. Note that
// even though the bundle identifier for the Canary channel differs from that
// of the other channels, Canary still uses the same keychain access group.
static const char* access_group = "EQHXZ8M8AV.com.google.Chrome.webauthn";
return access_group;
}
#endif
#if defined(OS_MACOSX) namespace {
std::string ChromeAuthenticatorRequestDelegate::TouchIdMetadataSecret() {
PrefService* prefs = std::string TouchIdMetadataSecret(Profile* profile) {
Profile::FromBrowserContext(browser_context())->GetPrefs(); PrefService* prefs = profile->GetPrefs();
std::string key = prefs->GetString(kWebAuthnTouchIdMetadataSecretPrefName); std::string key = prefs->GetString(kWebAuthnTouchIdMetadataSecretPrefName);
if (key.empty() || !base::Base64Decode(key, &key)) { if (key.empty() || !base::Base64Decode(key, &key)) {
key = device::fido::mac::CredentialMetadata::GenerateRandomSecret(); key = device::fido::mac::CredentialMetadata::GenerateRandomSecret();
...@@ -202,6 +194,24 @@ std::string ChromeAuthenticatorRequestDelegate::TouchIdMetadataSecret() { ...@@ -202,6 +194,24 @@ std::string ChromeAuthenticatorRequestDelegate::TouchIdMetadataSecret() {
} }
return key; return key;
} }
} // namespace
// static
content::AuthenticatorRequestClientDelegate::TouchIdAuthenticatorConfig
ChromeAuthenticatorRequestDelegate::TouchIdAuthenticatorConfigForProfile(
Profile* profile) {
return content::AuthenticatorRequestClientDelegate::
TouchIdAuthenticatorConfig{kTouchIdKeychainAccessGroup,
TouchIdMetadataSecret(profile)};
}
base::Optional<
content::AuthenticatorRequestClientDelegate::TouchIdAuthenticatorConfig>
ChromeAuthenticatorRequestDelegate::GetTouchIdAuthenticatorConfig() const {
return TouchIdAuthenticatorConfigForProfile(
Profile::FromBrowserContext(browser_context()));
}
#endif #endif
void ChromeAuthenticatorRequestDelegate::OnModelDestroyed() { void ChromeAuthenticatorRequestDelegate::OnModelDestroyed() {
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include "chrome/browser/webauthn/authenticator_request_dialog_model.h" #include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
#include "content/public/browser/authenticator_request_client_delegate.h" #include "content/public/browser/authenticator_request_client_delegate.h"
class Profile;
namespace content { namespace content {
class BrowserContext; class BrowserContext;
class RenderFrameHost; class RenderFrameHost;
...@@ -26,18 +28,22 @@ class ChromeAuthenticatorRequestDelegate ...@@ -26,18 +28,22 @@ class ChromeAuthenticatorRequestDelegate
public AuthenticatorRequestDialogModel::Observer { public AuthenticatorRequestDialogModel::Observer {
public: public:
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
#if defined(OS_MACOSX)
static TouchIdAuthenticatorConfig TouchIdAuthenticatorConfigForProfile(
Profile* profile);
#endif // defined(OS_MACOSX)
// The |render_frame_host| must outlive this instance. // The |render_frame_host| must outlive this instance.
explicit ChromeAuthenticatorRequestDelegate( explicit ChromeAuthenticatorRequestDelegate(
content::RenderFrameHost* render_frame_host); content::RenderFrameHost* render_frame_host);
~ChromeAuthenticatorRequestDelegate() override; ~ChromeAuthenticatorRequestDelegate() override;
base::WeakPtr<ChromeAuthenticatorRequestDelegate> AsWeakPtr();
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
std::string TouchIdAuthenticatorKeychainAccessGroup() override; base::Optional<TouchIdAuthenticatorConfig> GetTouchIdAuthenticatorConfig()
std::string TouchIdMetadataSecret() override; const override;
#endif #endif // defined(OS_MACOSX)
base::WeakPtr<ChromeAuthenticatorRequestDelegate> AsWeakPtr();
private: private:
content::RenderFrameHost* render_frame_host() const { content::RenderFrameHost* render_frame_host() const {
......
...@@ -17,11 +17,18 @@ class ChromeAuthenticatorRequestDelegateTest ...@@ -17,11 +17,18 @@ class ChromeAuthenticatorRequestDelegateTest
: public ChromeRenderViewHostTestHarness {}; : public ChromeRenderViewHostTestHarness {};
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
std::string TouchIdMetadataSecret(
const ChromeAuthenticatorRequestDelegate& delegate) {
base::Optional<AuthenticatorRequestClientDelegate::TouchIdAuthenticatorConfig>
config = delegate.GetTouchIdAuthenticatorConfig();
return config->metadata_secret;
}
TEST_F(ChromeAuthenticatorRequestDelegateTest, TouchIdMetadataSecret) { TEST_F(ChromeAuthenticatorRequestDelegateTest, TouchIdMetadataSecret) {
ChromeAuthenticatorRequestDelegate delegate(main_rfh()); ChromeAuthenticatorRequestDelegate delegate(main_rfh());
std::string secret = delegate.TouchIdMetadataSecret(); std::string secret = TouchIdMetadataSecret(delegate);
EXPECT_EQ(secret.size(), 32u); EXPECT_EQ(secret.size(), 32u);
EXPECT_EQ(secret, delegate.TouchIdMetadataSecret()); EXPECT_EQ(secret, TouchIdMetadataSecret(delegate));
} }
TEST_F(ChromeAuthenticatorRequestDelegateTest, TEST_F(ChromeAuthenticatorRequestDelegateTest,
...@@ -29,8 +36,8 @@ TEST_F(ChromeAuthenticatorRequestDelegateTest, ...@@ -29,8 +36,8 @@ TEST_F(ChromeAuthenticatorRequestDelegateTest,
// Different delegates on the same BrowserContext (Profile) should return the // Different delegates on the same BrowserContext (Profile) should return the
// same secret. // same secret.
EXPECT_EQ( EXPECT_EQ(
ChromeAuthenticatorRequestDelegate(main_rfh()).TouchIdMetadataSecret(), TouchIdMetadataSecret(ChromeAuthenticatorRequestDelegate(main_rfh())),
ChromeAuthenticatorRequestDelegate(main_rfh()).TouchIdMetadataSecret()); TouchIdMetadataSecret(ChromeAuthenticatorRequestDelegate(main_rfh())));
} }
TEST_F(ChromeAuthenticatorRequestDelegateTest, TEST_F(ChromeAuthenticatorRequestDelegateTest,
...@@ -41,14 +48,13 @@ TEST_F(ChromeAuthenticatorRequestDelegateTest, ...@@ -41,14 +48,13 @@ TEST_F(ChromeAuthenticatorRequestDelegateTest,
auto web_contents = auto web_contents =
WebContentsTester::CreateTestWebContents(browser_context.get(), nullptr); WebContentsTester::CreateTestWebContents(browser_context.get(), nullptr);
EXPECT_NE( EXPECT_NE(
ChromeAuthenticatorRequestDelegate(main_rfh()).TouchIdMetadataSecret(), TouchIdMetadataSecret(ChromeAuthenticatorRequestDelegate(main_rfh())),
ChromeAuthenticatorRequestDelegate(web_contents->GetMainFrame()) TouchIdMetadataSecret(
.TouchIdMetadataSecret()); ChromeAuthenticatorRequestDelegate(web_contents->GetMainFrame())));
// Ensure this second secret is actually valid. // Ensure this second secret is actually valid.
EXPECT_EQ(32u, EXPECT_EQ(32u, TouchIdMetadataSecret(ChromeAuthenticatorRequestDelegate(
ChromeAuthenticatorRequestDelegate(web_contents->GetMainFrame()) web_contents->GetMainFrame()))
.TouchIdMetadataSecret() .size());
.size());
} }
#endif #endif
......
...@@ -816,12 +816,15 @@ void AuthenticatorImpl::Cleanup() { ...@@ -816,12 +816,15 @@ void AuthenticatorImpl::Cleanup() {
std::unique_ptr<device::FidoAuthenticator> std::unique_ptr<device::FidoAuthenticator>
AuthenticatorImpl::MaybeCreatePlatformAuthenticator() { AuthenticatorImpl::MaybeCreatePlatformAuthenticator() {
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
return device::fido::mac::TouchIdAuthenticator::CreateIfAvailable( auto opt_authenticator_config =
request_delegate_->TouchIdAuthenticatorKeychainAccessGroup(), request_delegate_->GetTouchIdAuthenticatorConfig();
request_delegate_->TouchIdMetadataSecret()); if (opt_authenticator_config) {
#else return device::fido::mac::TouchIdAuthenticator::CreateIfAvailable(
std::move(opt_authenticator_config->keychain_access_group),
std::move(opt_authenticator_config->metadata_secret));
}
#endif // defined(OS_MACOSX)
return nullptr; return nullptr;
#endif
} }
} // namespace content } // namespace content
...@@ -32,15 +32,9 @@ bool AuthenticatorRequestClientDelegate::IsFocused() { ...@@ -32,15 +32,9 @@ bool AuthenticatorRequestClientDelegate::IsFocused() {
} }
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
std::string base::Optional<AuthenticatorRequestClientDelegate::TouchIdAuthenticatorConfig>
AuthenticatorRequestClientDelegate::TouchIdAuthenticatorKeychainAccessGroup() { AuthenticatorRequestClientDelegate::GetTouchIdAuthenticatorConfig() const {
return std::string(); return base::nullopt;
}
#endif
#if defined(OS_MACOSX)
std::string AuthenticatorRequestClientDelegate::TouchIdMetadataSecret() {
return std::string();
} }
#endif #endif
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/optional.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
...@@ -55,20 +56,24 @@ class CONTENT_EXPORT AuthenticatorRequestClientDelegate { ...@@ -55,20 +56,24 @@ class CONTENT_EXPORT AuthenticatorRequestClientDelegate {
virtual bool IsFocused(); virtual bool IsFocused();
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
// Returns the kechain-access-group value used for WebAuthn credentials struct TouchIdAuthenticatorConfig {
// stored in the macOS keychain by the built-in Touch ID authenticator. For // The keychain-access-group value used for WebAuthn credentials
// more information on this, refer to |device::fido::TouchIdAuthenticator|. // stored in the macOS keychain by the built-in Touch ID
// This method may to return empty string or some other placeholder value on // authenticator. For more information on this, refer to
// platforms where |TouchIdAuthenticator| is not used. // |device::fido::TouchIdAuthenticator|.
virtual std::string TouchIdAuthenticatorKeychainAccessGroup(); std::string keychain_access_group;
// The secret used to derive key material when encrypting WebAuthn
// credential metadata for storage in the macOS keychain. Chrome returns
// different secrets for each user profile in order to logically separate
// credentials per profile.
std::string metadata_secret;
};
// Returns the secret used to derive key material when encrypting WebAuthn // Returns configuration data for the built-in Touch ID platform
// credential metadata for storage in the macOS keychain. Chrome returns // authenticator. May return nullopt if the authenticator is not used or not
// different secrets for each user profile in order to logically separate // available.
// credentials per profile. This method may to return empty string or some virtual base::Optional<TouchIdAuthenticatorConfig>
// other placeholder value on platforms where |TouchIdAuthenticator| is not GetTouchIdAuthenticatorConfig() const;
// used.
virtual std::string TouchIdMetadataSecret();
#endif #endif
private: private:
......
...@@ -28,13 +28,14 @@ class COMPONENT_EXPORT(DEVICE_FIDO) TouchIdAuthenticator ...@@ -28,13 +28,14 @@ class COMPONENT_EXPORT(DEVICE_FIDO) TouchIdAuthenticator
static std::unique_ptr<TouchIdAuthenticator> CreateIfAvailable( static std::unique_ptr<TouchIdAuthenticator> CreateIfAvailable(
std::string keychain_access_group, std::string keychain_access_group,
std::string metadata_secret); std::string metadata_secret);
static std::unique_ptr<TouchIdAuthenticator> CreateForTesting( static std::unique_ptr<TouchIdAuthenticator> CreateForTesting(
std::string keychain_access_group, std::string keychain_access_group,
std::string metadata_secret); std::string metadata_secret);
~TouchIdAuthenticator() override; ~TouchIdAuthenticator() override;
// TouchIdAuthenticator // FidoAuthenticator
void MakeCredential( void MakeCredential(
AuthenticatorSelectionCriteria authenticator_selection_criteria, AuthenticatorSelectionCriteria authenticator_selection_criteria,
CtapMakeCredentialRequest request, CtapMakeCredentialRequest request,
...@@ -42,7 +43,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) TouchIdAuthenticator ...@@ -42,7 +43,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) TouchIdAuthenticator
void GetAssertion(CtapGetAssertionRequest request, void GetAssertion(CtapGetAssertionRequest request,
GetAssertionCallback callback) override; GetAssertionCallback callback) override;
void Cancel() override; void Cancel() override;
std::string GetId() const override; std::string GetId() const override;
private: private:
...@@ -52,7 +52,8 @@ class COMPONENT_EXPORT(DEVICE_FIDO) TouchIdAuthenticator ...@@ -52,7 +52,8 @@ class COMPONENT_EXPORT(DEVICE_FIDO) TouchIdAuthenticator
// The keychain access group under which credentials are stored in the macOS // The keychain access group under which credentials are stored in the macOS
// keychain for access control. The set of all access groups that the // keychain for access control. The set of all access groups that the
// application belongs to is stored in the entitlements file that gets // application belongs to is stored in the entitlements file that gets
// embedded into the application during code signing. For more information see // embedded into the application during code signing. For more information
// see
// https://developer.apple.com/documentation/security/ksecattraccessgroup?language=objc. // https://developer.apple.com/documentation/security/ksecattraccessgroup?language=objc.
std::string keychain_access_group_; std::string keychain_access_group_;
......
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