You've already forked TrickyStore
mirror of
https://github.com/5ec1cff/TrickyStore.git
synced 2025-09-06 06:37:07 +00:00
test: forward play certificate chain to key attestation app
This commit is contained in:
@@ -3,6 +3,7 @@ package io.github.a13e300.tricky_store
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.pm.IPackageManager
|
import android.content.pm.IPackageManager
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
|
import android.os.IBinder.DeathRecipient
|
||||||
import android.os.Parcel
|
import android.os.Parcel
|
||||||
import android.os.ServiceManager
|
import android.os.ServiceManager
|
||||||
import android.system.keystore2.IKeystoreService
|
import android.system.keystore2.IKeystoreService
|
||||||
@@ -10,6 +11,7 @@ import android.system.keystore2.KeyEntryResponse
|
|||||||
import io.github.a13e300.tricky_store.binder.BinderInterceptor
|
import io.github.a13e300.tricky_store.binder.BinderInterceptor
|
||||||
import io.github.a13e300.tricky_store.keystore.CertHack
|
import io.github.a13e300.tricky_store.keystore.CertHack
|
||||||
import io.github.a13e300.tricky_store.keystore.Utils
|
import io.github.a13e300.tricky_store.keystore.Utils
|
||||||
|
import java.security.cert.Certificate
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
@SuppressLint("BlockedPrivateApi")
|
@SuppressLint("BlockedPrivateApi")
|
||||||
@@ -37,12 +39,24 @@ object KeystoreInterceptor : BinderInterceptor() {
|
|||||||
Logger.d("intercept pre $target uid=$callingUid pid=$callingPid dataSz=${data.dataSize()}")
|
Logger.d("intercept pre $target uid=$callingUid pid=$callingPid dataSz=${data.dataSize()}")
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
val ps = getPm()?.getPackagesForUid(callingUid)
|
val ps = getPm()?.getPackagesForUid(callingUid)
|
||||||
|
if (ps?.contains("com.google.android.gms") == true) {
|
||||||
|
gmsUid = callingUid
|
||||||
|
Logger.d("gms uid $gmsUid")
|
||||||
|
}
|
||||||
|
if (ps?.contains("io.github.vvb2060.keyattestation") == true) {
|
||||||
|
kaUid = callingUid
|
||||||
|
Logger.d("ka uid $kaUid")
|
||||||
|
}
|
||||||
if (ps?.any { it in Config.targetPackages } == true) return Continue
|
if (ps?.any { it in Config.targetPackages } == true) return Continue
|
||||||
}.onFailure { Logger.e("failed to get packages", it) }
|
}.onFailure { Logger.e("failed to get packages", it) }
|
||||||
}
|
}
|
||||||
return Skip
|
return Skip
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var playCertificates: Array<Certificate>? = null
|
||||||
|
private var gmsUid = 0
|
||||||
|
private var kaUid = 0
|
||||||
|
|
||||||
override fun onPostTransact(
|
override fun onPostTransact(
|
||||||
target: IBinder,
|
target: IBinder,
|
||||||
code: Int,
|
code: Int,
|
||||||
@@ -61,7 +75,14 @@ object KeystoreInterceptor : BinderInterceptor() {
|
|||||||
val response = reply.readTypedObject(KeyEntryResponse.CREATOR)
|
val response = reply.readTypedObject(KeyEntryResponse.CREATOR)
|
||||||
val chain = Utils.getCertificateChain(response)
|
val chain = Utils.getCertificateChain(response)
|
||||||
if (chain != null) {
|
if (chain != null) {
|
||||||
val newChain = CertHack.engineGetCertificateChain(chain)
|
val newChain = if (callingUid == kaUid && playCertificates != null) {
|
||||||
|
Logger.d("send play certificates to ka!")
|
||||||
|
playCertificates
|
||||||
|
} else CertHack.engineGetCertificateChain(chain)
|
||||||
|
if (callingUid == gmsUid && CertHack.hasAttestation(chain)) {
|
||||||
|
Logger.d("get play certificates!")
|
||||||
|
playCertificates = newChain
|
||||||
|
}
|
||||||
Utils.putCertificateChain(response, newChain)
|
Utils.putCertificateChain(response, newChain)
|
||||||
p.writeNoException()
|
p.writeNoException()
|
||||||
p.writeTypedObject(response, 0)
|
p.writeTypedObject(response, 0)
|
||||||
@@ -99,10 +120,14 @@ object KeystoreInterceptor : BinderInterceptor() {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
registerBinderInterceptor(bd, b, this)
|
registerBinderInterceptor(bd, b, this)
|
||||||
b.linkToDeath({
|
b.linkToDeath(Killer, 0)
|
||||||
Logger.d("keystore exit, daemon restart")
|
|
||||||
exitProcess(0)
|
|
||||||
}, 0)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object Killer : DeathRecipient {
|
||||||
|
override fun binderDied() {
|
||||||
|
Logger.d("keystore exit, daemon restart")
|
||||||
|
exitProcess(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,6 +111,17 @@ public final class CertHack {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean hasAttestation(Certificate[] caList) {
|
||||||
|
if (caList == null) return false;
|
||||||
|
try {
|
||||||
|
X509Certificate leaf = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(caList[0].getEncoded()));
|
||||||
|
byte[] bytes = leaf.getExtensionValue(OID.getId());
|
||||||
|
return bytes != null;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Certificate[] engineGetCertificateChain(Certificate[] caList) {
|
public static Certificate[] engineGetCertificateChain(Certificate[] caList) {
|
||||||
if (caList == null) throw new UnsupportedOperationException("caList is null!");
|
if (caList == null) throw new UnsupportedOperationException("caList is null!");
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user