build/snet20-3.patch

92 lines
3.7 KiB
Diff
Raw Normal View History

2022-12-25 20:51:09 +01:00
From ae57183500bb34032ec426fcae2b9a14e028ce12 Mon Sep 17 00:00:00 2001
From: Danny Lin <danny@kdrag0n.dev>
Date: Mon, 11 Oct 2021 20:00:44 -0700
2023-05-28 08:47:33 +02:00
Subject: [PATCH] XXXHIDEXXX keystore: Block key attestation for SafetyNet
2022-12-25 20:51:09 +01:00
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
---
.../internal/gmscompat/AttestationHooks.java | 16 ++++++++++++++++
.../security/keystore2/AndroidKeyStoreSpi.java | 3 +++
2 files changed, 19 insertions(+)
diff --git a/core/java/com/android/internal/gmscompat/AttestationHooks.java b/core/java/com/android/internal/gmscompat/AttestationHooks.java
index 621156eb84b9..fe12dfe02a9f 100644
--- a/core/java/com/android/internal/gmscompat/AttestationHooks.java
+++ b/core/java/com/android/internal/gmscompat/AttestationHooks.java
@@ -22,12 +22,15 @@
import android.util.Log;
import java.lang.reflect.Field;
+import java.util.Arrays;
/** @hide */
public final class AttestationHooks {
private static final String TAG = "GmsCompat/Attestation";
private static final String PACKAGE_GMS = "com.google.android.gms";
+ private static volatile boolean sIsGms = false;
+
private AttestationHooks() { }
private static void setBuildField(String key, String value) {
@@ -53,7 +56,20 @@ private static void spoofBuildGms() {
public static void initApplicationBeforeOnCreate(Application app) {
if (PACKAGE_GMS.equals(app.getPackageName())) {
+ sIsGms = true;
spoofBuildGms();
}
}
+
+ 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.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 @@ private KeyEntryResponse getKeyMetadata(String alias) {
@Override
public Certificate[] engineGetCertificateChain(String alias) {
+ AttestationHooks.onEngineGetCertificateChain();
+
KeyEntryResponse response = getKeyMetadata(alias);
if (response == null || response.metadata.certificate == null) {