readded the original files, builds break without it
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
From 09662a87b7db9b520aa5f996c5b837717fadfdec Mon Sep 17 00:00:00 2001
|
||||
From: Andy CrossGate Yan <GeForce8800Ultra@gmail.com>
|
||||
Date: Sun, 10 Jan 2021 11:44:29 +0000
|
||||
Subject: [PATCH 05/22] UI: Disable wallpaper zoom
|
||||
|
||||
It does little more than inducing motion sickness
|
||||
|
||||
Change-Id: I78cc5484930b27f172cd8d8a5bd9042dce3478d0
|
||||
---
|
||||
core/res/res/values/config.xml | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
|
||||
index f015b485dfa6..77045ea11775 100644
|
||||
--- a/core/res/res/values/config.xml
|
||||
+++ b/core/res/res/values/config.xml
|
||||
@@ -5206,7 +5206,7 @@
|
||||
<item name="config_wallpaperMinScale" format="float" type="dimen">1</item>
|
||||
|
||||
<!-- The max scale for the wallpaper when it's zoomed in -->
|
||||
- <item name="config_wallpaperMaxScale" format="float" type="dimen">1.10</item>
|
||||
+ <item name="config_wallpaperMaxScale" format="float" type="dimen">1</item>
|
||||
|
||||
<!-- If true, the wallpaper will scale regardless of the value of shouldZoomOutWallpaper() -->
|
||||
<bool name="config_alwaysScaleWallpaper">false</bool>
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
From 2249465d16cea6251df69dd13d331ed2fae270f0 Mon Sep 17 00:00:00 2001
|
||||
From: Andy CrossGate Yan <GeForce8800Ultra@gmail.com>
|
||||
Date: Wed, 3 Jun 2020 01:31:34 +0000
|
||||
Subject: [PATCH 07/22] UI: Increase default status bar height
|
||||
|
||||
Change-Id: Ibbcf63159e19bb2bb2b1094ea07ab85917630b07
|
||||
---
|
||||
core/res/res/values/dimens.xml | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
|
||||
index 2542268a153a..099a6badc034 100644
|
||||
--- a/core/res/res/values/dimens.xml
|
||||
+++ b/core/res/res/values/dimens.xml
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
<!-- The default height of the status bar used in {@link SystemBarUtils#getStatusBarHeight} to
|
||||
calculate the status bar height. -->
|
||||
- <dimen name="status_bar_height_default">24dp</dimen>
|
||||
+ <dimen name="status_bar_height_default">28dp</dimen>
|
||||
<!-- Height of the status bar.
|
||||
Do not read this dimen directly. Use {@link SystemBarUtils#getStatusBarHeight} instead.
|
||||
-->
|
||||
@@ -49,7 +49,7 @@
|
||||
<!-- Height of the status bar in portrait.
|
||||
Do not read this dimen directly. Use {@link SystemBarUtils#getStatusBarHeight} instead.
|
||||
-->
|
||||
- <dimen name="status_bar_height_portrait">24dp</dimen>
|
||||
+ <dimen name="status_bar_height_portrait">28dp</dimen>
|
||||
<!-- Height of the status bar in landscape.
|
||||
Do not read this dimen directly. Use {@link SystemBarUtils#getStatusBarHeight} instead.
|
||||
-->
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
From 380d8dff252dcde3b490cc3080bd56d2e3d21ec4 Mon Sep 17 00:00:00 2001
|
||||
From: Andy CrossGate Yan <GeForce8800Ultra@gmail.com>
|
||||
Date: Sun, 25 Sep 2022 02:20:20 +0000
|
||||
Subject: [PATCH 08/22] UI: Remove QS footer background
|
||||
|
||||
Change-Id: I68e82e0c5e3eddb2d3f767fe792b1436eae506ef
|
||||
---
|
||||
packages/SystemUI/res-keyguard/layout/footer_actions.xml | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/packages/SystemUI/res-keyguard/layout/footer_actions.xml b/packages/SystemUI/res-keyguard/layout/footer_actions.xml
|
||||
index 544d0299060d..d45744961f59 100644
|
||||
--- a/packages/SystemUI/res-keyguard/layout/footer_actions.xml
|
||||
+++ b/packages/SystemUI/res-keyguard/layout/footer_actions.xml
|
||||
@@ -23,7 +23,6 @@
|
||||
android:elevation="@dimen/qs_panel_elevation"
|
||||
android:paddingTop="@dimen/qs_footer_actions_top_padding"
|
||||
android:paddingBottom="@dimen/qs_footer_actions_bottom_padding"
|
||||
- android:background="@drawable/qs_footer_actions_background"
|
||||
android:gravity="center_vertical|end"
|
||||
android:layout_gravity="bottom"
|
||||
/>
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
From 8b17b1dc3b1f373a0ae8a44d16a8adec599915b3 Mon Sep 17 00:00:00 2001
|
||||
From: Danny Lin <danny@kdrag0n.dev>
|
||||
Date: Tue, 5 Oct 2021 21:01:50 -0700
|
||||
Subject: [PATCH 13/22] Paint: Enable subpixel text positioning by default
|
||||
|
||||
On desktop Linux, subpixel text positioning is necessary to avoid
|
||||
kerning issues, and Android is no different. Even though most phone
|
||||
displays have relatively high DPIs, the lack of subpixel text
|
||||
positioning is only unnoticeable on high-end devices such as the Pixel 4
|
||||
XL (1440x3040 @ 6.3 in => 537 dpi).
|
||||
|
||||
For example, on the Pixel 5 (1080 x 2340 @ 6.0 in => 432 dpi),
|
||||
horizontally-scrolling labels in QS tiles can be seen "jittering"
|
||||
slightly upon close observation. This was tested with the Google Sans
|
||||
font on Google's stock OS. At this lower DPI, there is still a need for
|
||||
subpixel text positioning (at least in some cases).
|
||||
|
||||
Enable subpixel text positioning by default to fix occasional kerning
|
||||
issues and jittering when text is in motion.
|
||||
|
||||
Change-Id: I8d71e5848a745c5a2d457a28c68458920928ee09
|
||||
---
|
||||
graphics/java/android/graphics/Paint.java | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
|
||||
index f438a03b1434..6621d1f23166 100644
|
||||
--- a/graphics/java/android/graphics/Paint.java
|
||||
+++ b/graphics/java/android/graphics/Paint.java
|
||||
@@ -260,7 +260,7 @@ public class Paint {
|
||||
|
||||
// These flags are always set on a new/reset paint, even if flags 0 is passed.
|
||||
static final int HIDDEN_DEFAULT_PAINT_FLAGS = DEV_KERN_TEXT_FLAG | EMBEDDED_BITMAP_TEXT_FLAG
|
||||
- | FILTER_BITMAP_FLAG;
|
||||
+ | FILTER_BITMAP_FLAG | SUBPIXEL_TEXT_FLAG;
|
||||
|
||||
/**
|
||||
* Font hinter option that disables font hinting.
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
From 482d15491c36aeb11a0e8b5c9a5205d389507034 Mon Sep 17 00:00:00 2001
|
||||
From: Danny Lin <danny@kdrag0n.dev>
|
||||
Date: Sat, 16 Oct 2021 05:27:57 -0700
|
||||
Subject: [PATCH 14/22] Add support for app signature spoofing
|
||||
|
||||
This is needed by microG GmsCore to pretend to be the official Google
|
||||
Play Services package, because client apps check the package signature
|
||||
to make sure it matches Google's official certificate.
|
||||
|
||||
This was forward-ported from the Android 10 patch by gudenau:
|
||||
https://github.com/microg/android_packages_apps_GmsCore/pull/957
|
||||
|
||||
Changes made for Android 11:
|
||||
- Updated PackageInfo calls
|
||||
- Added new permission to public API surface, needed for
|
||||
PermissionController which is now an updatable APEX on 11
|
||||
- Added a dummy permission group to allow users to manage the
|
||||
permission through the PermissionController UI
|
||||
(by Vachounet <vachounet@live.fr>)
|
||||
- Updated location provider comment for conciseness
|
||||
|
||||
Changes made for Android 12:
|
||||
- Moved mayFakeSignature into lock-free Computer subclass
|
||||
- Always get permissions for packages that request signature spoofing
|
||||
(otherwise permissions are usually ommitted and thus the permission
|
||||
check doesn't work properly)
|
||||
- Optimize mayFakeSignature check order to improve performance
|
||||
|
||||
Changes made for Android 13:
|
||||
- Computer subclass is now an independent class.
|
||||
|
||||
Change-Id: Ied7d6ce0b83a2d2345c3abba0429998d86494a88
|
||||
---
|
||||
core/api/current.txt | 2 ++
|
||||
core/res/AndroidManifest.xml | 15 ++++++++++
|
||||
core/res/res/values/strings.xml | 12 ++++++++
|
||||
.../com/android/server/pm/ComputerEngine.java | 30 +++++++++++++++++--
|
||||
4 files changed, 56 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/core/api/current.txt b/core/api/current.txt
|
||||
index 487e57d114c9..04e69741b9fd 100644
|
||||
--- a/core/api/current.txt
|
||||
+++ b/core/api/current.txt
|
||||
@@ -87,6 +87,7 @@ package android {
|
||||
field public static final String DUMP = "android.permission.DUMP";
|
||||
field public static final String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR";
|
||||
field public static final String FACTORY_TEST = "android.permission.FACTORY_TEST";
|
||||
+ field public static final String FAKE_PACKAGE_SIGNATURE = "android.permission.FAKE_PACKAGE_SIGNATURE";
|
||||
field public static final String FOREGROUND_SERVICE = "android.permission.FOREGROUND_SERVICE";
|
||||
field public static final String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
|
||||
field public static final String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED";
|
||||
@@ -222,6 +223,7 @@ package android {
|
||||
field public static final String CALL_LOG = "android.permission-group.CALL_LOG";
|
||||
field public static final String CAMERA = "android.permission-group.CAMERA";
|
||||
field public static final String CONTACTS = "android.permission-group.CONTACTS";
|
||||
+ field public static final String FAKE_PACKAGE = "android.permission-group.FAKE_PACKAGE";
|
||||
field public static final String LOCATION = "android.permission-group.LOCATION";
|
||||
field public static final String MICROPHONE = "android.permission-group.MICROPHONE";
|
||||
field public static final String NEARBY_DEVICES = "android.permission-group.NEARBY_DEVICES";
|
||||
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
|
||||
index bbc3a7369423..af04d9d18fbd 100644
|
||||
--- a/core/res/AndroidManifest.xml
|
||||
+++ b/core/res/AndroidManifest.xml
|
||||
@@ -3577,6 +3577,21 @@
|
||||
android:description="@string/permdesc_getPackageSize"
|
||||
android:protectionLevel="normal" />
|
||||
|
||||
+ <!-- Dummy user-facing group for faking package signature -->
|
||||
+ <permission-group android:name="android.permission-group.FAKE_PACKAGE"
|
||||
+ android:label="@string/permgrouplab_fake_package_signature"
|
||||
+ android:description="@string/permgroupdesc_fake_package_signature"
|
||||
+ android:request="@string/permgrouprequest_fake_package_signature"
|
||||
+ android:priority="100" />
|
||||
+
|
||||
+ <!-- Allows an application to change the package signature as
|
||||
+ seen by applications -->
|
||||
+ <permission android:name="android.permission.FAKE_PACKAGE_SIGNATURE"
|
||||
+ android:permissionGroup="android.permission-group.UNDEFINED"
|
||||
+ android:protectionLevel="signature|privileged"
|
||||
+ android:label="@string/permlab_fakePackageSignature"
|
||||
+ android:description="@string/permdesc_fakePackageSignature" />
|
||||
+
|
||||
<!-- @deprecated No longer useful, see
|
||||
{@link android.content.pm.PackageManager#addPackageToPreferred}
|
||||
for details. -->
|
||||
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
|
||||
index 2091c0502b6f..6888edcf7d3c 100644
|
||||
--- a/core/res/res/values/strings.xml
|
||||
+++ b/core/res/res/values/strings.xml
|
||||
@@ -982,6 +982,18 @@
|
||||
|
||||
<!-- Permissions -->
|
||||
|
||||
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
+ <string name="permlab_fakePackageSignature">Spoof package signature</string>
|
||||
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
+ <string name="permdesc_fakePackageSignature">Allows the app to pretend to be a different app. Malicious applications might be able to use this to access private application data. Legitimate uses include an emulator pretending to be what it emulates. Grant this permission with caution only!</string>
|
||||
+ <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
+ <string name="permgrouplab_fake_package_signature">Spoof package signature</string>
|
||||
+ <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
+ <string name="permgroupdesc_fake_package_signature">allow to spoof package signature</string>
|
||||
+ <!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
|
||||
+ <string name="permgrouprequest_fake_package_signature">Allow
|
||||
+ <b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g></b> to spoof package signature?</string>
|
||||
+
|
||||
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
<string name="permlab_statusBar">disable or modify status bar</string>
|
||||
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
|
||||
index 46b7460dff1b..40549962436f 100644
|
||||
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
|
||||
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
|
||||
@@ -1603,6 +1603,29 @@ public class ComputerEngine implements Computer {
|
||||
return result;
|
||||
}
|
||||
|
||||
+ private boolean requestsFakeSignature(AndroidPackage p) {
|
||||
+ return p.getMetaData() != null &&
|
||||
+ p.getMetaData().getString("fake-signature") != null;
|
||||
+ }
|
||||
+
|
||||
+ private PackageInfo mayFakeSignature(AndroidPackage p, PackageInfo pi,
|
||||
+ Set<String> permissions) {
|
||||
+ try {
|
||||
+ if (p.getMetaData() != null &&
|
||||
+ p.getTargetSdkVersion() > Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||
+ String sig = p.getMetaData().getString("fake-signature");
|
||||
+ if (sig != null &&
|
||||
+ permissions.contains("android.permission.FAKE_PACKAGE_SIGNATURE")) {
|
||||
+ pi.signatures = new Signature[] {new Signature(sig)};
|
||||
+ }
|
||||
+ }
|
||||
+ } catch (Throwable t) {
|
||||
+ // We should never die because of any failures, this is system code!
|
||||
+ Log.w("PackageManagerService.FAKE_PACKAGE_SIGNATURE", t);
|
||||
+ }
|
||||
+ return pi;
|
||||
+ }
|
||||
+
|
||||
public final PackageInfo generatePackageInfo(PackageStateInternal ps,
|
||||
@PackageManager.PackageInfoFlagsBits long flags, int userId) {
|
||||
if (!mUserManager.exists(userId)) return null;
|
||||
@@ -1632,13 +1655,14 @@ public class ComputerEngine implements Computer {
|
||||
final int[] gids = (flags & PackageManager.GET_GIDS) == 0 ? EMPTY_INT_ARRAY
|
||||
: mPermissionManager.getGidsForUid(UserHandle.getUid(userId, ps.getAppId()));
|
||||
// Compute granted permissions only if package has requested permissions
|
||||
- final Set<String> permissions = ((flags & PackageManager.GET_PERMISSIONS) == 0
|
||||
+ final Set<String> permissions = (((flags & PackageManager.GET_PERMISSIONS) == 0
|
||||
+ && !requestsFakeSignature(p))
|
||||
|| ArrayUtils.isEmpty(p.getRequestedPermissions())) ? Collections.emptySet()
|
||||
: mPermissionManager.getGrantedPermissions(ps.getPackageName(), userId);
|
||||
|
||||
- PackageInfo packageInfo = PackageInfoUtils.generate(p, gids, flags,
|
||||
+ PackageInfo packageInfo = mayFakeSignature(p, PackageInfoUtils.generate(p, gids, flags,
|
||||
state.getFirstInstallTime(), ps.getLastUpdateTime(), permissions, state, userId,
|
||||
- ps);
|
||||
+ ps), permissions);
|
||||
|
||||
if (packageInfo == null) {
|
||||
return null;
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
From db27d27f48658841c6a74e55f543f417ddb16e76 Mon Sep 17 00:00:00 2001
|
||||
From: Danny Lin <danny@kdrag0n.dev>
|
||||
Date: Mon, 11 Oct 2021 19:59:51 -0700
|
||||
Subject: [PATCH 15/22] Spoof product name for Google Play Services
|
||||
|
||||
NB: This code is under the gmscompat package, but it does not depend on
|
||||
any code from gmscompat.
|
||||
|
||||
Change-Id: Ic018c0d7abe4573143c3b92301a2625b91e6673a
|
||||
---
|
||||
core/java/android/app/Instrumentation.java | 4 ++
|
||||
.../internal/gmscompat/AttestationHooks.java | 60 +++++++++++++++++++
|
||||
2 files changed, 64 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 556058b567f9..44449588bbab 100644
|
||||
--- a/core/java/android/app/Instrumentation.java
|
||||
+++ b/core/java/android/app/Instrumentation.java
|
||||
@@ -57,6 +57,8 @@ import android.view.WindowManagerGlobal;
|
||||
|
||||
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;
|
||||
@@ -1242,6 +1244,7 @@ public class Instrumentation {
|
||||
Application app = getFactory(context.getPackageName())
|
||||
.instantiateApplication(cl, className);
|
||||
app.attach(context);
|
||||
+ AttestationHooks.initApplicationBeforeOnCreate(app);
|
||||
return app;
|
||||
}
|
||||
|
||||
@@ -1259,6 +1262,7 @@ public class Instrumentation {
|
||||
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..55db97dc28a1
|
||||
--- /dev/null
|
||||
+++ b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
@@ -0,0 +1,60 @@
|
||||
+/*
|
||||
+ * 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", "Pixel 5a");
|
||||
+ }
|
||||
+
|
||||
+ public static void initApplicationBeforeOnCreate(Application app) {
|
||||
+ if (PACKAGE_GMS.equals(app.getPackageName())) {
|
||||
+ spoofBuildGms();
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
From dc4bd0f140c6946e01e0a3c31bfc71c884138981 Mon Sep 17 00:00:00 2001
|
||||
From: Danny Lin <danny@kdrag0n.dev>
|
||||
Date: Mon, 11 Oct 2021 20:00:44 -0700
|
||||
Subject: [PATCH 16/22] 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
|
||||
---
|
||||
.../internal/gmscompat/AttestationHooks.java | 15 +++++++++++++++
|
||||
.../security/keystore2/AndroidKeyStoreSpi.java | 3 +++
|
||||
2 files changed, 18 insertions(+)
|
||||
|
||||
diff --git a/core/java/com/android/internal/gmscompat/AttestationHooks.java b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
index 55db97dc28a1..f2c85c82821f 100644
|
||||
--- a/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
+++ b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
@@ -22,12 +22,14 @@ import android.os.SystemProperties;
|
||||
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() { }
|
||||
|
||||
@@ -54,7 +56,20 @@ public final class AttestationHooks {
|
||||
|
||||
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.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) {
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
From 05bc5fa10b4e2ebc539c32db04abbc995906ff05 Mon Sep 17 00:00:00 2001
|
||||
From: Danny Lin <danny@kdrag0n.dev>
|
||||
Date: Mon, 1 Nov 2021 20:06:48 -0700
|
||||
Subject: [PATCH 17/22] Limit SafetyNet workarounds to unstable GMS process
|
||||
|
||||
The unstable process is where SafetyNet attestation actually runs, so
|
||||
we only need to spoof the model in that process. Leaving other processes
|
||||
fixes various issues caused by model detection and flag provisioning,
|
||||
including screen-off Voice Match in Google Assistant, broken At a Glance
|
||||
weather and settings on Android 12, and more.
|
||||
|
||||
Change-Id: Idcf663907a6c3d0408dbd45b1ac53c9eb4200df8
|
||||
---
|
||||
.../com/android/internal/gmscompat/AttestationHooks.java | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/core/java/com/android/internal/gmscompat/AttestationHooks.java b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
index f2c85c82821f..37ce8c946de6 100644
|
||||
--- a/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
+++ b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
@@ -29,6 +29,8 @@ public final class AttestationHooks {
|
||||
private static final String TAG = "GmsCompat/Attestation";
|
||||
|
||||
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() { }
|
||||
@@ -55,7 +57,8 @@ public final class AttestationHooks {
|
||||
}
|
||||
|
||||
public static void initApplicationBeforeOnCreate(Application app) {
|
||||
- if (PACKAGE_GMS.equals(app.getPackageName())) {
|
||||
+ if (PACKAGE_GMS.equals(app.getPackageName()) &&
|
||||
+ PROCESS_UNSTABLE.equals(Application.getProcessName())) {
|
||||
sIsGms = true;
|
||||
spoofBuildGms();
|
||||
}
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
From ace6036332743c6f1a5614b2fd573464ddbffef7 Mon Sep 17 00:00:00 2001
|
||||
From: Dyneteve <dyneteve@hentaios.com>
|
||||
Date: Tue, 23 Aug 2022 18:57:05 +0200
|
||||
Subject: [PATCH 18/22] gmscompat: Apply the SafetyNet workaround to Play Store
|
||||
aswell
|
||||
|
||||
Play Store is used for the new Play Integrity API, extend the hack
|
||||
to it aswell
|
||||
|
||||
Test: Device Integrity and Basic Integrity passes.
|
||||
|
||||
Signed-off-by: Dyneteve <dyneteve@hentaios.com>
|
||||
Change-Id: Id607cdff0b902f285a6c1b769c0a4ee4202842b1
|
||||
---
|
||||
.../android/internal/gmscompat/AttestationHooks.java | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/core/java/com/android/internal/gmscompat/AttestationHooks.java b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
index 37ce8c946de6..65469239a0c6 100644
|
||||
--- a/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
+++ b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
@@ -29,9 +29,11 @@ public final class AttestationHooks {
|
||||
private static final String TAG = "GmsCompat/Attestation";
|
||||
|
||||
private static final String PACKAGE_GMS = "com.google.android.gms";
|
||||
+ private static final String PACKAGE_FINSKY = "com.android.vending";
|
||||
private static final String PROCESS_UNSTABLE = "com.google.android.gms.unstable";
|
||||
|
||||
private static volatile boolean sIsGms = false;
|
||||
+ private static volatile boolean sIsFinsky = false;
|
||||
|
||||
private AttestationHooks() { }
|
||||
|
||||
@@ -62,6 +64,11 @@ public final class AttestationHooks {
|
||||
sIsGms = true;
|
||||
spoofBuildGms();
|
||||
}
|
||||
+
|
||||
+ if (PACKAGE_FINSKY.equals(app.getPackageName())) {
|
||||
+ sIsFinsky = true;
|
||||
+ spoofBuildGms();
|
||||
+ }
|
||||
}
|
||||
|
||||
private static boolean isCallerSafetyNet() {
|
||||
@@ -74,5 +81,10 @@ public final class AttestationHooks {
|
||||
if (sIsGms && isCallerSafetyNet()) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
+
|
||||
+ // Check stack for PlayIntegrity
|
||||
+ if (sIsFinsky) {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
}
|
||||
}
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
From d67897a23c6e182294d6a6d137d7ccc430a1abe0 Mon Sep 17 00:00:00 2001
|
||||
From: Dyneteve <dyneteve@hentaios.com>
|
||||
Date: Thu, 8 Sep 2022 14:39:52 +0200
|
||||
Subject: [PATCH 19/22] gmscompat: Use Nexus 6P fingerprint for CTS/Integrity
|
||||
|
||||
Google seems to have patched the KM block to Play Store in record time,
|
||||
but is still not enforced for anything under android N.
|
||||
|
||||
Since we moved to angler FP we don't need to spoof model to Play Store
|
||||
anymore, however the KM block is still needed.
|
||||
|
||||
Test: Run Play Intregrity Attestation
|
||||
|
||||
Signed-off-by: Dyneteve <dyneteve@hentaios.com>
|
||||
Change-Id: Ic2401a6e40ddfc4318a1d0faa87e42eb118ac3d1
|
||||
---
|
||||
.../com/android/internal/gmscompat/AttestationHooks.java | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/core/java/com/android/internal/gmscompat/AttestationHooks.java b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
index 65469239a0c6..328d9777b2a2 100644
|
||||
--- a/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
+++ b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
@@ -54,8 +54,9 @@ public final class AttestationHooks {
|
||||
}
|
||||
|
||||
private static void spoofBuildGms() {
|
||||
- // Alter model name to avoid hardware attestation enforcement
|
||||
- setBuildField("MODEL", "Pixel 5a");
|
||||
+ // Alter model name and fingerprint to avoid hardware attestation enforcement
|
||||
+ setBuildField("FINGERPRINT", "google/angler/angler:6.0/MDB08L/2343525:user/release-keys");
|
||||
+ setBuildField("MODEL", "Nexus 6P");
|
||||
}
|
||||
|
||||
public static void initApplicationBeforeOnCreate(Application app) {
|
||||
@@ -67,7 +68,6 @@ public final class AttestationHooks {
|
||||
|
||||
if (PACKAGE_FINSKY.equals(app.getPackageName())) {
|
||||
sIsFinsky = true;
|
||||
- spoofBuildGms();
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
From 7893f246007a1989420583ab8728a5ced89e944d Mon Sep 17 00:00:00 2001
|
||||
From: Dyneteve <dyneteve@hentaios.com>
|
||||
Date: Tue, 6 Dec 2022 15:59:08 +0100
|
||||
Subject: [PATCH 20/22] gmscompat: Use actual device model name
|
||||
|
||||
Signed-off-by: Dyneteve <dyneteve@hentaios.com>
|
||||
Change-Id: I454654d87b3ea6286e12e9a9f5ed120f06cb2aa6
|
||||
---
|
||||
core/java/com/android/internal/gmscompat/AttestationHooks.java | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/core/java/com/android/internal/gmscompat/AttestationHooks.java b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
index 328d9777b2a2..7649bb6533da 100644
|
||||
--- a/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
+++ b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
@@ -56,7 +56,7 @@ public final class AttestationHooks {
|
||||
private static void spoofBuildGms() {
|
||||
// Alter model name and fingerprint to avoid hardware attestation enforcement
|
||||
setBuildField("FINGERPRINT", "google/angler/angler:6.0/MDB08L/2343525:user/release-keys");
|
||||
- setBuildField("MODEL", "Nexus 6P");
|
||||
+ setBuildField("MODEL", Build.MODEL + "\u200b");
|
||||
}
|
||||
|
||||
public static void initApplicationBeforeOnCreate(Application app) {
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
From dd5e4484df6868958941773ac310396b281e5ceb Mon Sep 17 00:00:00 2001
|
||||
From: Anirudh Gupta <anirudhgupta109@aosip.dev>
|
||||
Date: Wed, 4 Jan 2023 18:20:56 +0000
|
||||
Subject: [PATCH 21/22] gmscompat: Set shipping level to 32 for devices >=33
|
||||
|
||||
If ro.product.first_api_level is 33, its forced to use HW attestation even though the safteynet checker app shows BASIC
|
||||
setting it to 32 allows for software attestation and passing CTS
|
||||
|
||||
Change-Id: Ie7326eaac48424cdea3d9633ebe13c65053ef6c1
|
||||
Signed-off-by: Dyneteve <dyneteve@hentaios.com>
|
||||
---
|
||||
.../internal/gmscompat/AttestationHooks.java | 18 ++++++++++++++++++
|
||||
1 file changed, 18 insertions(+)
|
||||
|
||||
diff --git a/core/java/com/android/internal/gmscompat/AttestationHooks.java b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
index 7649bb6533da..d2b1d2879c9c 100644
|
||||
--- a/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
+++ b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
@@ -18,6 +18,7 @@ package com.android.internal.gmscompat;
|
||||
|
||||
import android.app.Application;
|
||||
import android.os.Build;
|
||||
+import android.os.Build.VERSION;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -53,10 +54,27 @@ public final class AttestationHooks {
|
||||
}
|
||||
}
|
||||
|
||||
+ private static void setVersionField(String key, Integer value) {
|
||||
+ try {
|
||||
+ // Unlock
|
||||
+ Field field = Build.VERSION.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 and fingerprint to avoid hardware attestation enforcement
|
||||
setBuildField("FINGERPRINT", "google/angler/angler:6.0/MDB08L/2343525:user/release-keys");
|
||||
setBuildField("MODEL", Build.MODEL + "\u200b");
|
||||
+ setVersionField("DEVICE_INITIAL_SDK_INT", Build.VERSION_CODES.S);
|
||||
}
|
||||
|
||||
public static void initApplicationBeforeOnCreate(Application app) {
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
From 4ffed064b21d9662631ee70d20dfd8441fcec574 Mon Sep 17 00:00:00 2001
|
||||
From: Dyneteve <dyneteve@hentaios.com>
|
||||
Date: Wed, 8 Feb 2023 15:21:01 +0000
|
||||
Subject: [PATCH 22/22] gmscompat: Make CTS/Play Integrity pass again
|
||||
|
||||
The logic behind CTS and Play Integrity has been updated today it now
|
||||
checks the product and model names against the fingerprint and if
|
||||
they do not match the CTS profile will fail.
|
||||
|
||||
Also while we are at it use a newer FP from Pixel XL and add logging
|
||||
for key attestation blocking for debugging.
|
||||
|
||||
Test: Boot, check for CTS and Play Integrity
|
||||
|
||||
Change-Id: I089d5ef935bba40338e10c795ea7d181103ffd15
|
||||
Signed-off-by: Dyneteve <dyneteve@hentaios.com>
|
||||
---
|
||||
.../internal/gmscompat/AttestationHooks.java | 20 +++++++++----------
|
||||
1 file changed, 9 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/core/java/com/android/internal/gmscompat/AttestationHooks.java b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
index d2b1d2879c9c..ef7a308a25bc 100644
|
||||
--- a/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
+++ b/core/java/com/android/internal/gmscompat/AttestationHooks.java
|
||||
@@ -72,9 +72,11 @@ public final class AttestationHooks {
|
||||
|
||||
private static void spoofBuildGms() {
|
||||
// Alter model name and fingerprint to avoid hardware attestation enforcement
|
||||
- setBuildField("FINGERPRINT", "google/angler/angler:6.0/MDB08L/2343525:user/release-keys");
|
||||
- setBuildField("MODEL", Build.MODEL + "\u200b");
|
||||
- setVersionField("DEVICE_INITIAL_SDK_INT", Build.VERSION_CODES.S);
|
||||
+ setBuildField("FINGERPRINT", "google/marlin/marlin:7.1.2/NJH47F/4146041:user/release-keys");
|
||||
+ setBuildField("PRODUCT", "marlin");
|
||||
+ setBuildField("DEVICE", "marlin");
|
||||
+ setBuildField("MODEL", "Pixel XL");
|
||||
+ setVersionField("DEVICE_INITIAL_SDK_INT", Build.VERSION_CODES.N_MR1);
|
||||
}
|
||||
|
||||
public static void initApplicationBeforeOnCreate(Application app) {
|
||||
@@ -90,18 +92,14 @@ public final class AttestationHooks {
|
||||
}
|
||||
|
||||
private static boolean isCallerSafetyNet() {
|
||||
- return Arrays.stream(Thread.currentThread().getStackTrace())
|
||||
+ return sIsGms && 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();
|
||||
- }
|
||||
-
|
||||
- // Check stack for PlayIntegrity
|
||||
- if (sIsFinsky) {
|
||||
+ // Check stack for SafetyNet or Play Integrity
|
||||
+ if (isCallerSafetyNet() || sIsFinsky) {
|
||||
+ Log.i(TAG, "Blocked key attestation sIsGms=" + sIsGms + " sIsFinsky=" + sIsFinsky);
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
--
|
||||
2.34.1
|
||||
|
||||
Reference in New Issue
Block a user