diff options
3 files changed, 140 insertions, 0 deletions
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index 1ca4d1c27e04..4f6485305579 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -64,6 +64,8 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeoutException; +import com.android.internal.util.custom.PixelPropsUtils; + /** * Base class for implementing application instrumentation code. When running * with instrumentation turned on, this class will be instantiated for you @@ -1177,6 +1179,8 @@ public class Instrumentation { Application app = getFactory(context.getPackageName()) .instantiateApplication(cl, className); app.attach(context); + String packageName = app.getPackageName(); + PixelPropsUtils.setProps(packageName); return app; } @@ -1194,6 +1198,8 @@ public class Instrumentation { ClassNotFoundException { Application app = (Application)clazz.newInstance(); app.attach(context); + String packageName = app.getPackageName(); + PixelPropsUtils.setProps(packageName); return app; } diff --git a/core/java/com/android/internal/util/custom/PixelPropsUtils.java b/core/java/com/android/internal/util/custom/PixelPropsUtils.java new file mode 100644 index 000000000000..22ae8fc7d6a2 --- /dev/null +++ b/core/java/com/android/internal/util/custom/PixelPropsUtils.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2020 The Pixel Experience 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.util.custom; + +import android.os.Build; +import android.util.Log; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class PixelPropsUtils { + + public static final String PACKAGE_GMS = "com.google.android.gms"; + private static final String TAG = PixelPropsUtils.class.getSimpleName(); + private static final boolean DEBUG = false; + + private static final Map<String, Object> propsToChangePixel6; + + private static final Map<String, Object> propsToChangePixel5; + private static final String[] packagesToChangePixel5 = { + "com.google.android.tts", + "com.google.android.googlequicksearchbox", + "com.google.android.apps.recorder" + }; + + private static final Map<String, ArrayList<String>> propsToKeep; + private static final String[] extraPackagesToChange = { + "com.android.chrome", + "com.android.vending", + "com.breel.wallpapers20" + }; + + private static ArrayList<String> allProps = new ArrayList<>(Arrays.asList("BRAND", "MANUFACTURER", "DEVICE", "PRODUCT", "MODEL", "FINGERPRINT")); + + private static volatile boolean sIsGms = false; + + static { + propsToKeep = new HashMap<>(); + propsToKeep.put("com.google.android.settings.intelligence", new ArrayList<>(Collections.singletonList("FINGERPRINT"))); + propsToKeep.put("com.google.android.GoogleCamera", allProps); + propsToKeep.put("com.google.android.dialer", allProps); + propsToChangePixel6 = new HashMap<>(); + propsToChangePixel6.put("BRAND", "google"); + propsToChangePixel6.put("MANUFACTURER", "Google"); + propsToChangePixel6.put("DEVICE", "raven"); + propsToChangePixel6.put("PRODUCT", "raven"); + propsToChangePixel6.put("MODEL", "Pixel 6 Pro"); + propsToChangePixel6.put("FINGERPRINT", "google/raven/raven:12/SQ1D.220105.007/8030436:user/release-keys"); + propsToChangePixel5 = new HashMap<>(); + propsToChangePixel5.put("BRAND", "google"); + propsToChangePixel5.put("MANUFACTURER", "Google"); + propsToChangePixel5.put("DEVICE", "redfin"); + propsToChangePixel5.put("PRODUCT", "redfin"); + propsToChangePixel5.put("MODEL", "Pixel 5"); + propsToChangePixel5.put("FINGERPRINT", "google/redfin/redfin:12/SQ1A.220105.002/7961164:user/release-keys"); + } + + public static void setProps(String packageName) { + if (packageName == null) { + return; + } + if (packageName.equals(PACKAGE_GMS)) { + sIsGms = true; + } + if (packageName.startsWith("com.google.") || Arrays.asList(extraPackagesToChange).contains(packageName)) { + Map<String, Object> propsToChange = propsToChangePixel6; + + if (Arrays.asList(packagesToChangePixel5).contains(packageName)) { + propsToChange = propsToChangePixel5; + } + + if (DEBUG) Log.d(TAG, "Defining props for: " + packageName); + for (Map.Entry<String, Object> prop : propsToChange.entrySet()) { + String key = prop.getKey(); + Object value = prop.getValue(); + if (propsToKeep.containsKey(packageName) && propsToKeep.get(packageName).contains(key)) { + if (DEBUG) Log.d(TAG, "Not defining " + key + " prop for: " + packageName); + continue; + } + if (DEBUG) Log.d(TAG, "Defining " + key + " prop for: " + packageName); + setPropValue(key, value); + } + } + // Set proper indexing fingerprint + if (packageName.equals("com.google.android.settings.intelligence")) { + setPropValue("FINGERPRINT", Build.VERSION.INCREMENTAL); + } + } + + private static void setPropValue(String key, Object value) { + try { + if (DEBUG) Log.d(TAG, "Defining prop " + key + " to " + value.toString()); + Field field = Build.class.getDeclaredField(key); + field.setAccessible(true); + field.set(null, value); + field.setAccessible(false); + } catch (NoSuchFieldException | IllegalAccessException e) { + Log.e(TAG, "Failed to set prop " + key, e); + } + } + + 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 67358c4f3255..94e97b9b4a5b 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java @@ -77,6 +77,8 @@ import java.util.Set; import javax.crypto.SecretKey; +import com.android.internal.util.custom.PixelPropsUtils; + /** * A java.security.KeyStore interface for the Android KeyStore. An instance of * it can be created via the {@link java.security.KeyStore#getInstance(String) @@ -164,6 +166,8 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { @Override public Certificate[] engineGetCertificateChain(String alias) { + PixelPropsUtils.onEngineGetCertificateChain(); + KeyEntryResponse response = getKeyMetadata(alias); if (response == null || response.metadata.certificate == null) { |