java: CertHack: Honour StrongBox security level when requested in generate mode (#20)

This commit is contained in:
Nicholas Bissell
2025-08-17 12:29:09 +05:30
committed by GitHub
parent 7410315701
commit 095b32554b
2 changed files with 16 additions and 13 deletions
@@ -505,11 +505,11 @@ object CertificateHacker {
Logger.e("Failed to generate key pair", it)
}.getOrNull()
fun generateChain(uid: Int, params: KeyGenParameters, keyPair: KeyPair): List<ByteArray>? = runCatching {
fun generateChain(uid: Int, params: KeyGenParameters, keyPair: KeyPair, securityLevel: Int = 1): List<ByteArray>? = runCatching {
val keybox = getKeyboxForAlgorithm(params.algorithm) ?: return null
val issuer = X509CertificateHolder(keybox.certificates[0].encoded).subject
val leaf = buildCertificate(keyPair, keybox, params, issuer, uid)
val leaf = buildCertificate(keyPair, keybox, params, issuer, uid, securityLevel)
val chain = buildList {
add(leaf)
@@ -525,7 +525,8 @@ object CertificateHacker {
uid: Int,
descriptor: KeyDescriptor,
attestKeyDescriptor: KeyDescriptor?,
params: KeyGenParameters
params: KeyGenParameters,
securityLevel: Int = 1
): Pair<KeyPair, List<Certificate>>? = runCatching {
Logger.i("Requested KeyPair with alias: ${descriptor.alias}")
@@ -545,7 +546,7 @@ object CertificateHacker {
keybox.keyPair to X509CertificateHolder(keybox.certificates[0].encoded).subject
}
val leaf = buildCertificate(keyPair, keybox, params, issuer, uid, signingKeyPair)
val leaf = buildCertificate(keyPair, keybox, params, issuer, uid, securityLevel, signingKeyPair)
val chain = buildList {
add(leaf)
if (!hasAttestKey) {
@@ -655,6 +656,7 @@ object CertificateHacker {
params: KeyGenParameters,
issuer: X500Name,
uid: Int,
securityLevel: Int = 1,
signingKeyPair: KeyPair = keybox.keyPair
): Certificate {
val builder = JcaX509v3CertificateBuilder(
@@ -667,7 +669,7 @@ object CertificateHacker {
)
builder.addExtension(Extension.keyUsage, true, KeyUsage(KeyUsage.keyCertSign))
builder.addExtension(createAttestationExtension(params, uid))
builder.addExtension(createAttestationExtension(params, uid, securityLevel))
val signerAlgorithm = when (params.algorithm) {
Algorithm.EC -> "SHA256withECDSA"
@@ -679,7 +681,7 @@ object CertificateHacker {
return JcaX509CertificateConverter().getCertificate(builder.build(contentSigner))
}
private fun createAttestationExtension(params: KeyGenParameters, uid: Int): Extension {
private fun createAttestationExtension(params: KeyGenParameters, uid: Int, securityLevel: Int = 1): Extension {
try {
val key = bootKey
val hash = bootHash
@@ -751,7 +753,7 @@ object CertificateHacker {
return Extension(
ATTESTATION_OID,
false,
getAsn1OctetString(teeEnforcedObjects.toTypedArray(), softwareEnforcedObjects, params)
getAsn1OctetString(teeEnforcedObjects.toTypedArray(), softwareEnforcedObjects, params, securityLevel)
)
} catch (t: Throwable) {
Logger.e("Failed to create attestation extension", t)
@@ -764,12 +766,13 @@ object CertificateHacker {
private fun getAsn1OctetString(
teeEnforcedEncodables: Array<ASN1Encodable>,
softwareEnforcedEncodables: Array<ASN1Encodable>,
params: KeyGenParameters
params: KeyGenParameters,
securityLevel: Int = 1
): ASN1OctetString {
val attestationVersion = ASN1Integer(io.github.beakthoven.TrickyStoreOSS.attestVersion.toLong())
val attestationSecurityLevel = ASN1Enumerated(1)
val attestationSecurityLevel = ASN1Enumerated(securityLevel)
val keymasterVersion = ASN1Integer(io.github.beakthoven.TrickyStoreOSS.keymasterVersion.toLong())
val keymasterSecurityLevel = ASN1Enumerated(1)
val keymasterSecurityLevel = ASN1Enumerated(securityLevel)
val attestationChallenge = DEROctetString(params.attestationChallenge ?: ByteArray(0))
val uniqueId = DEROctetString(ByteArray(0))
val softwareEnforced = DERSequence(softwareEnforcedEncodables)
@@ -82,7 +82,7 @@ class SecurityLevelInterceptor(
val entropy = data.createByteArray()
val kgp = CertificateHacker.KeyGenParameters(params)
if (Config.needGenerate(callingUid)) {
val pair = CertificateHacker.generateKeyPair(callingUid, keyDescriptor, attestationKeyDescriptor, kgp)
val pair = CertificateHacker.generateKeyPair(callingUid, keyDescriptor, attestationKeyDescriptor, kgp, level)
?: return@runCatching
keyPairs[Key(callingUid, keyDescriptor.alias)] = Pair(pair.first, pair.second)
val response = buildResponse(pair.second, kgp, attestationKeyDescriptor ?: keyDescriptor)
@@ -94,7 +94,7 @@ class SecurityLevelInterceptor(
} else if (Config.needHack(callingUid)) {
if ((kgp.purpose.contains(7)) || (attestationKeyDescriptor != null)) {
Logger.i("Generating key in generation mode for attestation: uid=$callingUid alias=${keyDescriptor.alias}")
val pair = CertificateHacker.generateKeyPair(callingUid, keyDescriptor, attestationKeyDescriptor, kgp)
val pair = CertificateHacker.generateKeyPair(callingUid, keyDescriptor, attestationKeyDescriptor, kgp, level)
?: return@runCatching
keyPairs[Key(callingUid, keyDescriptor.alias)] = Pair(pair.first, pair.second)
val response = buildResponse(pair.second, kgp, attestationKeyDescriptor ?: keyDescriptor)