0

webauthn: remove macOS 10.12 checks

The minimum is 10.13 now.

Bug: 1322548
Change-Id: I6e600827733fb24644b5a7a54c22afb8b94df2c4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3644698
Commit-Queue: Martin Kreichgauer <martinkr@google.com>
Auto-Submit: Martin Kreichgauer <martinkr@google.com>
Reviewed-by: Nina Satragno <nsatragno@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1004521}
This commit is contained in:
Martin Kreichgauer
2022-05-17 23:47:56 +00:00
committed by Chromium LUCI CQ
parent 3aaabf4d3a
commit c25bdf4500
20 changed files with 127 additions and 230 deletions

@ -8169,7 +8169,6 @@ TEST_F(TouchIdAuthenticatorImplTest, IsUVPAA) {
NavigateAndCommit(GURL(kTestOrigin1));
mojo::Remote<blink::mojom::Authenticator> authenticator =
ConnectToAuthenticator();
for (const bool touch_id_available : {false, true}) {
SCOPED_TRACE(::testing::Message()
<< "touch_id_available=" << touch_id_available);

@ -275,19 +275,12 @@ void FidoCableDiscovery::OnGetAdapter(scoped_refptr<BluetoothAdapter> adapter) {
#if BUILDFLAG(IS_MAC)
// TODO(crbug.com/1314404): turn this into a user-visible UI if we believe
// that it's a good signal.
switch (fido::mac::ProcessIsSigned()) {
case fido::mac::CodeSigningState::kUnknown:
FIDO_LOG(DEBUG) << "Cannot determine whether build is signed. Assuming "
"Bluetooth permission is granted.";
break;
case fido::mac::CodeSigningState::kSigned:
FIDO_LOG(DEBUG) << "Bluetooth authorized: "
<< (adapter_->GetOsPermissionStatus() !=
BluetoothAdapter::PermissionStatus::kDenied);
break;
case fido::mac::CodeSigningState::kNotSigned:
FIDO_LOG(DEBUG)
<< "Build not signed. Assuming Bluetooth permission is granted.";

@ -36,11 +36,7 @@ namespace mac {
void TouchIdAuthenticator::IsAvailable(
AuthenticatorConfig config,
base::OnceCallback<void(bool is_available)> callback) {
if (__builtin_available(macOS 10.12.2, *)) {
TouchIdContext::TouchIdAvailable(std::move(config), std::move(callback));
return;
}
std::move(callback).Run(false);
TouchIdContext::TouchIdAvailable(std::move(config), std::move(callback));
}
// static
@ -61,84 +57,65 @@ void TouchIdAuthenticator::InitializeAuthenticator(base::OnceClosure callback) {
void TouchIdAuthenticator::GetCredentialInformationForRequest(
const CtapGetAssertionRequest& request,
GetCredentialInformationForRequestCallback callback) {
if (__builtin_available(macOS 10.12.2, *)) {
if (!request.allow_list.empty()) {
// Non resident credentials request.
absl::optional<std::list<Credential>> credentials =
credential_store_.FindCredentialsFromCredentialDescriptorList(
request.rp_id, request.allow_list);
if (!credentials) {
FIDO_LOG(ERROR)
<< "FindCredentialsFromCredentialDescriptorList() failed";
std::move(callback).Run(/*credentials=*/{}, /*has_credentials=*/false);
return;
}
std::move(callback).Run(/*credentials=*/{},
/*has_credentials=*/!credentials->empty());
return;
}
// Resident credentials request.
absl::optional<std::list<Credential>> resident_credentials =
credential_store_.FindResidentCredentials(request.rp_id);
if (!resident_credentials) {
FIDO_LOG(ERROR) << "GetResidentCredentialsForRequest() failed";
if (!request.allow_list.empty()) {
// Non resident credentials request.
absl::optional<std::list<Credential>> credentials =
credential_store_.FindCredentialsFromCredentialDescriptorList(
request.rp_id, request.allow_list);
if (!credentials) {
FIDO_LOG(ERROR) << "FindCredentialsFromCredentialDescriptorList() failed";
std::move(callback).Run(/*credentials=*/{}, /*has_credentials=*/false);
return;
}
std::vector<DiscoverableCredentialMetadata> result;
for (const auto& credential : *resident_credentials) {
absl::optional<CredentialMetadata> metadata =
credential_store_.UnsealMetadata(request.rp_id, credential);
if (!metadata) {
FIDO_LOG(ERROR) << "Could not unseal metadata from resident credential";
continue;
}
result.emplace_back(DiscoverableCredentialMetadata(
credential.credential_id,
metadata->ToPublicKeyCredentialUserEntity()));
}
std::move(callback).Run(std::move(result), !resident_credentials->empty());
std::move(callback).Run(/*credentials=*/{},
/*has_credentials=*/!credentials->empty());
return;
}
NOTREACHED();
std::move(callback).Run(/*credentials=*/{}, /*has_credentials=*/false);
// Resident credentials request.
absl::optional<std::list<Credential>> resident_credentials =
credential_store_.FindResidentCredentials(request.rp_id);
if (!resident_credentials) {
FIDO_LOG(ERROR) << "GetResidentCredentialsForRequest() failed";
std::move(callback).Run(/*credentials=*/{}, /*has_credentials=*/false);
return;
}
std::vector<DiscoverableCredentialMetadata> result;
for (const auto& credential : *resident_credentials) {
absl::optional<CredentialMetadata> metadata =
credential_store_.UnsealMetadata(request.rp_id, credential);
if (!metadata) {
FIDO_LOG(ERROR) << "Could not unseal metadata from resident credential";
continue;
}
result.emplace_back(DiscoverableCredentialMetadata(
credential.credential_id, metadata->ToPublicKeyCredentialUserEntity()));
}
std::move(callback).Run(std::move(result), !resident_credentials->empty());
}
void TouchIdAuthenticator::MakeCredential(CtapMakeCredentialRequest request,
MakeCredentialOptions options,
MakeCredentialCallback callback) {
if (__builtin_available(macOS 10.12.2, *)) {
DCHECK(!operation_);
operation_ = std::make_unique<MakeCredentialOperation>(
std::move(request), &credential_store_, std::move(callback));
operation_->Run();
return;
}
NOTREACHED();
DCHECK(!operation_);
operation_ = std::make_unique<MakeCredentialOperation>(
std::move(request), &credential_store_, std::move(callback));
operation_->Run();
}
void TouchIdAuthenticator::GetAssertion(CtapGetAssertionRequest request,
CtapGetAssertionOptions options,
GetAssertionCallback callback) {
if (__builtin_available(macOS 10.12.2, *)) {
DCHECK(!operation_);
operation_ = std::make_unique<GetAssertionOperation>(
std::move(request), &credential_store_, std::move(callback));
operation_->Run();
return;
}
NOTREACHED();
DCHECK(!operation_);
operation_ = std::make_unique<GetAssertionOperation>(
std::move(request), &credential_store_, std::move(callback));
operation_->Run();
}
void TouchIdAuthenticator::GetNextAssertion(GetAssertionCallback callback) {
if (__builtin_available(macOS 10.12.2, *)) {
DCHECK(operation_);
reinterpret_cast<GetAssertionOperation*>(operation_.get())
->GetNextAssertion(std::move(callback));
return;
}
NOTREACHED();
DCHECK(operation_);
reinterpret_cast<GetAssertionOperation*>(operation_.get())
->GetNextAssertion(std::move(callback));
}
void TouchIdAuthenticator::Cancel() {

@ -71,22 +71,18 @@ base::ScopedCFTypeRef<CFMutableDictionaryRef> BaseQuery() {
// profile they are associated with. May return a null reference if an error
// occurred.
base::ScopedCFTypeRef<CFArrayRef> QueryAllCredentials() {
if (__builtin_available(macOS 10.12.2, *)) {
base::ScopedCFTypeRef<CFArrayRef> items;
OSStatus status = Keychain::GetInstance().ItemCopyMatching(
BaseQuery(), reinterpret_cast<CFTypeRef*>(items.InitializeInto()));
if (status == errSecItemNotFound) {
// The API returns null, but we should return an empty array instead to
// distinguish from real errors.
items = base::ScopedCFTypeRef<CFArrayRef>(
CFArrayCreate(nullptr, nullptr, 0, nullptr));
} else if (status != errSecSuccess) {
OSSTATUS_DLOG(ERROR, status);
}
return items;
base::ScopedCFTypeRef<CFArrayRef> items;
OSStatus status = Keychain::GetInstance().ItemCopyMatching(
BaseQuery(), reinterpret_cast<CFTypeRef*>(items.InitializeInto()));
if (status == errSecItemNotFound) {
// The API returns null, but we should return an empty array instead to
// distinguish from real errors.
items = base::ScopedCFTypeRef<CFArrayRef>(
CFArrayCreate(nullptr, nullptr, 0, nullptr));
} else if (status != errSecSuccess) {
OSSTATUS_DLOG(ERROR, status);
}
NOTREACHED();
return base::ScopedCFTypeRef<CFArrayRef>(nullptr);
return items;
}
// Returns the number of WebAuthn credentials in the keychain (for all
@ -97,16 +93,12 @@ ssize_t KeychainItemCount() {
}
bool ResetKeychain() {
if (__builtin_available(macOS 10.12.2, *)) {
OSStatus status = Keychain::GetInstance().ItemDelete(BaseQuery());
if (status != errSecSuccess && status != errSecItemNotFound) {
OSSTATUS_DLOG(ERROR, status);
return false;
}
return true;
OSStatus status = Keychain::GetInstance().ItemDelete(BaseQuery());
if (status != errSecSuccess && status != errSecItemNotFound) {
OSSTATUS_DLOG(ERROR, status);
return false;
}
NOTREACHED();
return false;
return true;
}
class BrowsingDataDeletionTest : public testing::Test {

@ -72,7 +72,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) TouchIdCredentialStore
// CreateCredential inserts a new credential into the keychain. It returns
// the new credential and its public key, or absl::nullopt if an error
// occurred.
API_AVAILABLE(macosx(10.12.2))
absl::optional<std::pair<Credential, base::ScopedCFTypeRef<SecKeyRef>>>
CreateCredential(const std::string& rp_id,
const PublicKeyCredentialUserEntity& user,
@ -85,7 +84,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) TouchIdCredentialStore
// FidoTransportProtocol::kInternal, and if its id() is the credential ID.
// The returned credentials may be resident or non-resident. If any
// unexpected keychain API error occurs, absl::nullopt is returned instead.
API_AVAILABLE(macosx(10.12.2))
absl::optional<std::list<Credential>>
FindCredentialsFromCredentialDescriptorList(
const std::string& rp_id,
@ -93,13 +91,11 @@ class COMPONENT_EXPORT(DEVICE_FIDO) TouchIdCredentialStore
// FindResidentCredentials returns the resident credentials for the given
// |rp_id|, or base::nulltopt if an error occurred.
API_AVAILABLE(macosx(10.12.2))
absl::optional<std::list<Credential>> FindResidentCredentials(
const std::string& rp_id) const;
// UnsealMetadata returns the CredentialMetadata for the given credential's
// ID if it was encoded for the given RP ID, or absl::nullopt otherwise.
API_AVAILABLE(macosx(10.12.2))
absl::optional<CredentialMetadata> UnsealMetadata(
const std::string& rp_id,
const Credential& credential) const;
@ -107,7 +103,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) TouchIdCredentialStore
// DeleteCredentialsForUserId deletes all (resident or non-resident)
// credentials for the given RP and user ID. Returns true if deleting
// succeeded or no matching credential exists, and false otherwise.
API_AVAILABLE(macosx(10.12.2))
bool DeleteCredentialsForUserId(const std::string& rp_id,
base::span<const uint8_t> user_id) const;
@ -129,7 +124,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) TouchIdCredentialStore
base::Time created_not_after);
private:
API_AVAILABLE(macosx(10.12.2))
absl::optional<std::list<Credential>> FindCredentialsImpl(
const std::string& rp_id,
const std::set<std::vector<uint8_t>>& credential_ids) const;

@ -72,8 +72,7 @@ absl::optional<std::vector<base::ScopedCFTypeRef<CFDictionaryRef>>>
QueryKeychainItemsForProfile(const std::string& keychain_access_group,
const std::string& metadata_secret,
base::Time created_not_before,
base::Time created_not_after)
API_AVAILABLE(macosx(10.12.2)) {
base::Time created_not_after) {
// Query the keychain for all items tagged with the given access group, which
// should in theory yield all WebAuthentication credentials (for all
// profiles). Sadly, the kSecAttrAccessGroup filter doesn't quite work, and
@ -149,69 +148,6 @@ QueryKeychainItemsForProfile(const std::string& keychain_access_group,
return result;
}
bool DoDeleteWebAuthnCredentials(const std::string& keychain_access_group,
const std::string& metadata_secret,
base::Time created_not_before,
base::Time created_not_after)
API_AVAILABLE(macosx(10.12.2)) {
bool result = true;
absl::optional<std::vector<base::ScopedCFTypeRef<CFDictionaryRef>>>
keychain_items =
QueryKeychainItemsForProfile(keychain_access_group, metadata_secret,
created_not_before, created_not_after);
if (!keychain_items) {
return false;
}
// The sane way to delete this item would be to build a query that has the
// kSecMatchItemList field set to a list of SecKeyRef objects that need
// deleting. Sadly, on macOS that appears to work only if you also set
// kSecAttrNoLegacy (which is an internal symbol); otherwise it appears to
// only search the "legacy" keychain and return errSecItemNotFound. What
// does work however, is to look up and delete by the (unique)
// kSecAttrApplicationLabel (which stores the credential id). So we clumsily
// do this for each item instead.
for (const base::ScopedCFTypeRef<CFDictionaryRef>& attributes :
*keychain_items) {
CFDataRef sec_attr_app_label = base::mac::GetValueFromDictionary<CFDataRef>(
attributes.get(), kSecAttrApplicationLabel);
if (!sec_attr_app_label) {
DLOG(ERROR) << "missing application label";
continue;
}
base::ScopedCFTypeRef<CFMutableDictionaryRef> delete_query(
CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks));
CFDictionarySetValue(delete_query, kSecClass, kSecClassKey);
CFDictionarySetValue(delete_query, kSecAttrApplicationLabel,
sec_attr_app_label);
OSStatus status = Keychain::GetInstance().ItemDelete(delete_query);
if (status != errSecSuccess) {
OSSTATUS_DLOG(ERROR, status) << "SecItemDelete failed";
result = false;
continue;
}
}
return result;
}
size_t DoCountWebAuthnCredentials(const std::string& keychain_access_group,
const std::string& metadata_secret,
base::Time created_not_before,
base::Time created_not_after)
API_AVAILABLE(macosx(10.12.2)) {
absl::optional<std::vector<base::ScopedCFTypeRef<CFDictionaryRef>>>
keychain_items =
QueryKeychainItemsForProfile(keychain_access_group, metadata_secret,
created_not_before, created_not_after);
if (!keychain_items) {
DLOG(ERROR) << "Failed to query credentials in keychain";
return 0;
}
return keychain_items->size();
}
} // namespace
Credential::Credential(base::ScopedCFTypeRef<SecKeyRef> private_key_,
@ -366,28 +302,62 @@ void TouchIdCredentialStore::CountCredentials(
bool TouchIdCredentialStore::DeleteCredentialsSync(
base::Time created_not_before,
base::Time created_not_after) {
// Touch ID uses macOS APIs available in 10.12.2 or newer. No need to check
// for credentials in lower OS versions.
if (__builtin_available(macos 10.12.2, *)) {
return DoDeleteWebAuthnCredentials(config_.keychain_access_group,
config_.metadata_secret,
created_not_before, created_not_after);
absl::optional<std::vector<base::ScopedCFTypeRef<CFDictionaryRef>>>
keychain_items = QueryKeychainItemsForProfile(
config_.keychain_access_group, config_.metadata_secret,
created_not_before, created_not_after);
if (!keychain_items) {
return false;
}
return true;
// The sane way to delete this item would be to build a query that has the
// kSecMatchItemList field set to a list of SecKeyRef objects that need
// deleting. Sadly, on macOS that appears to work only if you also set
// kSecAttrNoLegacy (which is an internal symbol); otherwise it appears to
// only search the "legacy" keychain and return errSecItemNotFound. What
// does work however, is to look up and delete by the (unique)
// kSecAttrApplicationLabel (which stores the credential id). So we clumsily
// do this for each item instead.
bool result = true;
for (const base::ScopedCFTypeRef<CFDictionaryRef>& attributes :
*keychain_items) {
CFDataRef sec_attr_app_label = base::mac::GetValueFromDictionary<CFDataRef>(
attributes.get(), kSecAttrApplicationLabel);
if (!sec_attr_app_label) {
DLOG(ERROR) << "missing application label";
continue;
}
base::ScopedCFTypeRef<CFMutableDictionaryRef> delete_query(
CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks));
CFDictionarySetValue(delete_query, kSecClass, kSecClassKey);
CFDictionarySetValue(delete_query, kSecAttrApplicationLabel,
sec_attr_app_label);
OSStatus status = Keychain::GetInstance().ItemDelete(delete_query);
if (status != errSecSuccess) {
// Indicate failure but keep deleting remaining items.
OSSTATUS_DLOG(ERROR, status) << "SecItemDelete failed";
result = false;
}
}
return result;
}
size_t TouchIdCredentialStore::CountCredentialsSync(
base::Time created_not_before,
base::Time created_not_after) {
if (__builtin_available(macos 10.12.2, *)) {
return DoCountWebAuthnCredentials(config_.keychain_access_group,
config_.metadata_secret,
created_not_before, created_not_after);
absl::optional<std::vector<base::ScopedCFTypeRef<CFDictionaryRef>>>
keychain_items = QueryKeychainItemsForProfile(
config_.keychain_access_group, config_.metadata_secret,
created_not_before, created_not_after);
if (!keychain_items) {
DLOG(ERROR) << "Failed to query credentials in keychain";
return 0;
}
return 0;
return keychain_items->size();
}
API_AVAILABLE(macosx(10.12.2))
absl::optional<std::list<Credential>>
TouchIdCredentialStore::FindCredentialsImpl(
const std::string& rp_id,

@ -15,7 +15,7 @@ namespace device {
namespace fido {
namespace mac {
class API_AVAILABLE(macos(10.12.2)) FakeKeychain : public Keychain {
class FakeKeychain : public Keychain {
public:
struct Item {
Item();

@ -12,8 +12,7 @@ namespace device {
namespace fido {
namespace mac {
class API_AVAILABLE(macosx(10.12.2)) FakeTouchIdContext
: public TouchIdContext {
class FakeTouchIdContext : public TouchIdContext {
public:
FakeTouchIdContext(const FakeTouchIdContext&) = delete;
FakeTouchIdContext& operator=(const FakeTouchIdContext&) = delete;

@ -28,8 +28,7 @@ namespace mac {
//
// For documentation on the keychain item metadata, see
// |MakeCredentialOperation|.
class API_AVAILABLE(macosx(10.12.2))
COMPONENT_EXPORT(DEVICE_FIDO) GetAssertionOperation : public Operation {
class COMPONENT_EXPORT(DEVICE_FIDO) GetAssertionOperation : public Operation {
public:
using Callback = base::OnceCallback<void(
CtapDeviceResponseCode,

@ -36,7 +36,7 @@ CtapGetAssertionRequest MakeTestRequest() {
return CtapGetAssertionRequest(kRpId, test_data::kClientDataJson);
}
bool MakeCredential() API_AVAILABLE(macos(10.12.2)) {
bool MakeCredential() {
TestCallbackReceiver<CtapDeviceResponseCode,
absl::optional<AuthenticatorMakeCredentialResponse>>
callback_receiver;
@ -62,8 +62,7 @@ bool MakeCredential() API_AVAILABLE(macos(10.12.2)) {
// For demo purposes only. This test does a Touch ID user prompt. It will fail
// on incompatible hardware and crash if not code signed or lacking the
// keychain-access-group entitlement.
TEST(GetAssertionOperationTest, DISABLED_TestRun)
API_AVAILABLE(macos(10.12.2)) {
TEST(GetAssertionOperationTest, DISABLED_TestRun) {
base::test::TaskEnvironment task_environment;
ASSERT_TRUE(MakeCredential());

@ -25,7 +25,7 @@ namespace mac {
// keychain-access-group entitlements, and therefore requires code signing with
// a real Apple developer ID. We therefore group these function here, so they
// can be mocked out in testing.
class COMPONENT_EXPORT(DEVICE_FIDO) API_AVAILABLE(macos(10.12.2)) Keychain {
class COMPONENT_EXPORT(DEVICE_FIDO) Keychain {
public:
static Keychain& GetInstance();

@ -10,8 +10,7 @@ namespace device {
namespace fido {
namespace mac {
static API_AVAILABLE(macos(10.12.2)) Keychain* g_keychain_instance_override =
nullptr;
static Keychain* g_keychain_instance_override = nullptr;
// static
Keychain& Keychain::GetInstance() {

@ -45,8 +45,7 @@ namespace mac {
// (keychain_access_group_), so that they are logically
// separate from any other data that Chrome may store in the keychain in
// the future.
class API_AVAILABLE(macosx(10.12.2))
COMPONENT_EXPORT(DEVICE_FIDO) MakeCredentialOperation : public Operation {
class COMPONENT_EXPORT(DEVICE_FIDO) MakeCredentialOperation : public Operation {
public:
using Callback = base::OnceCallback<void(
CtapDeviceResponseCode,

@ -43,8 +43,7 @@ CtapMakeCredentialRequest MakeTestRequest() {
// For demo purposes only. This test does a Touch ID user prompt. It will fail
// on incompatible hardware and crash if not code signed or lacking the
// keychain-access-group entitlement.
TEST(MakeCredentialOperationTest, DISABLED_TestRun)
API_AVAILABLE(macosx(10.12.2)) {
TEST(MakeCredentialOperationTest, DISABLED_TestRun) {
base::test::TaskEnvironment task_environment;
TestCallbackReceiver<CtapDeviceResponseCode,
absl::optional<AuthenticatorMakeCredentialResponse>>

@ -27,8 +27,7 @@ class TouchIdContext;
// - allows faking TouchIdContext instances returned by TouchIdContext to stub
// out Touch ID fingerprint prompts.
// Overrides are reset when the instance is destroyed.
class COMPONENT_EXPORT(DEVICE_FIDO)
API_AVAILABLE(macosx(10.12.2)) ScopedTouchIdTestEnvironment {
class COMPONENT_EXPORT(DEVICE_FIDO) ScopedTouchIdTestEnvironment {
public:
ScopedTouchIdTestEnvironment();

@ -18,8 +18,7 @@ namespace device {
namespace fido {
namespace mac {
static API_AVAILABLE(macosx(10.12.2))
ScopedTouchIdTestEnvironment* g_current_environment = nullptr;
static ScopedTouchIdTestEnvironment* g_current_environment = nullptr;
ScopedTouchIdTestEnvironment::ScopedTouchIdTestEnvironment()
: keychain_(std::make_unique<FakeKeychain>()) {

@ -32,8 +32,7 @@ struct AuthenticatorConfig;
// cancel any other pending evaluations with an error. Deleting an instance
// will invalidate any pending evaluation prompts (i.e. the dialog will
// disappear and evaluation will fail with an error).
class COMPONENT_EXPORT(DEVICE_FIDO)
API_AVAILABLE(macosx(10.12.2)) TouchIdContext {
class COMPONENT_EXPORT(DEVICE_FIDO) TouchIdContext {
public:
// The callback is invoked when the local user authentication prompt
// completes. It receives a boolean indicating whether obtaining the

@ -29,7 +29,6 @@ namespace mac {
namespace {
API_AVAILABLE(macosx(10.12.2))
base::ScopedCFTypeRef<SecAccessControlRef> DefaultAccessControl() {
// The default access control policy used for WebAuthn credentials stored by
// the Touch ID platform authenticator.
@ -70,7 +69,6 @@ bool ExecutableHasKeychainAccessGroupEntitlement(
// Returns whether creating a key pair in the secure enclave succeeds. Keys are
// not persisted to the keychain.
API_AVAILABLE(macosx(10.12.2))
bool CanCreateSecureEnclaveKeyPairBlocking() {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);

@ -50,23 +50,20 @@ AuthenticatorData MakeAuthenticatorData(
absl::optional<std::vector<uint8_t>> GenerateSignature(
const AuthenticatorData& authenticator_data,
base::span<const uint8_t, kClientDataHashLength> client_data_hash,
SecKeyRef private_key) API_AVAILABLE(macosx(10.12.2));
SecKeyRef private_key);
// SecKeyRefToECPublicKey converts a SecKeyRef for a public key into an
// equivalent |PublicKey| instance. It returns |nullptr| if the key cannot
// be converted.
std::unique_ptr<PublicKey> SecKeyRefToECPublicKey(SecKeyRef public_key_ref)
API_AVAILABLE(macosx(10.12.2));
std::unique_ptr<PublicKey> SecKeyRefToECPublicKey(SecKeyRef public_key_ref);
enum class CodeSigningState {
kSigned,
kNotSigned,
kUnknown,
};
// ProcessIsSigned returns `kSigned` if the current process has been code
// signed, `kNotSigned` if not, or `kUnknown` if the signing status cannot be
// determined. (The latter will always happen on macOS < 10.12.)
// ProcessIsSigned returns whether the current process has been code
// signed.
CodeSigningState ProcessIsSigned();
} // namespace mac

@ -102,7 +102,7 @@ AuthenticatorData MakeAuthenticatorData(
absl::optional<std::vector<uint8_t>> GenerateSignature(
const AuthenticatorData& authenticator_data,
base::span<const uint8_t, kClientDataHashLength> client_data_hash,
SecKeyRef private_key) API_AVAILABLE(macosx(10.12.2)) {
SecKeyRef private_key) {
const std::vector<uint8_t> serialized_authenticator_data =
authenticator_data.SerializeToByteArray();
size_t capacity =
@ -130,8 +130,7 @@ absl::optional<std::vector<uint8_t>> GenerateSignature(
// SecKeyRefToECPublicKey converts a SecKeyRef for a public key into an
// equivalent |PublicKey| instance. It returns |nullptr| if the key cannot
// be converted.
std::unique_ptr<PublicKey> SecKeyRefToECPublicKey(SecKeyRef public_key_ref)
API_AVAILABLE(macosx(10.12.2)) {
std::unique_ptr<PublicKey> SecKeyRefToECPublicKey(SecKeyRef public_key_ref) {
CHECK(public_key_ref);
ScopedCFTypeRef<CFErrorRef> err;
ScopedCFTypeRef<CFDataRef> data_ref(
@ -153,22 +152,9 @@ std::unique_ptr<PublicKey> SecKeyRefToECPublicKey(SecKeyRef public_key_ref)
}
CodeSigningState ProcessIsSigned() {
// SecTaskCopySigningIdentifier is not decorated with availability attributes
// in the header, but it was only introduced in 10.12. For prior versions,
// `nullopt` is returned to indicate that the signing status of the process
// is unknown.
//
// `@available` cannot be negated, so the code is a little awkward around
// that.
base::ScopedCFTypeRef<SecTaskRef> task;
if (@available(macOS 10.12, *)) {
task.reset(SecTaskCreateFromSelf(nullptr));
if (!task) {
return CodeSigningState::kNotSigned;
}
} else {
return CodeSigningState::kUnknown;
base::ScopedCFTypeRef<SecTaskRef> task(SecTaskCreateFromSelf(nullptr));
if (!task) {
return CodeSigningState::kNotSigned;
}
base::ScopedCFTypeRef<CFStringRef> sign_id(