summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanny Lin <danny@kdrag0n.dev>2021-10-11 20:00:44 -0700
committeralk3pInjection <webmaster@raspii.tech>2023-08-08 02:08:48 +0800
commitc6f3d568baaea91b9df56b38b9b2b64d9af75851 (patch)
tree6c9cb6dbdc2dd510f108848bcb7f6eb146bc96e2
parent555e3a9a903d0f841617e649338b948ca6991d78 (diff)
keystore: Block key attestation for SafetyNet
SafetyNet (part of Google Play Services) opportunistically uses hardware-backed key attestation via KeyStore as a strong integrity check. This causes SafetyNet to fail on custom ROMs because the verified boot key and bootloader unlock state can be detected from attestation certificates. As a workaround, we can take advantage of the fact that SafetyNet's usage of key attestation is opportunistic (i.e. falls back to basic integrity checks if it fails) and prevent it from getting the attestation certificate chain from KeyStore. This is done by checking the stack for DroidGuard, which is the codename for SafetyNet, and pretending that the device doesn't support key attestation. Key attestation has only been blocked for SafetyNet specifically, as Google Play Services and other apps have many valid reasons to use it. For example, it appears to be involved in Google's mobile security key ferature. Change-Id: I5146439d47f42dc6231cb45c4dab9f61540056f6
-rw-r--r--core/java/com/android/internal/gmscompat/AttestationHooks.java16
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java3
2 files changed, 19 insertions, 0 deletions
diff --git a/core/java/com/android/internal/gmscompat/AttestationHooks.java b/core/java/com/android/internal/gmscompat/AttestationHooks.java
index 4c7335236cd6..64e29fd3a826 100644
--- a/core/java/com/android/internal/gmscompat/AttestationHooks.java
+++ b/core/java/com/android/internal/gmscompat/AttestationHooks.java
@@ -21,6 +21,7 @@ import android.os.Build;
import android.util.Log;
import java.lang.reflect.Field;
+import java.util.Arrays;
/** @hide */
public final class AttestationHooks {
@@ -29,6 +30,8 @@ public final class AttestationHooks {
private static final String PACKAGE_GMS = "com.google.android.gms";
private static final String PROCESS_UNSTABLE = "com.google.android.gms.unstable";
+ private static volatile boolean sIsGms = false;
+
private AttestationHooks() { }
private static void setBuildField(String key, Object value) {
@@ -52,10 +55,23 @@ public final class AttestationHooks {
String processName = Application.getProcessName();
if (PACKAGE_GMS.equals(packageName) && PROCESS_UNSTABLE.equals(processName)) {
+ sIsGms = true;
setBuildField("DEVICE", "redfin");
setBuildField("PRODUCT", "redfin");
setBuildField("MODEL", "Pixel 5");
setBuildField("FINGERPRINT", "google/redfin/redfin:13/TQ3A.230605.011/10161073:user/release-keys");
}
}
+
+ private static boolean isCallerSafetyNet() {
+ return Arrays.stream(Thread.currentThread().getStackTrace())
+ .anyMatch(elem -> elem.getClassName().contains("DroidGuard"));
+ }
+
+ public static void onEngineGetCertificateChain() {
+ // Check stack for SafetyNet
+ if (sIsGms && isCallerSafetyNet()) {
+ throw new UnsupportedOperationException();
+ }
+ }
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
index 33411e1ec5b9..133a4094d434 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -42,6 +42,7 @@ import android.system.keystore2.ResponseCode;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.gmscompat.AttestationHooks;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -164,6 +165,8 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
@Override
public Certificate[] engineGetCertificateChain(String alias) {
+ AttestationHooks.onEngineGetCertificateChain();
+
KeyEntryResponse response = getKeyMetadata(alias);
if (response == null || response.metadata.certificate == null) {