139 lines
5.1 KiB
Diff
139 lines
5.1 KiB
Diff
|
From 3db46053ca0547c175fa591075a67b8d76c4b906 Mon Sep 17 00:00:00 2001
|
||
|
From: Danny Lin <danny@kdrag0n.dev>
|
||
|
Date: Mon, 11 Oct 2021 19:59:51 -0700
|
||
|
Subject: [PATCH] Alter model name to avoid SafetyNet HW attestation
|
||
|
enforcement
|
||
|
|
||
|
As of September 2, Google is enforcing SafetyNet's previously
|
||
|
opportunistic hardware-backed attestation based on device information.
|
||
|
Append a space to the device model name in order to avoid such
|
||
|
enforcement.
|
||
|
|
||
|
Also contains:
|
||
|
Spoof build fingerprint for Google Play Services
|
||
|
|
||
|
SafetyNet's CTS profile attestation checks whether Build.FINGERPRINT
|
||
|
matches that of the device's stock OS, which has passed CTS testing.
|
||
|
Spoof the fingerprint for Google Play Services to help pass SafetyNet.
|
||
|
|
||
|
We used to set the real system build fingerprint to the stock one, but
|
||
|
Android relies on each build having a unique fingerprint in order to
|
||
|
clear the correct caches and update persistent state for system changes.
|
||
|
On devices that no longer receive updates from the OEM, the build
|
||
|
fingerprint never changes and Android doesn't account for updates
|
||
|
correctly, which causes issues when updating without wiping data.
|
||
|
Only spoofing the fingerprint for Google Play Services fixes this issue.
|
||
|
|
||
|
Corresponding vendor commit:
|
||
|
"Only use stock build fingerprint for Google Play Services"
|
||
|
|
||
|
NB: This code is under the gmscompat package, but it does not depend on
|
||
|
any code from gmscompat.
|
||
|
|
||
|
Change-Id: I26a2498eb2e2163933303b03f6d516e5fb30fe51
|
||
|
|
||
|
* We don't need to spoof the fingerprint here since we do it globally, but we
|
||
|
use the Build field spoofing code it added for model
|
||
|
|
||
|
Change-Id: Ib7779e0aae40cab3730a56785e9231896917ab0a
|
||
|
---
|
||
|
core/java/android/app/Instrumentation.java | 4 ++
|
||
|
.../internal/gmscompat/AttestationHooks.java | 59 +++++++++++++++++++
|
||
|
2 files changed, 63 insertions(+)
|
||
|
create mode 100644 core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||
|
|
||
|
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
|
||
|
index 8984c4292023..58258acaef97 100644
|
||
|
--- a/core/java/android/app/Instrumentation.java
|
||
|
+++ b/core/java/android/app/Instrumentation.java
|
||
|
@@ -57,6 +57,8 @@
|
||
|
|
||
|
import com.android.internal.content.ReferrerIntent;
|
||
|
|
||
|
+import com.android.internal.gmscompat.AttestationHooks;
|
||
|
+
|
||
|
import java.io.File;
|
||
|
import java.lang.annotation.Retention;
|
||
|
import java.lang.annotation.RetentionPolicy;
|
||
|
@@ -1231,6 +1233,7 @@ public Application newApplication(ClassLoader cl, String className, Context cont
|
||
|
Application app = getFactory(context.getPackageName())
|
||
|
.instantiateApplication(cl, className);
|
||
|
app.attach(context);
|
||
|
+ AttestationHooks.initApplicationBeforeOnCreate(app);
|
||
|
return app;
|
||
|
}
|
||
|
|
||
|
@@ -1248,6 +1251,7 @@ static public Application newApplication(Class<?> clazz, Context context)
|
||
|
ClassNotFoundException {
|
||
|
Application app = (Application)clazz.newInstance();
|
||
|
app.attach(context);
|
||
|
+ AttestationHooks.initApplicationBeforeOnCreate(app);
|
||
|
return app;
|
||
|
}
|
||
|
|
||
|
diff --git a/core/java/com/android/internal/gmscompat/AttestationHooks.java b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||
|
new file mode 100644
|
||
|
index 000000000000..621156eb84b9
|
||
|
--- /dev/null
|
||
|
+++ b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||
|
@@ -0,0 +1,59 @@
|
||
|
+/*
|
||
|
+ * Copyright (C) 2021 The Android Open Source Project
|
||
|
+ *
|
||
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
+ * you may not use this file except in compliance with the License.
|
||
|
+ * You may obtain a copy of the License at
|
||
|
+ *
|
||
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
||
|
+ *
|
||
|
+ * Unless required by applicable law or agreed to in writing, software
|
||
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
+ * See the License for the specific language governing permissions and
|
||
|
+ * limitations under the License.
|
||
|
+ */
|
||
|
+
|
||
|
+package com.android.internal.gmscompat;
|
||
|
+
|
||
|
+import android.app.Application;
|
||
|
+import android.os.Build;
|
||
|
+import android.os.SystemProperties;
|
||
|
+import android.util.Log;
|
||
|
+
|
||
|
+import java.lang.reflect.Field;
|
||
|
+
|
||
|
+/** @hide */
|
||
|
+public final class AttestationHooks {
|
||
|
+ private static final String TAG = "GmsCompat/Attestation";
|
||
|
+ private static final String PACKAGE_GMS = "com.google.android.gms";
|
||
|
+
|
||
|
+ private AttestationHooks() { }
|
||
|
+
|
||
|
+ private static void setBuildField(String key, String value) {
|
||
|
+ try {
|
||
|
+ // Unlock
|
||
|
+ Field field = Build.class.getDeclaredField(key);
|
||
|
+ field.setAccessible(true);
|
||
|
+
|
||
|
+ // Edit
|
||
|
+ field.set(null, value);
|
||
|
+
|
||
|
+ // Lock
|
||
|
+ field.setAccessible(false);
|
||
|
+ } catch (NoSuchFieldException | IllegalAccessException e) {
|
||
|
+ Log.e(TAG, "Failed to spoof Build." + key, e);
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ private static void spoofBuildGms() {
|
||
|
+ // Alter model name to avoid hardware attestation enforcement
|
||
|
+ setBuildField("MODEL", Build.MODEL + " ");
|
||
|
+ }
|
||
|
+
|
||
|
+ public static void initApplicationBeforeOnCreate(Application app) {
|
||
|
+ if (PACKAGE_GMS.equals(app.getPackageName())) {
|
||
|
+ spoofBuildGms();
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|