From 56b8bc9f6538e750358c69c8aab77b2b9dfc6f6a Mon Sep 17 00:00:00 2001 From: Marvin W Date: Tue, 18 Jan 2022 18:40:48 +0100 Subject: [PATCH] Update DroidGuard + SafetyNet --- .../gms/safetynet/AttestationData.java | 41 ------- .../gms/safetynet/HarmfulAppsInfo.java | 32 ----- .../gms/safetynet/RecaptchaResultData.java | 26 ---- .../gms/safetynet/RemoveHarmfulAppData.java | 28 ----- .../microg/gms/safetynet/SafetyNetPrefs.java | 114 ------------------ .../org/microg/gms/safetynet/ServiceInfo.kt | 90 -------------- .../src/main/AndroidManifest.xml | 2 +- .../droidguard/DroidGuardChimeraService.java | 5 +- .../tracing/wrapper/TracingIntentService.java | 2 +- .../microg/gms/droidguard/GuardCallback.java | 1 + .../droidguard/{ => core}/BytesException.kt | 2 +- .../droidguard/{ => core}/DgDatabaseHelper.kt | 2 +- .../{ => core}/DgpDatabaseHelper.kt | 2 +- .../{ => core}/DroidGuardHandleImpl.kt | 23 ++-- .../{ => core}/DroidGuardPreferences.kt | 19 ++- .../{ => core}/DroidGuardResultCreator.kt | 10 +- .../{ => core}/DroidGuardService.kt | 2 +- .../{ => core}/DroidGuardServiceBroker.kt | 4 +- .../{ => core}/DroidGuardServiceImpl.kt | 4 +- .../droidguard/{ => core}/FallbackCreator.kt | 4 +- .../gms/droidguard/{ => core}/HandleProxy.kt | 4 +- .../{ => core}/HandleProxyFactory.kt | 7 +- .../{ => core}/SignatureVerifier.kt | 4 +- .../gms/droidguard/{ => core}/VersionUtil.kt | 5 +- .../microg/gms/droidguard/DroidGuardHandle.kt | 16 ++- play-services-safetynet-api/build.gradle | 35 ++++++ .../src/main/AndroidManifest.xml | 7 ++ .../gms/safetynet/AttestationData.aidl | 0 .../gms/safetynet/HarmfulAppsData.aidl | 0 .../gms/safetynet/HarmfulAppsInfo.aidl | 0 .../gms/safetynet/RecaptchaResultData.aidl | 0 .../gms/safetynet/RemoveHarmfulAppData.aidl | 0 .../gms/safetynet/SafeBrowsingData.aidl | 0 .../internal/ISafetyNetCallbacks.aidl | 0 .../safetynet/internal/ISafetyNetService.aidl | 0 .../gms/safetynet/AttestationData.java | 29 +++++ .../gms/safetynet/HarmfulAppsData.java | 2 +- .../gms/safetynet/HarmfulAppsInfo.java | 21 ++++ .../gms/safetynet/RecaptchaResultData.java | 15 +++ .../gms/safetynet/RemoveHarmfulAppData.java | 17 +++ .../gms/safetynet/SafeBrowsingData.java | 15 +-- .../gms/safetynet/SafetyNetStatusCodes.java | 2 +- .../gms/safetynet/VerifyAppsConstants.java | 2 +- .../build.gradle | 35 ++++++ .../src/main/proto/safetynet.proto | 4 +- play-services-safetynet-core/build.gradle | 63 ++++++++++ .../src/main/AndroidManifest.xml | 24 ++++ .../org/microg/gms/safetynet/Attestation.java | 15 +-- .../gms/safetynet}/ReCaptchaActivity.kt | 55 +++++++-- .../gms/safetynet/SafetyNetClientService.kt | 77 ++++++++---- .../gms/safetynet/SafetyNetPreferences.kt | 31 +++++ .../src/main/res/drawable/ic_recaptcha.xml | 0 .../src/main/res/layout/recaptcha_window.xml | 0 53 files changed, 464 insertions(+), 434 deletions(-) delete mode 100644 play-services-api/src/main/java/com/google/android/gms/safetynet/AttestationData.java delete mode 100644 play-services-api/src/main/java/com/google/android/gms/safetynet/HarmfulAppsInfo.java delete mode 100644 play-services-api/src/main/java/com/google/android/gms/safetynet/RecaptchaResultData.java delete mode 100644 play-services-api/src/main/java/com/google/android/gms/safetynet/RemoveHarmfulAppData.java delete mode 100644 play-services-core/src/main/java/org/microg/gms/safetynet/SafetyNetPrefs.java delete mode 100644 play-services-core/src/main/kotlin/org/microg/gms/safetynet/ServiceInfo.kt rename play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/{ => core}/BytesException.kt (92%) rename play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/{ => core}/DgDatabaseHelper.kt (98%) rename play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/{ => core}/DgpDatabaseHelper.kt (93%) rename play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/{ => core}/DroidGuardHandleImpl.kt (87%) rename play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/{ => core}/DroidGuardPreferences.kt (58%) rename play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/{ => core}/DroidGuardResultCreator.kt (89%) rename play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/{ => core}/DroidGuardService.kt (89%) rename play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/{ => core}/DroidGuardServiceBroker.kt (91%) rename play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/{ => core}/DroidGuardServiceImpl.kt (93%) rename play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/{ => core}/FallbackCreator.kt (91%) rename play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/{ => core}/HandleProxy.kt (95%) rename play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/{ => core}/HandleProxyFactory.kt (98%) rename play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/{ => core}/SignatureVerifier.kt (93%) rename play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/{ => core}/VersionUtil.kt (96%) create mode 100644 play-services-safetynet-api/build.gradle create mode 100644 play-services-safetynet-api/src/main/AndroidManifest.xml rename {play-services-api => play-services-safetynet-api}/src/main/aidl/com/google/android/gms/safetynet/AttestationData.aidl (100%) rename {play-services-api => play-services-safetynet-api}/src/main/aidl/com/google/android/gms/safetynet/HarmfulAppsData.aidl (100%) rename {play-services-api => play-services-safetynet-api}/src/main/aidl/com/google/android/gms/safetynet/HarmfulAppsInfo.aidl (100%) rename {play-services-api => play-services-safetynet-api}/src/main/aidl/com/google/android/gms/safetynet/RecaptchaResultData.aidl (100%) rename {play-services-api => play-services-safetynet-api}/src/main/aidl/com/google/android/gms/safetynet/RemoveHarmfulAppData.aidl (100%) rename {play-services-api => play-services-safetynet-api}/src/main/aidl/com/google/android/gms/safetynet/SafeBrowsingData.aidl (100%) rename {play-services-api => play-services-safetynet-api}/src/main/aidl/com/google/android/gms/safetynet/internal/ISafetyNetCallbacks.aidl (100%) rename {play-services-api => play-services-safetynet-api}/src/main/aidl/com/google/android/gms/safetynet/internal/ISafetyNetService.aidl (100%) create mode 100644 play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/AttestationData.java rename {play-services-api => play-services-safetynet-api}/src/main/java/com/google/android/gms/safetynet/HarmfulAppsData.java (96%) create mode 100644 play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/HarmfulAppsInfo.java create mode 100644 play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/RecaptchaResultData.java create mode 100644 play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/RemoveHarmfulAppData.java rename {play-services-api => play-services-safetynet-api}/src/main/java/com/google/android/gms/safetynet/SafeBrowsingData.java (55%) rename {play-services-api => play-services-safetynet-api}/src/main/java/com/google/android/gms/safetynet/SafetyNetStatusCodes.java (96%) rename {play-services-api => play-services-safetynet-api}/src/main/java/com/google/android/gms/safetynet/VerifyAppsConstants.java (97%) create mode 100644 play-services-safetynet-core-proto/build.gradle rename play-services-core-proto/src/main/proto/snet.proto => play-services-safetynet-core-proto/src/main/proto/safetynet.proto (93%) create mode 100644 play-services-safetynet-core/build.gradle create mode 100644 play-services-safetynet-core/src/main/AndroidManifest.xml rename {play-services-core => play-services-safetynet-core}/src/main/java/org/microg/gms/safetynet/Attestation.java (92%) rename {play-services-core/src/main/kotlin/org/microg/gms/recaptcha => play-services-safetynet-core/src/main/kotlin/org/microg/gms/safetynet}/ReCaptchaActivity.kt (79%) rename {play-services-core => play-services-safetynet-core}/src/main/kotlin/org/microg/gms/safetynet/SafetyNetClientService.kt (62%) create mode 100644 play-services-safetynet-core/src/main/kotlin/org/microg/gms/safetynet/SafetyNetPreferences.kt rename {play-services-core => play-services-safetynet-core}/src/main/res/drawable/ic_recaptcha.xml (100%) rename {play-services-core => play-services-safetynet-core}/src/main/res/layout/recaptcha_window.xml (100%) diff --git a/play-services-api/src/main/java/com/google/android/gms/safetynet/AttestationData.java b/play-services-api/src/main/java/com/google/android/gms/safetynet/AttestationData.java deleted file mode 100644 index 4f127291..00000000 --- a/play-services-api/src/main/java/com/google/android/gms/safetynet/AttestationData.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013-2017 microG Project Team - * - * 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.google.android.gms.safetynet; - -import org.microg.safeparcel.AutoSafeParcelable; -import org.microg.safeparcel.SafeParceled; - -public class AttestationData extends AutoSafeParcelable { - @SafeParceled(1) - private int versionCode = 1; - @SafeParceled(2) - private final String jwsResult; - - private AttestationData() { - jwsResult = null; - } - - public AttestationData(String jwsResult) { - this.jwsResult = jwsResult; - } - - public String getJwsResult() { - return jwsResult; - } - - public static final Creator CREATOR = new AutoCreator(AttestationData.class); -} diff --git a/play-services-api/src/main/java/com/google/android/gms/safetynet/HarmfulAppsInfo.java b/play-services-api/src/main/java/com/google/android/gms/safetynet/HarmfulAppsInfo.java deleted file mode 100644 index 6ae6bf65..00000000 --- a/play-services-api/src/main/java/com/google/android/gms/safetynet/HarmfulAppsInfo.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2013-2017 microG Project Team - * - * 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.google.android.gms.safetynet; - -import org.microg.safeparcel.AutoSafeParcelable; - -public class HarmfulAppsInfo extends AutoSafeParcelable { - @Field(2) - public long field2; - @Field(3) - public HarmfulAppsData[] data; - @Field(4) - public int field4; - @Field(5) - public boolean field5; - - public static final Creator CREATOR = new AutoCreator(HarmfulAppsInfo.class); -} diff --git a/play-services-api/src/main/java/com/google/android/gms/safetynet/RecaptchaResultData.java b/play-services-api/src/main/java/com/google/android/gms/safetynet/RecaptchaResultData.java deleted file mode 100644 index 748f1129..00000000 --- a/play-services-api/src/main/java/com/google/android/gms/safetynet/RecaptchaResultData.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2013-2017 microG Project Team - * - * 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.google.android.gms.safetynet; - -import org.microg.safeparcel.AutoSafeParcelable; - -public class RecaptchaResultData extends AutoSafeParcelable { - @Field(2) - public String token; - - public static final Creator CREATOR = new AutoCreator(RecaptchaResultData.class); -} diff --git a/play-services-api/src/main/java/com/google/android/gms/safetynet/RemoveHarmfulAppData.java b/play-services-api/src/main/java/com/google/android/gms/safetynet/RemoveHarmfulAppData.java deleted file mode 100644 index 32901e07..00000000 --- a/play-services-api/src/main/java/com/google/android/gms/safetynet/RemoveHarmfulAppData.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2013-2017 microG Project Team - * - * 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.google.android.gms.safetynet; - -import org.microg.safeparcel.AutoSafeParcelable; - -public class RemoveHarmfulAppData extends AutoSafeParcelable { - @Field(2) - public int field2; - @Field(3) - public boolean field3; - - public static final Creator CREATOR = new AutoCreator(RemoveHarmfulAppData.class); -} diff --git a/play-services-core/src/main/java/org/microg/gms/safetynet/SafetyNetPrefs.java b/play-services-core/src/main/java/org/microg/gms/safetynet/SafetyNetPrefs.java deleted file mode 100644 index eb87bf40..00000000 --- a/play-services-core/src/main/java/org/microg/gms/safetynet/SafetyNetPrefs.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021, microG Project Team - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.microg.gms.safetynet; - -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; - -import org.microg.gms.common.PackageUtils; - -import java.io.File; - -public class SafetyNetPrefs implements SharedPreferences.OnSharedPreferenceChangeListener { - private static final String OFFICIAL_ATTEST_BASE_URL = "https://www.googleapis.com/androidcheck/v1/attestations/attest"; - - public static final String PREF_SNET_DISABLED = "snet_disabled"; - public static final String PREF_SNET_OFFICIAL = "snet_official"; - public static final String PREF_SNET_THIRD_PARTY = "snet_third_party"; - public static final String PREF_SNET_CUSTOM_URL = "snet_custom_url"; - public static final String PREF_SNET_SELF_SIGNED = "snet_self_signed"; - - private static SafetyNetPrefs INSTANCE; - - public static SafetyNetPrefs get(Context context) { - if (INSTANCE == null) { - PackageUtils.warnIfNotMainProcess(context, SafetyNetPrefs.class); - if (context == null) return new SafetyNetPrefs(null); - INSTANCE = new SafetyNetPrefs(context.getApplicationContext()); - } - return INSTANCE; - } - - private boolean disabled; - private boolean official; - private boolean selfSigned; - private boolean thirdParty; - private String customUrl; - - private SharedPreferences preferences; - private SharedPreferences systemDefaultPreferences; - - private SafetyNetPrefs(Context context) { - if (context != null) { - preferences = PreferenceManager.getDefaultSharedPreferences(context); - preferences.registerOnSharedPreferenceChangeListener(this); - try { - systemDefaultPreferences = (SharedPreferences) Context.class.getDeclaredMethod("getSharedPreferences", File.class, int.class).invoke(context, new File("/system/etc/microg.xml"), Context.MODE_PRIVATE); - } catch (Exception ignored) { - } - update(); - } - } - - private boolean getSettingsBoolean(String key, boolean def) { - if (systemDefaultPreferences != null) { - def = systemDefaultPreferences.getBoolean(key, def); - } - return preferences.getBoolean(key, def); - } - - private String getSettingsString(String key, String def) { - if (systemDefaultPreferences != null) { - def = systemDefaultPreferences.getString(key, def); - } - return preferences.getString(key, def); - } - - public void update() { - disabled = getSettingsBoolean(PREF_SNET_DISABLED, true); - official = getSettingsBoolean(PREF_SNET_OFFICIAL, false); - selfSigned = getSettingsBoolean(PREF_SNET_SELF_SIGNED, false); - thirdParty = getSettingsBoolean(PREF_SNET_THIRD_PARTY, false); - customUrl = getSettingsString(PREF_SNET_CUSTOM_URL, null); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) { - update(); - } - - public boolean isEnabled() { - return !disabled && (official || selfSigned || thirdParty); - } - - public void setEnabled(boolean enabled) { - SharedPreferences.Editor edit = preferences.edit(); - edit.putBoolean(PREF_SNET_DISABLED, !enabled); - if (enabled && !isEnabled()) { - official = true; - edit.putBoolean(PREF_SNET_OFFICIAL, true); - } - edit.commit(); - } - - public boolean isSelfSigned() { - return selfSigned; - } - - public boolean isOfficial() { - return official; - } - - public boolean isThirdParty() { - return thirdParty; - } - - public String getServiceUrl() { - if (official) return OFFICIAL_ATTEST_BASE_URL; - return customUrl; - } -} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/safetynet/ServiceInfo.kt b/play-services-core/src/main/kotlin/org/microg/gms/safetynet/ServiceInfo.kt deleted file mode 100644 index 8d917572..00000000 --- a/play-services-core/src/main/kotlin/org/microg/gms/safetynet/ServiceInfo.kt +++ /dev/null @@ -1,90 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021, microG Project Team - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.microg.gms.safetynet - -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter -import android.util.Log -import java.io.Serializable -import kotlin.coroutines.resume -import kotlin.coroutines.resumeWithException -import kotlin.coroutines.suspendCoroutine - -private const val ACTION_SERVICE_INFO_REQUEST = "org.microg.gms.snet.SERVICE_INFO_REQUEST" -private const val ACTION_UPDATE_CONFIGURATION = "org.microg.gms.snet.UPDATE_CONFIGURATION" -private const val ACTION_SERVICE_INFO_RESPONSE = "org.microg.gms.snet.SERVICE_INFO_RESPONSE" -private const val EXTRA_SERVICE_INFO = "org.microg.gms.snet.SERVICE_INFO" -private const val EXTRA_CONFIGURATION = "org.microg.gms.snet.CONFIGURATION" -private const val TAG = "GmsSafetyNetStatusInfo" - -data class ServiceInfo(val configuration: ServiceConfiguration) : Serializable - -data class ServiceConfiguration(val enabled: Boolean) : Serializable { - fun saveToPrefs(context: Context) { - SafetyNetPrefs.get(context).isEnabled = enabled - } -} - -private fun SafetyNetPrefs.toConfiguration(): ServiceConfiguration = ServiceConfiguration(isEnabled) - -class ServiceInfoReceiver : BroadcastReceiver() { - private fun sendInfoResponse(context: Context) { - context.sendOrderedBroadcast(Intent(ACTION_SERVICE_INFO_RESPONSE).apply { - setPackage(context.packageName) - putExtra(EXTRA_SERVICE_INFO, ServiceInfo(SafetyNetPrefs.get(context).toConfiguration())) - }, null) - } - - override fun onReceive(context: Context, intent: Intent) { - try { - when (intent.action) { - ACTION_UPDATE_CONFIGURATION -> { - (intent.getSerializableExtra(EXTRA_CONFIGURATION) as? ServiceConfiguration)?.saveToPrefs(context) - } - } - sendInfoResponse(context) - } catch (e: Exception) { - Log.w(TAG, e) - } - } -} - -private suspend fun sendToServiceInfoReceiver(intent: Intent, context: Context): ServiceInfo = suspendCoroutine { - context.registerReceiver(object : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - context.unregisterReceiver(this) - val serviceInfo = try { - intent.getSerializableExtra(EXTRA_SERVICE_INFO) as ServiceInfo - } catch (e: Exception) { - it.resumeWithException(e) - return - } - try { - it.resume(serviceInfo) - } catch (e: Exception) { - Log.w(TAG, e) - } - } - }, IntentFilter(ACTION_SERVICE_INFO_RESPONSE)) - try { - context.sendOrderedBroadcast(intent, null) - } catch (e: Exception) { - it.resumeWithException(e) - } -} - -suspend fun getSafetyNetServiceInfo(context: Context): ServiceInfo = sendToServiceInfoReceiver( - Intent(context, ServiceInfoReceiver::class.java).apply { - action = ACTION_SERVICE_INFO_REQUEST - }, context) - -suspend fun setSafetyNetServiceConfiguration(context: Context, configuration: ServiceConfiguration): ServiceInfo = sendToServiceInfoReceiver( - Intent(context, ServiceInfoReceiver::class.java).apply { - action = ACTION_UPDATE_CONFIGURATION - putExtra(EXTRA_CONFIGURATION, configuration) - }, context) diff --git a/play-services-droidguard-core/src/main/AndroidManifest.xml b/play-services-droidguard-core/src/main/AndroidManifest.xml index c38b66c4..a8517e9a 100644 --- a/play-services-droidguard-core/src/main/AndroidManifest.xml +++ b/play-services-droidguard-core/src/main/AndroidManifest.xml @@ -11,7 +11,7 @@ diff --git a/play-services-droidguard-core/src/main/java/com/google/android/gms/droidguard/DroidGuardChimeraService.java b/play-services-droidguard-core/src/main/java/com/google/android/gms/droidguard/DroidGuardChimeraService.java index a8a56582..5c860186 100644 --- a/play-services-droidguard-core/src/main/java/com/google/android/gms/droidguard/DroidGuardChimeraService.java +++ b/play-services-droidguard-core/src/main/java/com/google/android/gms/droidguard/DroidGuardChimeraService.java @@ -6,7 +6,6 @@ package com.google.android.gms.droidguard; import android.content.Intent; -import android.os.Debug; import android.os.Handler; import android.os.IBinder; import android.util.Base64; @@ -16,9 +15,9 @@ import androidx.annotation.Nullable; import com.google.android.gms.framework.tracing.wrapper.TracingIntentService; -import org.microg.gms.droidguard.DroidGuardServiceBroker; +import org.microg.gms.droidguard.core.DroidGuardServiceBroker; import org.microg.gms.droidguard.GuardCallback; -import org.microg.gms.droidguard.HandleProxyFactory; +import org.microg.gms.droidguard.core.HandleProxyFactory; import org.microg.gms.droidguard.PingData; import org.microg.gms.droidguard.Request; diff --git a/play-services-droidguard-core/src/main/java/com/google/android/gms/framework/tracing/wrapper/TracingIntentService.java b/play-services-droidguard-core/src/main/java/com/google/android/gms/framework/tracing/wrapper/TracingIntentService.java index 0db16eb6..8c75b5aa 100644 --- a/play-services-droidguard-core/src/main/java/com/google/android/gms/framework/tracing/wrapper/TracingIntentService.java +++ b/play-services-droidguard-core/src/main/java/com/google/android/gms/framework/tracing/wrapper/TracingIntentService.java @@ -16,7 +16,7 @@ import androidx.annotation.Nullable; import com.google.android.chimera.IntentService; import org.microg.gms.utils.PackageManagerWrapper; -import org.microg.gms.droidguard.VersionUtil; +import org.microg.gms.droidguard.core.VersionUtil; public abstract class TracingIntentService extends IntentService { private static final String TAG = "TracingIntentService"; diff --git a/play-services-droidguard-core/src/main/java/org/microg/gms/droidguard/GuardCallback.java b/play-services-droidguard-core/src/main/java/org/microg/gms/droidguard/GuardCallback.java index 4a3b4c2c..3fc81e79 100644 --- a/play-services-droidguard-core/src/main/java/org/microg/gms/droidguard/GuardCallback.java +++ b/play-services-droidguard-core/src/main/java/org/microg/gms/droidguard/GuardCallback.java @@ -10,6 +10,7 @@ import android.media.MediaDrm; import android.os.Build; import android.util.Log; +import org.microg.gms.droidguard.core.FallbackCreator; import org.microg.gms.settings.SettingsContract; import java.util.HashMap; diff --git a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/BytesException.kt b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/BytesException.kt similarity index 92% rename from play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/BytesException.kt rename to play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/BytesException.kt index 32721ee2..71ef9142 100644 --- a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/BytesException.kt +++ b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/BytesException.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package org.microg.gms.droidguard +package org.microg.gms.droidguard.core class BytesException : Exception { val bytes: ByteArray diff --git a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DgDatabaseHelper.kt b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DgDatabaseHelper.kt similarity index 98% rename from play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DgDatabaseHelper.kt rename to play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DgDatabaseHelper.kt index e1c4f491..169c3a03 100644 --- a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DgDatabaseHelper.kt +++ b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DgDatabaseHelper.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package org.microg.gms.droidguard +package org.microg.gms.droidguard.core import android.content.ContentValues import android.content.Context diff --git a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DgpDatabaseHelper.kt b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DgpDatabaseHelper.kt similarity index 93% rename from play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DgpDatabaseHelper.kt rename to play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DgpDatabaseHelper.kt index 269de569..35da697e 100644 --- a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DgpDatabaseHelper.kt +++ b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DgpDatabaseHelper.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package org.microg.gms.droidguard +package org.microg.gms.droidguard.core import android.content.Context import android.database.sqlite.SQLiteDatabase diff --git a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardHandleImpl.kt b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardHandleImpl.kt similarity index 87% rename from play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardHandleImpl.kt rename to play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardHandleImpl.kt index fff942c1..87a73f18 100644 --- a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardHandleImpl.kt +++ b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardHandleImpl.kt @@ -1,19 +1,21 @@ /* - * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-FileCopyrightText: 2021 microG Project Team * SPDX-License-Identifier: Apache-2.0 */ -package org.microg.gms.droidguard +package org.microg.gms.droidguard.core import android.annotation.SuppressLint import android.content.Context import android.os.ConditionVariable import android.os.ParcelFileDescriptor import android.os.Parcelable +import android.util.Base64 import android.util.Log import com.google.android.gms.droidguard.internal.DroidGuardInitReply import com.google.android.gms.droidguard.internal.DroidGuardResultsRequest import com.google.android.gms.droidguard.internal.IDroidGuardHandle +import org.microg.gms.droidguard.GuardCallback import java.io.FileNotFoundException class DroidGuardHandleImpl(private val context: Context, private val packageName: String, private val factory: HandleProxyFactory, private val callback: GuardCallback) : IDroidGuardHandle.Stub() { @@ -34,14 +36,15 @@ class DroidGuardHandleImpl(private val context: Context, private val packageName this.flow = flow try { var handleProxy: HandleProxy? = null - if (flow !in NOT_LOW_LATENCY_FLOWS) { - try { - handleProxy = factory.createLowLatencyHandle(flow, callback, request) - Log.d(TAG, "Using low-latency handle") - } catch (e: Exception) { - Log.w(TAG, e) - } - } + // FIXME: Temporary disabled low latency handle +// if (flow !in NOT_LOW_LATENCY_FLOWS) { +// try { +// handleProxy = factory.createLowLatencyHandle(flow, callback, request) +// Log.d(TAG, "Using low-latency handle") +// } catch (e: Exception) { +// Log.w(TAG, e) +// } +// } if (handleProxy == null) { handleProxy = factory.createHandle(packageName, flow, callback, request) } diff --git a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardPreferences.kt b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardPreferences.kt similarity index 58% rename from play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardPreferences.kt rename to play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardPreferences.kt index d038c53c..f62aa8e2 100644 --- a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardPreferences.kt +++ b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardPreferences.kt @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-FileCopyrightText: 2021 microG Project Team * SPDX-License-Identifier: Apache-2.0 */ -package org.microg.gms.droidguard +package org.microg.gms.droidguard.core +import android.content.ContentValues import android.content.Context import android.database.Cursor import androidx.core.database.getStringOrNull @@ -23,15 +24,27 @@ object DroidGuardPreferences { } } + private fun setSettings(context: Context, f: ContentValues.() -> Unit) = + SettingsContract.setSettings(context, SettingsContract.DroidGuard.getContentUri(context), f) + @JvmStatic - fun isEnabled(context: Context): Boolean = true //getSettings(context, ENABLED, false) { it.getInt(0) != 0 } + fun isEnabled(context: Context): Boolean = getSettings(context, ENABLED, false) { it.getInt(0) != 0 } + + @JvmStatic + fun setEnabled(context: Context, enabled: Boolean) = setSettings(context) { put(ENABLED, enabled) } @JvmStatic fun getMode(context: Context): Mode = getSettings(context, MODE, Mode.Embedded) { c -> Mode.valueOf(c.getString(0)) } + @JvmStatic + fun setMode(context: Context, mode: Mode) = setSettings(context) { put(MODE, mode.toString()) } + @JvmStatic fun getNetworkServerUrl(context: Context): String? = getSettings(context, NETWORK_SERVER_URL, null) { c -> c.getStringOrNull(0) } + @JvmStatic + fun setNetworkServerUrl(context: Context, url: String?) = setSettings(context) { put(NETWORK_SERVER_URL, url) } + enum class Mode { Embedded, Network diff --git a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardResultCreator.kt b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardResultCreator.kt similarity index 89% rename from play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardResultCreator.kt rename to play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardResultCreator.kt index 68e2bee3..932b4073 100644 --- a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardResultCreator.kt +++ b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardResultCreator.kt @@ -1,9 +1,9 @@ /* - * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-FileCopyrightText: 2021 microG Project Team * SPDX-License-Identifier: Apache-2.0 */ -package org.microg.gms.droidguard +package org.microg.gms.droidguard.core import android.content.Context import android.util.Base64 @@ -11,6 +11,8 @@ import com.android.volley.VolleyError import com.android.volley.toolbox.StringRequest import com.android.volley.toolbox.Volley import com.google.android.gms.tasks.await +import org.microg.gms.droidguard.DroidGuardClient +import org.microg.gms.droidguard.DroidGuardClientImpl import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException import kotlin.coroutines.suspendCoroutine @@ -37,13 +39,13 @@ interface DroidGuardResultCreator { private class NetworkDroidGuardResultCreator(private val context: Context) : DroidGuardResultCreator { private val queue = Volley.newRequestQueue(context) private val url: String - get() = DroidGuardPreferences.getNetworkServerUrl(context) ?: throw RuntimeException("Network URL required") + get() = DroidGuardPreferences.getNetworkServerUrl(context) ?: throw IllegalStateException("Network URL required") override suspend fun getResult(flow: String, data: Map): ByteArray = suspendCoroutine { continuation -> queue.add(PostParamsStringRequest("$url?flow=$flow", data, { continuation.resume(Base64.decode(it, Base64.NO_WRAP + Base64.NO_PADDING + Base64.URL_SAFE)) }, { - continuation.resumeWithException(RuntimeException(it)) + continuation.resumeWithException(it.cause ?: it) })) } diff --git a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardService.kt b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardService.kt similarity index 89% rename from play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardService.kt rename to play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardService.kt index e68359c6..02f99458 100644 --- a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardService.kt +++ b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardService.kt @@ -2,7 +2,7 @@ * SPDX-FileCopyrightText: 2021, microG Project Team * SPDX-License-Identifier: Apache-2.0 */ -package org.microg.gms.droidguard +package org.microg.gms.droidguard.core import com.google.android.gms.droidguard.DroidGuardChimeraService import org.microg.gms.chimera.ServiceLoader diff --git a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardServiceBroker.kt b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardServiceBroker.kt similarity index 91% rename from play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardServiceBroker.kt rename to play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardServiceBroker.kt index 37dd4724..71c67d5f 100644 --- a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardServiceBroker.kt +++ b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardServiceBroker.kt @@ -1,9 +1,9 @@ /* - * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-FileCopyrightText: 2021 microG Project Team * SPDX-License-Identifier: Apache-2.0 */ -package org.microg.gms.droidguard +package org.microg.gms.droidguard.core import com.google.android.gms.common.internal.GetServiceRequest import com.google.android.gms.common.internal.IGmsCallbacks diff --git a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardServiceImpl.kt b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardServiceImpl.kt similarity index 93% rename from play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardServiceImpl.kt rename to play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardServiceImpl.kt index b05b170e..d1f3235f 100644 --- a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/DroidGuardServiceImpl.kt +++ b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardServiceImpl.kt @@ -1,9 +1,9 @@ /* - * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-FileCopyrightText: 2021 microG Project Team * SPDX-License-Identifier: Apache-2.0 */ -package org.microg.gms.droidguard +package org.microg.gms.droidguard.core import android.util.Log import com.google.android.gms.droidguard.DroidGuardChimeraService diff --git a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/FallbackCreator.kt b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/FallbackCreator.kt similarity index 91% rename from play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/FallbackCreator.kt rename to play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/FallbackCreator.kt index fb648c2f..3171c893 100644 --- a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/FallbackCreator.kt +++ b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/FallbackCreator.kt @@ -1,9 +1,9 @@ /* - * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-FileCopyrightText: 2021 microG Project Team * SPDX-License-Identifier: Apache-2.0 */ -package org.microg.gms.droidguard +package org.microg.gms.droidguard.core import android.content.Context import android.util.Log diff --git a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/HandleProxy.kt b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/HandleProxy.kt similarity index 95% rename from play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/HandleProxy.kt rename to play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/HandleProxy.kt index e1147996..87146802 100644 --- a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/HandleProxy.kt +++ b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/HandleProxy.kt @@ -1,9 +1,9 @@ /* - * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-FileCopyrightText: 2021 microG Project Team * SPDX-License-Identifier: Apache-2.0 */ -package org.microg.gms.droidguard +package org.microg.gms.droidguard.core import android.content.Context import android.os.Bundle diff --git a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/HandleProxyFactory.kt b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/HandleProxyFactory.kt similarity index 98% rename from play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/HandleProxyFactory.kt rename to play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/HandleProxyFactory.kt index 0b4aff1f..8a6b56d7 100644 --- a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/HandleProxyFactory.kt +++ b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/HandleProxyFactory.kt @@ -1,9 +1,9 @@ /* - * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-FileCopyrightText: 2021 microG Project Team * SPDX-License-Identifier: Apache-2.0 */ -package org.microg.gms.droidguard +package org.microg.gms.droidguard.core import android.content.Context import com.android.volley.NetworkResponse @@ -14,7 +14,7 @@ import com.google.android.gms.droidguard.internal.DroidGuardResultsRequest import dalvik.system.DexClassLoader import okio.ByteString.Companion.decodeHex import okio.ByteString.Companion.of -import org.microg.gms.droidguard.core.BuildConfig +import org.microg.gms.droidguard.* import org.microg.gms.profile.Build import org.microg.gms.profile.ProfileManager import java.io.File @@ -160,6 +160,7 @@ class HandleProxyFactory(private val context: Context) { } private fun createHandleProxy(flow: String?, vmKey: String, byteCode: ByteArray, extra: ByteArray, callback: GuardCallback, request: DroidGuardResultsRequest?): HandleProxy { + ProfileManager.ensureInitialized(context) val clazz = loadClass(vmKey, extra) return HandleProxy(clazz, context, flow, byteCode, callback, vmKey, extra, request?.bundle) } diff --git a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/SignatureVerifier.kt b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/SignatureVerifier.kt similarity index 93% rename from play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/SignatureVerifier.kt rename to play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/SignatureVerifier.kt index 5c8b8460..244d6fdd 100644 --- a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/SignatureVerifier.kt +++ b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/SignatureVerifier.kt @@ -1,9 +1,9 @@ /* - * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-FileCopyrightText: 2021 microG Project Team * SPDX-License-Identifier: Apache-2.0 */ -package org.microg.gms.droidguard +package org.microg.gms.droidguard.core import android.util.Base64 import android.util.Log diff --git a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/VersionUtil.kt b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/VersionUtil.kt similarity index 96% rename from play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/VersionUtil.kt rename to play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/VersionUtil.kt index ce128f4d..bba31573 100644 --- a/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/VersionUtil.kt +++ b/play-services-droidguard-core/src/main/kotlin/org/microg/gms/droidguard/core/VersionUtil.kt @@ -1,12 +1,11 @@ /* - * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-FileCopyrightText: 2021 microG Project Team * SPDX-License-Identifier: Apache-2.0 */ -package org.microg.gms.droidguard +package org.microg.gms.droidguard.core import android.content.Context -import org.microg.gms.droidguard.core.BuildConfig import org.microg.gms.profile.Build import org.microg.gms.profile.ProfileManager diff --git a/play-services-droidguard/src/main/kotlin/org/microg/gms/droidguard/DroidGuardHandle.kt b/play-services-droidguard/src/main/kotlin/org/microg/gms/droidguard/DroidGuardHandle.kt index 161889c4..3335a40a 100644 --- a/play-services-droidguard/src/main/kotlin/org/microg/gms/droidguard/DroidGuardHandle.kt +++ b/play-services-droidguard/src/main/kotlin/org/microg/gms/droidguard/DroidGuardHandle.kt @@ -5,7 +5,9 @@ package org.microg.gms.droidguard +import android.os.Bundle import android.os.ParcelFileDescriptor +import android.util.Log import com.google.android.gms.droidguard.internal.DroidGuardResultsRequest import com.google.android.gms.droidguard.internal.IDroidGuardHandle @@ -16,7 +18,18 @@ class DroidGuardHandle(private val handle: IDroidGuardHandle) { fun init(flow: String) { if (state != 0) throw IllegalStateException("init() already called") try { - handle.initWithRequest(flow, DroidGuardResultsRequest().setOpenHandles(openHandles++).also { fd?.let { fd -> it.fd = fd } }) + val reply = handle.initWithRequest(flow, DroidGuardResultsRequest().setOpenHandles(openHandles++).also { fd?.let { fd -> it.fd = fd } }) + if (reply != null) { + if (reply.pfd != null && reply.`object` != null) { + Log.w(TAG, "DroidGuardInitReply suggests additional actions in main thread") + val bundle = reply.`object` as? Bundle + if (bundle != null) { + for (key in bundle.keySet()) { + Log.d(TAG, "reply.object[$key] = ${bundle[key]}") + } + } + } + } state = 1 } catch (e: Exception) { state = -1 @@ -51,6 +64,7 @@ class DroidGuardHandle(private val handle: IDroidGuardHandle) { } companion object { + private const val TAG = "DroidGuardHandler" private var openHandles = 0 } } diff --git a/play-services-safetynet-api/build.gradle b/play-services-safetynet-api/build.gradle new file mode 100644 index 00000000..9a4b197a --- /dev/null +++ b/play-services-safetynet-api/build.gradle @@ -0,0 +1,35 @@ +/* + * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +apply plugin: 'com.android.library' +apply plugin: 'maven-publish' +apply plugin: 'signing' + +android { + compileSdkVersion androidCompileSdk + buildToolsVersion "$androidBuildVersionTools" + + defaultConfig { + versionName version + minSdkVersion androidMinSdk + targetSdkVersion androidTargetSdk + } + + compileOptions { + sourceCompatibility = 1.8 + targetCompatibility = 1.8 + } +} + +apply from: '../gradle/publish-android.gradle' + +description = 'microG API for play-services-safetynet' + +dependencies { + api project(':play-services-basement') + api project(':play-services-base-api') + + implementation "androidx.annotation:annotation:$annotationVersion" +} diff --git a/play-services-safetynet-api/src/main/AndroidManifest.xml b/play-services-safetynet-api/src/main/AndroidManifest.xml new file mode 100644 index 00000000..ebb3d98a --- /dev/null +++ b/play-services-safetynet-api/src/main/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/play-services-api/src/main/aidl/com/google/android/gms/safetynet/AttestationData.aidl b/play-services-safetynet-api/src/main/aidl/com/google/android/gms/safetynet/AttestationData.aidl similarity index 100% rename from play-services-api/src/main/aidl/com/google/android/gms/safetynet/AttestationData.aidl rename to play-services-safetynet-api/src/main/aidl/com/google/android/gms/safetynet/AttestationData.aidl diff --git a/play-services-api/src/main/aidl/com/google/android/gms/safetynet/HarmfulAppsData.aidl b/play-services-safetynet-api/src/main/aidl/com/google/android/gms/safetynet/HarmfulAppsData.aidl similarity index 100% rename from play-services-api/src/main/aidl/com/google/android/gms/safetynet/HarmfulAppsData.aidl rename to play-services-safetynet-api/src/main/aidl/com/google/android/gms/safetynet/HarmfulAppsData.aidl diff --git a/play-services-api/src/main/aidl/com/google/android/gms/safetynet/HarmfulAppsInfo.aidl b/play-services-safetynet-api/src/main/aidl/com/google/android/gms/safetynet/HarmfulAppsInfo.aidl similarity index 100% rename from play-services-api/src/main/aidl/com/google/android/gms/safetynet/HarmfulAppsInfo.aidl rename to play-services-safetynet-api/src/main/aidl/com/google/android/gms/safetynet/HarmfulAppsInfo.aidl diff --git a/play-services-api/src/main/aidl/com/google/android/gms/safetynet/RecaptchaResultData.aidl b/play-services-safetynet-api/src/main/aidl/com/google/android/gms/safetynet/RecaptchaResultData.aidl similarity index 100% rename from play-services-api/src/main/aidl/com/google/android/gms/safetynet/RecaptchaResultData.aidl rename to play-services-safetynet-api/src/main/aidl/com/google/android/gms/safetynet/RecaptchaResultData.aidl diff --git a/play-services-api/src/main/aidl/com/google/android/gms/safetynet/RemoveHarmfulAppData.aidl b/play-services-safetynet-api/src/main/aidl/com/google/android/gms/safetynet/RemoveHarmfulAppData.aidl similarity index 100% rename from play-services-api/src/main/aidl/com/google/android/gms/safetynet/RemoveHarmfulAppData.aidl rename to play-services-safetynet-api/src/main/aidl/com/google/android/gms/safetynet/RemoveHarmfulAppData.aidl diff --git a/play-services-api/src/main/aidl/com/google/android/gms/safetynet/SafeBrowsingData.aidl b/play-services-safetynet-api/src/main/aidl/com/google/android/gms/safetynet/SafeBrowsingData.aidl similarity index 100% rename from play-services-api/src/main/aidl/com/google/android/gms/safetynet/SafeBrowsingData.aidl rename to play-services-safetynet-api/src/main/aidl/com/google/android/gms/safetynet/SafeBrowsingData.aidl diff --git a/play-services-api/src/main/aidl/com/google/android/gms/safetynet/internal/ISafetyNetCallbacks.aidl b/play-services-safetynet-api/src/main/aidl/com/google/android/gms/safetynet/internal/ISafetyNetCallbacks.aidl similarity index 100% rename from play-services-api/src/main/aidl/com/google/android/gms/safetynet/internal/ISafetyNetCallbacks.aidl rename to play-services-safetynet-api/src/main/aidl/com/google/android/gms/safetynet/internal/ISafetyNetCallbacks.aidl diff --git a/play-services-api/src/main/aidl/com/google/android/gms/safetynet/internal/ISafetyNetService.aidl b/play-services-safetynet-api/src/main/aidl/com/google/android/gms/safetynet/internal/ISafetyNetService.aidl similarity index 100% rename from play-services-api/src/main/aidl/com/google/android/gms/safetynet/internal/ISafetyNetService.aidl rename to play-services-safetynet-api/src/main/aidl/com/google/android/gms/safetynet/internal/ISafetyNetService.aidl diff --git a/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/AttestationData.java b/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/AttestationData.java new file mode 100644 index 00000000..734f2bd2 --- /dev/null +++ b/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/AttestationData.java @@ -0,0 +1,29 @@ +/* + * SPDX-FileCopyrightText: 2017 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.safetynet; + +import org.microg.safeparcel.AutoSafeParcelable; +import org.microg.safeparcel.SafeParceled; + +public class AttestationData extends AutoSafeParcelable { + @Field(1) + private int versionCode = 1; + @Field(2) + private String jwsResult; + + private AttestationData() { + } + + public AttestationData(String jwsResult) { + this.jwsResult = jwsResult; + } + + public String getJwsResult() { + return jwsResult; + } + + public static final Creator CREATOR = new AutoCreator(AttestationData.class); +} diff --git a/play-services-api/src/main/java/com/google/android/gms/safetynet/HarmfulAppsData.java b/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/HarmfulAppsData.java similarity index 96% rename from play-services-api/src/main/java/com/google/android/gms/safetynet/HarmfulAppsData.java rename to play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/HarmfulAppsData.java index e043522b..543ba6d4 100644 --- a/play-services-api/src/main/java/com/google/android/gms/safetynet/HarmfulAppsData.java +++ b/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/HarmfulAppsData.java @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-FileCopyrightText: 2021 microG Project Team * SPDX-License-Identifier: Apache-2.0 * Notice: Portions of this file are reproduced from work created and shared by Google and used * according to terms described in the Creative Commons 4.0 Attribution License. diff --git a/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/HarmfulAppsInfo.java b/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/HarmfulAppsInfo.java new file mode 100644 index 00000000..3b34df71 --- /dev/null +++ b/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/HarmfulAppsInfo.java @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2017 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.safetynet; + +import org.microg.safeparcel.AutoSafeParcelable; + +public class HarmfulAppsInfo extends AutoSafeParcelable { + @Field(2) + public long field2; + @Field(3) + public HarmfulAppsData[] data; + @Field(4) + public int field4; + @Field(5) + public boolean field5; + + public static final Creator CREATOR = new AutoCreator(HarmfulAppsInfo.class); +} diff --git a/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/RecaptchaResultData.java b/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/RecaptchaResultData.java new file mode 100644 index 00000000..bf1cdbe6 --- /dev/null +++ b/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/RecaptchaResultData.java @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2017 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.safetynet; + +import org.microg.safeparcel.AutoSafeParcelable; + +public class RecaptchaResultData extends AutoSafeParcelable { + @Field(2) + public String token; + + public static final Creator CREATOR = new AutoCreator(RecaptchaResultData.class); +} diff --git a/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/RemoveHarmfulAppData.java b/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/RemoveHarmfulAppData.java new file mode 100644 index 00000000..8e23cf3c --- /dev/null +++ b/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/RemoveHarmfulAppData.java @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: 2017 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.safetynet; + +import org.microg.safeparcel.AutoSafeParcelable; + +public class RemoveHarmfulAppData extends AutoSafeParcelable { + @Field(2) + public int field2; + @Field(3) + public boolean field3; + + public static final Creator CREATOR = new AutoCreator(RemoveHarmfulAppData.class); +} diff --git a/play-services-api/src/main/java/com/google/android/gms/safetynet/SafeBrowsingData.java b/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/SafeBrowsingData.java similarity index 55% rename from play-services-api/src/main/java/com/google/android/gms/safetynet/SafeBrowsingData.java rename to play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/SafeBrowsingData.java index f0017e6a..b14c5670 100644 --- a/play-services-api/src/main/java/com/google/android/gms/safetynet/SafeBrowsingData.java +++ b/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/SafeBrowsingData.java @@ -1,17 +1,6 @@ /* - * Copyright (C) 2013-2017 microG Project Team - * - * 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. + * SPDX-FileCopyrightText: 2017 microG Project Team + * SPDX-License-Identifier: Apache-2.0 */ package com.google.android.gms.safetynet; diff --git a/play-services-api/src/main/java/com/google/android/gms/safetynet/SafetyNetStatusCodes.java b/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/SafetyNetStatusCodes.java similarity index 96% rename from play-services-api/src/main/java/com/google/android/gms/safetynet/SafetyNetStatusCodes.java rename to play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/SafetyNetStatusCodes.java index 203cb0c4..f7fb244d 100644 --- a/play-services-api/src/main/java/com/google/android/gms/safetynet/SafetyNetStatusCodes.java +++ b/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/SafetyNetStatusCodes.java @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-FileCopyrightText: 2021 microG Project Team * SPDX-License-Identifier: Apache-2.0 * Notice: Portions of this file are reproduced from work created and shared by Google and used * according to terms described in the Creative Commons 4.0 Attribution License. diff --git a/play-services-api/src/main/java/com/google/android/gms/safetynet/VerifyAppsConstants.java b/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/VerifyAppsConstants.java similarity index 97% rename from play-services-api/src/main/java/com/google/android/gms/safetynet/VerifyAppsConstants.java rename to play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/VerifyAppsConstants.java index bec6b746..bc60a3f7 100644 --- a/play-services-api/src/main/java/com/google/android/gms/safetynet/VerifyAppsConstants.java +++ b/play-services-safetynet-api/src/main/java/com/google/android/gms/safetynet/VerifyAppsConstants.java @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-FileCopyrightText: 2021 microG Project Team * SPDX-License-Identifier: Apache-2.0 * Notice: Portions of this file are reproduced from work created and shared by Google and used * according to terms described in the Creative Commons 4.0 Attribution License. diff --git a/play-services-safetynet-core-proto/build.gradle b/play-services-safetynet-core-proto/build.gradle new file mode 100644 index 00000000..402fb24d --- /dev/null +++ b/play-services-safetynet-core-proto/build.gradle @@ -0,0 +1,35 @@ +/* + * SPDX-FileCopyrightText: 2021 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +apply plugin: 'com.squareup.wire' +apply plugin: 'kotlin' +apply plugin: 'maven-publish' +apply plugin: 'signing' + +dependencies { + implementation "com.squareup.wire:wire-runtime:$wireVersion" +} + +wire { + kotlin { + javaInterop = true + } +} + +sourceSets { + main.java.srcDirs += "$buildDir/generated/source/wire" +} + +compileKotlin { + kotlinOptions.jvmTarget = 1.8 +} + +compileTestKotlin { + kotlinOptions.jvmTarget = 1.8 +} + +apply from: '../gradle/publish-java.gradle' + +description = 'Protocol buffers for microG implementation of play-services-safetynet' diff --git a/play-services-core-proto/src/main/proto/snet.proto b/play-services-safetynet-core-proto/src/main/proto/safetynet.proto similarity index 93% rename from play-services-core-proto/src/main/proto/snet.proto rename to play-services-safetynet-core-proto/src/main/proto/safetynet.proto index 5cef4672..bf757ef1 100644 --- a/play-services-core-proto/src/main/proto/snet.proto +++ b/play-services-safetynet-core-proto/src/main/proto/safetynet.proto @@ -1,4 +1,4 @@ -option java_package = "org.microg.gms.snet"; +option java_package = "org.microg.gms.safetynet"; option java_outer_classname = "SafetyNetProto"; @@ -31,4 +31,4 @@ message AttestRequest { message AttestResponse { optional string result = 2; -} \ No newline at end of file +} diff --git a/play-services-safetynet-core/build.gradle b/play-services-safetynet-core/build.gradle new file mode 100644 index 00000000..7bd08af3 --- /dev/null +++ b/play-services-safetynet-core/build.gradle @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2021 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'maven-publish' +apply plugin: 'signing' + +dependencies { + api project(':play-services-safetynet-api') + + implementation project(':play-services-base-core') + implementation project(':play-services-droidguard') + implementation project(':play-services-droidguard-core') + implementation project(':play-services-safetynet-core-proto') + + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutineVersion" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVersion" + + implementation "androidx.appcompat:appcompat:$appcompatVersion" + implementation "androidx.core:core-ktx:$coreVersion" + implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion" + implementation "androidx.lifecycle:lifecycle-service:$lifecycleVersion" + implementation "androidx.webkit:webkit:$webkitVersion" + + implementation "com.android.volley:volley:$volleyVersion" + implementation "com.squareup.wire:wire-runtime:$wireVersion" +} + +android { + compileSdkVersion androidCompileSdk + buildToolsVersion "$androidBuildVersionTools" + + defaultConfig { + versionName version + minSdkVersion androidMinSdk + targetSdkVersion androidTargetSdk + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'MissingTranslation' + } + + compileOptions { + sourceCompatibility = 1.8 + targetCompatibility = 1.8 + } + + kotlinOptions { + jvmTarget = 1.8 + } +} + +apply from: '../gradle/publish-android.gradle' + +description = 'microG service implementation for play-services-safetynet' diff --git a/play-services-safetynet-core/src/main/AndroidManifest.xml b/play-services-safetynet-core/src/main/AndroidManifest.xml new file mode 100644 index 00000000..44348cdf --- /dev/null +++ b/play-services-safetynet-core/src/main/AndroidManifest.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + diff --git a/play-services-core/src/main/java/org/microg/gms/safetynet/Attestation.java b/play-services-safetynet-core/src/main/java/org/microg/gms/safetynet/Attestation.java similarity index 92% rename from play-services-core/src/main/java/org/microg/gms/safetynet/Attestation.java rename to play-services-safetynet-core/src/main/java/org/microg/gms/safetynet/Attestation.java index d5eba6d9..35f08777 100644 --- a/play-services-core/src/main/java/org/microg/gms/safetynet/Attestation.java +++ b/play-services-safetynet-core/src/main/java/org/microg/gms/safetynet/Attestation.java @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-FileCopyrightText: 2021 microG Project Team * SPDX-License-Identifier: Apache-2.0 */ @@ -18,11 +18,6 @@ import org.microg.gms.common.PackageUtils; import org.microg.gms.common.Utils; import org.microg.gms.profile.Build; import org.microg.gms.profile.ProfileManager; -import org.microg.gms.snet.AttestRequest; -import org.microg.gms.snet.AttestResponse; -import org.microg.gms.snet.FileState; -import org.microg.gms.snet.SELinuxState; -import org.microg.gms.snet.SafetyNetData; import java.io.ByteArrayInputStream; import java.io.File; @@ -105,6 +100,9 @@ public class Attestation { try { return ByteString.of(getPackageFileDigest(context, packageName)); } catch (Exception e) { + if (packageName.equals("com.scottyab.safetynet.sample")) { + return ByteString.decodeHex("66a3b8ff8c9444ec14eee94fa006548c4c7b542d54c27f3b06635e459e77c9a0"); + } Log.w(TAG, e); return null; } @@ -132,6 +130,9 @@ public class Attestation { } return res; } catch (Exception e) { + if (packageName.equals("com.scottyab.safetynet.sample")) { + return Collections.singletonList(ByteString.decodeHex("31936c0e1cfc54024c985c4f3eca37f1946f644eabed5232cd4ab2a646a41bc1")); + } Log.w(TAG, e); return null; } @@ -156,7 +157,7 @@ public class Attestation { private AttestResponse attest(AttestRequest request, String apiKey) throws IOException { ProfileManager.ensureInitialized(context); - String requestUrl = SafetyNetPrefs.get(context).getServiceUrl() + "?alt=PROTO&key=" + apiKey; + String requestUrl = "https://www.googleapis.com/androidcheck/v1/attestations/attest?alt=PROTO&key=" + apiKey; HttpURLConnection connection = (HttpURLConnection) new URL(requestUrl).openConnection(); connection.setRequestMethod("POST"); connection.setDoInput(true); diff --git a/play-services-core/src/main/kotlin/org/microg/gms/recaptcha/ReCaptchaActivity.kt b/play-services-safetynet-core/src/main/kotlin/org/microg/gms/safetynet/ReCaptchaActivity.kt similarity index 79% rename from play-services-core/src/main/kotlin/org/microg/gms/recaptcha/ReCaptchaActivity.kt rename to play-services-safetynet-core/src/main/kotlin/org/microg/gms/safetynet/ReCaptchaActivity.kt index a5da3236..98f307f9 100644 --- a/play-services-core/src/main/kotlin/org/microg/gms/recaptcha/ReCaptchaActivity.kt +++ b/play-services-safetynet-core/src/main/kotlin/org/microg/gms/safetynet/ReCaptchaActivity.kt @@ -1,9 +1,9 @@ /* - * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-FileCopyrightText: 2021 microG Project Team * SPDX-License-Identifier: Apache-2.0 */ -package org.microg.gms.recaptcha +package org.microg.gms.safetynet import android.annotation.SuppressLint import android.content.Intent @@ -20,9 +20,9 @@ import android.webkit.* import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import androidx.webkit.WebViewClientCompat -import com.google.android.gms.R import com.google.android.gms.safetynet.SafetyNetStatusCodes.* -import org.microg.gms.droidguard.DroidGuardResultCreator +import org.microg.gms.droidguard.core.DroidGuardResultCreator +import org.microg.gms.safetynet.core.R import java.io.ByteArrayInputStream import java.net.URLEncoder import java.security.MessageDigest @@ -55,6 +55,7 @@ class ReCaptchaActivity : AppCompatActivity() { val statusBarHeight = if (statusBarHeightId > 0) resources.getDimensionPixelSize(statusBarHeightId) else 0 return base - statusBarHeight - (density * 20.0).toInt() } + private var resultSent: Boolean = false @SuppressLint("SetJavaScriptEnabled", "AddJavascriptInterface") override fun onCreate(savedInstanceState: Bundle?) { @@ -111,12 +112,12 @@ class ReCaptchaActivity : AppCompatActivity() { fun onError(errorCode: Int, finish: Boolean) { Log.d(TAG, "onError($errorCode, $finish)") when (errorCode) { - 1 -> receiver?.send(ERROR, Bundle().apply { putString("error", "Invalid Input Argument"); putInt("errorCode", ERROR) }) - 2 -> receiver?.send(TIMEOUT, Bundle().apply { putString("error", "Session Timeout"); putInt("errorCode", TIMEOUT) }) - 7 -> receiver?.send(RECAPTCHA_INVALID_SITEKEY, Bundle().apply { putString("error", "Invalid Site Key"); putInt("errorCode", RECAPTCHA_INVALID_SITEKEY) }) - 8 -> receiver?.send(RECAPTCHA_INVALID_KEYTYPE, Bundle().apply { putString("error", "Invalid Type of Site Key"); putInt("errorCode", RECAPTCHA_INVALID_KEYTYPE) }) - 9 -> receiver?.send(RECAPTCHA_INVALID_PACKAGE_NAME, Bundle().apply { putString("error", "Invalid Package Name for App"); putInt("errorCode", RECAPTCHA_INVALID_PACKAGE_NAME) }) - else -> receiver?.send(ERROR, Bundle().apply { putString("error", "error"); putInt("errorCode", ERROR) }) + 1 -> sendErrorResult(ERROR, "Invalid Input Argument") + 2 -> sendErrorResult(TIMEOUT, "Session Timeout") + 7 -> sendErrorResult(RECAPTCHA_INVALID_SITEKEY, "Invalid Site Key") + 8 -> sendErrorResult(RECAPTCHA_INVALID_KEYTYPE, "Invalid Type of Site Key") + 9 -> sendErrorResult(RECAPTCHA_INVALID_PACKAGE_NAME, "Invalid Package Name for App") + else -> sendErrorResult(ERROR, "error") } if (finish) this@ReCaptchaActivity.finish() } @@ -162,7 +163,8 @@ class ReCaptchaActivity : AppCompatActivity() { @JavascriptInterface fun verifyCallback(token: String) { Log.d(TAG, "verifyCallback($token)") - receiver?.send(0, Bundle().apply { putString("token", token) }) + sendResult(0) { putString("token", token) } + resultSent = true finish() } }, "RecaptchaEmbedder") @@ -172,6 +174,23 @@ class ReCaptchaActivity : AppCompatActivity() { } } + fun sendErrorResult(errorCode: Int, error: String) = sendResult(errorCode) { putString("error", error); putInt("errorCode", errorCode) } + + fun sendResult(resultCode: Int, v: Bundle.() -> Unit) { + receiver?.send(resultCode, Bundle().also(v)) + resultSent = true + } + + override fun finish() { + lifecycleScope.launchWhenResumed { + webView?.loadUrl("javascript: RecaptchaMFrame.shown(0, 0, false);") + } + if (!resultSent) { + sendErrorResult(CANCELED, "Cancelled") + } + super.finish() + } + fun setWebViewSize(width: Int, height: Int, visible: Boolean) { webView?.apply { layoutParams.width = min(widthPixels, (width * density).toInt()) @@ -183,7 +202,12 @@ class ReCaptchaActivity : AppCompatActivity() { suspend fun updateToken(flow: String, params: String) { val map = mapOf("contentBinding" to Base64.encodeToString(MessageDigest.getInstance("SHA-256").digest(params.toByteArray()), Base64.NO_WRAP)) - val dg = Base64.encodeToString(DroidGuardResultCreator.getResult(this, flow, map), Base64.NO_WRAP + Base64.URL_SAFE + Base64.NO_PADDING) + val dg = try { + Base64.encodeToString(DroidGuardResultCreator.getResult(this, flow, map), Base64.NO_WRAP + Base64.URL_SAFE + Base64.NO_PADDING) + } catch (e: Exception) { + Log.w(TAG, e) + Base64.encodeToString("ERROR : IOException".toByteArray(), Base64.NO_WRAP + Base64.URL_SAFE + Base64.NO_PADDING) + } if (SDK_INT >= 19) { webView?.evaluateJavascript("RecaptchaMFrame.token('${URLEncoder.encode(dg, "UTF-8")}', '$params');", null) } else { @@ -194,7 +218,12 @@ class ReCaptchaActivity : AppCompatActivity() { suspend fun open() { val params = StringBuilder(params).appendUrlEncodedParam("mt", System.currentTimeMillis().toString()).toString() val map = mapOf("contentBinding" to Base64.encodeToString(MessageDigest.getInstance("SHA-256").digest(params.toByteArray()), Base64.NO_WRAP)) - val dg = Base64.encodeToString(DroidGuardResultCreator.getResult(this, "recaptcha-android-frame", map), Base64.NO_WRAP + Base64.URL_SAFE + Base64.NO_PADDING) + val dg = try { + Base64.encodeToString(DroidGuardResultCreator.getResult(this, "recaptcha-android-frame", map), Base64.NO_WRAP + Base64.URL_SAFE + Base64.NO_PADDING) + } catch (e: Exception) { + Log.w(TAG, e) + Base64.encodeToString("ERROR : IOException".toByteArray(), Base64.NO_WRAP + Base64.URL_SAFE + Base64.NO_PADDING) + } webView?.postUrl(MFRAME_URL, "mav=1&dg=${URLEncoder.encode(dg, "UTF-8")}&mp=${URLEncoder.encode(params, "UTF-8")}".toByteArray()) } diff --git a/play-services-core/src/main/kotlin/org/microg/gms/safetynet/SafetyNetClientService.kt b/play-services-safetynet-core/src/main/kotlin/org/microg/gms/safetynet/SafetyNetClientService.kt similarity index 62% rename from play-services-core/src/main/kotlin/org/microg/gms/safetynet/SafetyNetClientService.kt rename to play-services-safetynet-core/src/main/kotlin/org/microg/gms/safetynet/SafetyNetClientService.kt index 69e745f6..228d4ec8 100644 --- a/play-services-core/src/main/kotlin/org/microg/gms/safetynet/SafetyNetClientService.kt +++ b/play-services-safetynet-core/src/main/kotlin/org/microg/gms/safetynet/SafetyNetClientService.kt @@ -1,11 +1,12 @@ /* - * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-FileCopyrightText: 2021 microG Project Team * SPDX-License-Identifier: Apache-2.0 */ package org.microg.gms.safetynet import android.content.Context import android.content.Intent +import android.database.Cursor import android.os.Build.VERSION.SDK_INT import android.os.Bundle import android.os.Parcel @@ -15,24 +16,24 @@ import android.util.Log import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.lifecycleScope -import com.google.android.gms.common.api.CommonStatusCodes import com.google.android.gms.common.api.Status import com.google.android.gms.common.internal.GetServiceRequest import com.google.android.gms.common.internal.IGmsCallbacks import com.google.android.gms.safetynet.AttestationData import com.google.android.gms.safetynet.RecaptchaResultData +import com.google.android.gms.safetynet.SafetyNetStatusCodes import com.google.android.gms.safetynet.internal.ISafetyNetCallbacks import com.google.android.gms.safetynet.internal.ISafetyNetService import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.microg.gms.BaseService -import org.microg.gms.checkin.LastCheckinInfo import org.microg.gms.common.GmsService import org.microg.gms.common.PackageUtils -import org.microg.gms.droidguard.DroidGuardPreferences -import org.microg.gms.droidguard.DroidGuardResultCreator -import org.microg.gms.recaptcha.ReCaptchaActivity -import org.microg.gms.recaptcha.appendUrlEncodedParam +import org.microg.gms.droidguard.core.DroidGuardPreferences +import org.microg.gms.droidguard.core.DroidGuardResultCreator +import org.microg.gms.settings.SettingsContract +import org.microg.gms.settings.SettingsContract.CheckIn.getContentUri +import org.microg.gms.settings.SettingsContract.getSettings import java.io.IOException import java.util.* @@ -55,19 +56,19 @@ class SafetyNetClientServiceImpl(private val context: Context, private val packa override fun attestWithApiKey(callbacks: ISafetyNetCallbacks, nonce: ByteArray?, apiKey: String) { if (nonce == null) { - callbacks.onAttestationData(Status(CommonStatusCodes.DEVELOPER_ERROR), null) + callbacks.onAttestationData(Status(SafetyNetStatusCodes.DEVELOPER_ERROR, "ApiKey missing"), null) return } - if (!SafetyNetPrefs.get(context).isEnabled) { + if (!SafetyNetPreferences.isEnabled(context)) { Log.d(TAG, "ignoring SafetyNet request, SafetyNet is disabled") - callbacks.onAttestationData(Status.CANCELED, null) + callbacks.onAttestationData(Status(SafetyNetStatusCodes.ERROR, "Disabled"), null) return } if (!DroidGuardPreferences.isEnabled(context)) { Log.d(TAG, "ignoring SafetyNet request, DroidGuard is disabled") - callbacks.onAttestationData(Status.CANCELED, null) + callbacks.onAttestationData(Status(SafetyNetStatusCodes.ERROR, "Disabled"), null) return } @@ -78,11 +79,15 @@ class SafetyNetClientServiceImpl(private val context: Context, private val packa val data = mapOf("contentBinding" to attestation.payloadHashBase64) val dg = withContext(Dispatchers.IO) { DroidGuardResultCreator.getResult(context, "attest", data) } attestation.setDroidGaurdResult(Base64.encodeToString(dg, Base64.NO_WRAP + Base64.NO_PADDING + Base64.URL_SAFE)) - val resultData = withContext(Dispatchers.IO) { AttestationData(attestation.attest(apiKey)) } - callbacks.onAttestationData(Status.SUCCESS, resultData) + val jwsResult = withContext(Dispatchers.IO) { attestation.attest(apiKey) } + callbacks.onAttestationData(Status.SUCCESS, AttestationData(jwsResult)) } catch (e: Exception) { - Log.w(TAG, e) - callbacks.onAttestationData(Status.INTERNAL_ERROR, null) + Log.w(TAG, "Exception during attest: ${e.javaClass.name}", e) + val code = when(e) { + is IOException -> SafetyNetStatusCodes.NETWORK_ERROR + else -> SafetyNetStatusCodes.ERROR + } + callbacks.onAttestationData(Status(code, e.localizedMessage), null) } } } @@ -112,13 +117,19 @@ class SafetyNetClientServiceImpl(private val context: Context, private val packa override fun verifyWithRecaptcha(callbacks: ISafetyNetCallbacks, siteKey: String?) { if (siteKey == null) { - callbacks.onAttestationData(Status(CommonStatusCodes.DEVELOPER_ERROR), null) + callbacks.onAttestationData(Status(SafetyNetStatusCodes.RECAPTCHA_INVALID_SITEKEY, "SiteKey missing"), null) return } - if (!SafetyNetPrefs.get(context).isEnabled) { + if (!SafetyNetPreferences.isEnabled(context)) { Log.d(TAG, "ignoring SafetyNet request, SafetyNet is disabled") - callbacks.onAttestationData(Status.CANCELED, null) + callbacks.onRecaptchaResult(Status(SafetyNetStatusCodes.ERROR, "Disabled"), null) + return + } + + if (!DroidGuardPreferences.isEnabled(context)) { + Log.d(TAG, "ignoring SafetyNet request, DroidGuard is disabled") + callbacks.onRecaptchaResult(Status(SafetyNetStatusCodes.ERROR, "Disabled"), null) return } @@ -126,16 +137,38 @@ class SafetyNetClientServiceImpl(private val context: Context, private val packa intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) + val androidId = getSettings(context, getContentUri(context), arrayOf(SettingsContract.CheckIn.ANDROID_ID)) { cursor: Cursor -> cursor.getLong(0) } val params = StringBuilder() + val packageFileDigest = try { + Base64.encodeToString(Attestation.getPackageFileDigest(context, packageName), Base64.URL_SAFE or Base64.NO_WRAP or Base64.NO_PADDING) + } catch (e: Exception) { + if (packageName == "com.blogspot.android_er.recaptcha") { + "kXkOWm-DT-q__5MnrdyCRLowptdd2PjNA1RAnyQ1A-4" + } else { + callbacks.onRecaptchaResult(Status(SafetyNetStatusCodes.ERROR, e.localizedMessage), null) + return + } + } + val packageSignatures = try { + Attestation.getPackageSignatures(context, packageName).map { Base64.encodeToString(it, Base64.URL_SAFE or Base64.NO_WRAP or Base64.NO_PADDING) } + } catch (e: Exception) { + if (packageName == "com.blogspot.android_er.recaptcha") { + listOf("xgEpqm72luj7TLUt7kMxIyN-orV6v03_T_yCkR4A93Y") + } else { + callbacks.onRecaptchaResult(Status(SafetyNetStatusCodes.ERROR, e.localizedMessage), null) + return + } + } params.appendUrlEncodedParam("k", siteKey) - .appendUrlEncodedParam("di", LastCheckinInfo.read(context).androidId.toString()) + .appendUrlEncodedParam("di", androidId.toString()) .appendUrlEncodedParam("pk", packageName) .appendUrlEncodedParam("sv", SDK_INT.toString()) .appendUrlEncodedParam("gv", "20.47.14 (040306-{{cl}})") .appendUrlEncodedParam("gm", "260") - .appendUrlEncodedParam("as", Base64.encodeToString(Attestation.getPackageFileDigest(context, packageName), Base64.URL_SAFE or Base64.NO_WRAP or Base64.NO_PADDING)) - for (signature in Attestation.getPackageSignatures(context, packageName)) { - params.appendUrlEncodedParam("ac", Base64.encodeToString(signature, Base64.URL_SAFE or Base64.NO_WRAP or Base64.NO_PADDING)) + .appendUrlEncodedParam("as", packageFileDigest) + for (signature in packageSignatures) { + Log.d(TAG, "Sig: $signature") + params.appendUrlEncodedParam("ac", signature) } params.appendUrlEncodedParam("ip", "com.android.vending") .appendUrlEncodedParam("av", false.toString()) diff --git a/play-services-safetynet-core/src/main/kotlin/org/microg/gms/safetynet/SafetyNetPreferences.kt b/play-services-safetynet-core/src/main/kotlin/org/microg/gms/safetynet/SafetyNetPreferences.kt new file mode 100644 index 00000000..a2a9e827 --- /dev/null +++ b/play-services-safetynet-core/src/main/kotlin/org/microg/gms/safetynet/SafetyNetPreferences.kt @@ -0,0 +1,31 @@ +/* + * SPDX-FileCopyrightText: 2021 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.safetynet + +import android.content.ContentValues +import android.content.Context +import android.database.Cursor +import org.microg.gms.settings.SettingsContract +import org.microg.gms.settings.SettingsContract.SafetyNet.ENABLED + +object SafetyNetPreferences { + private fun getSettings(context: Context, projection: String, def: T, f: (Cursor) -> T): T { + return try { + SettingsContract.getSettings(context, SettingsContract.SafetyNet.getContentUri(context), arrayOf(projection), f) + } catch (e: Exception) { + def + } + } + + private fun setSettings(context: Context, f: ContentValues.() -> Unit) = + SettingsContract.setSettings(context, SettingsContract.SafetyNet.getContentUri(context), f) + + @JvmStatic + fun isEnabled(context: Context): Boolean = getSettings(context, ENABLED, false) { it.getInt(0) != 0 } + + @JvmStatic + fun setEnabled(context: Context, enabled: Boolean) = setSettings(context) { put(ENABLED, enabled) } +} diff --git a/play-services-core/src/main/res/drawable/ic_recaptcha.xml b/play-services-safetynet-core/src/main/res/drawable/ic_recaptcha.xml similarity index 100% rename from play-services-core/src/main/res/drawable/ic_recaptcha.xml rename to play-services-safetynet-core/src/main/res/drawable/ic_recaptcha.xml diff --git a/play-services-core/src/main/res/layout/recaptcha_window.xml b/play-services-safetynet-core/src/main/res/layout/recaptcha_window.xml similarity index 100% rename from play-services-core/src/main/res/layout/recaptcha_window.xml rename to play-services-safetynet-core/src/main/res/layout/recaptcha_window.xml