fix: return full keybox chain when BYO attest key misses

CertificateGenerator.generateCertificateChain selected
keybox.keyPair as fallback signer when getAttestationKeyInfo returned
null, but the chain assembly at line 115 still keyed on
"attestKeyAlias != null" and returned only listOf(leafCert). The
caller received a depth-1 chain signed by the keybox root with no
parent attached — structurally invalid.

Track whether the BYO lookup actually returned a key. On hit return
the depth-1 chain (caller holds the rest). On miss include
keybox.certificates so the chain is rooted.

Surfaced by adversarial audit of 66a8c7f, which broadened the
software-dispatch gate to all attestationKey != null requests.
Without this companion fix the miss path produces a malformed chain
where the previous code would have forwarded to HAL.
This commit is contained in:
Enginex0
2026-05-20 03:58:20 +01:00
parent 95b8c27a9f
commit 240728f98d
@@ -101,18 +101,19 @@ object CertificateGenerator {
val keybox = getKeyboxForAlgorithm(uid, params.algorithm)
val (signingKey, issuer) =
val attestKeyInfo =
if (attestKeyAlias != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
getAttestationKeyInfo(uid, attestKeyAlias)?.let { it.first to it.second }
?: (keybox.keyPair to getIssuerFromKeybox(keybox))
} else {
keybox.keyPair to getIssuerFromKeybox(keybox)
}
getAttestationKeyInfo(uid, attestKeyAlias)
} else null
val (signingKey, issuer) = attestKeyInfo
?.let { it.first to it.second }
?: (keybox.keyPair to getIssuerFromKeybox(keybox))
val leafCert =
buildCertificate(subjectKeyPair, signingKey, issuer, params, uid, securityLevel)
if (attestKeyAlias != null) {
if (attestKeyInfo != null) {
listOf(leafCert)
} else {
listOf(leafCert) + keybox.certificates