From 15633a3d29bf727b83083f2c49d906c16527d389 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Wed, 13 Jan 2021 02:05:05 -0800 Subject: [PATCH] keystore: Block key attestation for Google Play Services In order to enforce SafetyNet security, Google Play Services is now using hardware attestation for ctsProfile validation in all cases, even when basic attestation is selected. The SafetyNet API response from GMS will report that basic attestation was used, but under the hood, hardware attestation is always used regardless of the reported state. This results in SafetyNet failing to pass due to TrustZone reporting an unlocked bootloader (and a partially invalidated root of trust) in the key attestation result. We can still take advantage of the fact that this usage of hardware attestation is opportunistic - that is, it falls back to basic attestation if key attestation fails to run - and prevent GMS from using key attestation at the framework level. This causes it to gracefully fall back to basic attestation and pass SafetyNet with an unlocked bootloader. Key attestation is still available for other apps, as there are valid uses for it that do not involve SafetyNet. The "not implemented" error code from keymaster is used to simulate the most realistic failure condition to evade detection, i.e. an old device that lacks support for key attestation. Change-Id: Iba5fe0791622839e1bad4730593a319ea03661f2 --- keystore/key_store_service.cpp | 11 ++++++++--- keystore/keystore_attestation_id.cpp | 6 ++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp index 1b38643..b1f1304 100644 --- a/keystore/key_store_service.cpp +++ b/keystore/key_store_service.cpp @@ -49,6 +49,7 @@ #include #include +#include namespace keystore { @@ -120,9 +121,13 @@ KeyStoreServiceReturnCode updateParamsForAttestation(uid_t callingUid, Authoriza auto asn1_attestation_id_result = security::gather_attestation_application_id(callingUid); if (!asn1_attestation_id_result.isOk()) { - ALOGE("failed to gather attestation_id"); - // Couldn't get attestation ID; just use an empty one rather than failing. - asn1_attestation_id_result = std::vector(); + if (asn1_attestation_id_result.status() == KM_ERROR_UNIMPLEMENTED) { + return KeyStoreServiceReturnCode(KM_ERROR_UNIMPLEMENTED); + } else { + ALOGE("failed to gather attestation_id"); + // Couldn't get attestation ID; just use an empty one rather than failing. + asn1_attestation_id_result = std::vector(); + } } std::vector& asn1_attestation_id = asn1_attestation_id_result; diff --git a/keystore/keystore_attestation_id.cpp b/keystore/keystore_attestation_id.cpp index 3d9e87e..448a909 100644 --- a/keystore/keystore_attestation_id.cpp +++ b/keystore/keystore_attestation_id.cpp @@ -35,6 +35,8 @@ #include #include +#include + #include /* for AID_SYSTEM */ #include @@ -210,6 +212,10 @@ build_attestation_application_id(const KeyAttestationApplicationId& key_attestat return BAD_VALUE; } std::string package_name(String8(*pinfo->package_name()).string()); + // Prevent Google Play Services from using key attestation for SafetyNet + if (package_name == "com.google.android.gms") { + return KM_ERROR_UNIMPLEMENTED; + } std::unique_ptr attestation_package_info; auto rc = build_attestation_package_info(*pinfo, &attestation_package_info); if (rc != NO_ERROR) { -- 2.29.2