blob: 47b80fb2c7895df2d5237dd1b18950e250ffa9aa [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/webauthn/unexportable_key_utils.h"
#include <memory>
#include "base/feature_list.h"
#include "build/build_config.h"
#include "crypto/unexportable_key.h"
#include "crypto/user_verifying_key.h"
#include "device/fido/enclave/constants.h"
#include "device/fido/features.h"
#if BUILDFLAG(IS_MAC)
#include "chrome/browser/webauthn/enclave_manager.h"
#endif // BUILDFLAG(IS_MAC)
std::unique_ptr<crypto::UnexportableKeyProvider>
GetWebAuthnUnexportableKeyProvider() {
// On Linux, access to the TPM is complex compared to Windows and macOS.
// There are libraries that _should_ work with a TPM 2.0, but Linux often
// runs on non-PCs, where TPMs will probably never exist. Thus gating enclave
// features on the presence of a TPM isn't viable, and trying to use one
// where it is present seems complex and likely to cause lots of problems.
// Thus Linux saves identity keys on disk.
//
// ChromeOS would need to implement support for unexportable keys backed by
// TPM/H1 in a system daemon. This doesn't exist at present, so keys are
// instead saved on disk.
//
// If there is a scoped UnexportableKeyProvider configured, we always use
// that so that tests can still override the key provider.
const bool use_software_provider =
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
!crypto::internal::HasScopedUnexportableKeyProvider();
#else
false;
#endif
if (use_software_provider ||
base::FeatureList::IsEnabled(
device::kWebAuthnUseInsecureSoftwareUnexportableKeys)) {
return crypto::GetSoftwareUnsecureUnexportableKeyProvider();
}
crypto::UnexportableKeyProvider::Config config;
#if BUILDFLAG(IS_MAC)
config.keychain_access_group =
EnclaveManager::kEnclaveKeysKeychainAccessGroup;
#endif // BUILDFLAG(IS_MAC)
std::unique_ptr<crypto::UnexportableKeyProvider> provider =
crypto::GetUnexportableKeyProvider(std::move(config));
if ((!provider || provider->SelectAlgorithm(
device::enclave::kSigningAlgorithms) == std::nullopt) &&
base::FeatureList::IsEnabled(
device::kWebAuthnMicrosoftSoftwareUnexportableKeyProvider)) {
// On Windows, if there is no TPM support, use the Microsoft Software Key
// Storage Provider instead.
provider = crypto::GetMicrosoftSoftwareUnexportableKeyProvider();
}
return provider;
}
std::unique_ptr<crypto::UserVerifyingKeyProvider>
GetWebAuthnUserVerifyingKeyProvider(
crypto::UserVerifyingKeyProvider::Config config) {
return crypto::GetUserVerifyingKeyProvider(std::move(config));
}