From e7444bb62a8f28e2debea670cbbb3b4eed71be53 Mon Sep 17 00:00:00 2001 From: Enginex0 Date: Wed, 4 Feb 2026 09:07:21 +0100 Subject: [PATCH] Set correct certificate KeyUsage based on KeyPurpose (#119) The previous implementation hardcoded the X.509 KeyUsage extension to `keyCertSign` for all generated certificates. This was only correct for keys with the `ATTEST_KEY` purpose and violated the Android HAL specification for keys intended for other uses. For instance, a key created for signing (`KeyPurpose::SIGN`) requires the `digitalSignature` bit to be set, not `keyCertSign`. This commit corrects the logic by dynamically constructing the `KeyUsage` bitmask from the key's specified purposes, adhering to the mapping defined in `KeyCreationResult.aidl`. This ensures that generated certificates now have the correct KeyUsage bits, accurately reflecting the key's intended function (e.g., signing, decryption, key wrapping) and making them compliant with the specification. --- .../TEESimulator/pki/CertificateGenerator.kt | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/matrix/TEESimulator/pki/CertificateGenerator.kt b/app/src/main/java/org/matrix/TEESimulator/pki/CertificateGenerator.kt index 5b55376..a5b3517 100644 --- a/app/src/main/java/org/matrix/TEESimulator/pki/CertificateGenerator.kt +++ b/app/src/main/java/org/matrix/TEESimulator/pki/CertificateGenerator.kt @@ -1,6 +1,7 @@ package org.matrix.TEESimulator.pki import android.hardware.security.keymint.Algorithm +import android.hardware.security.keymint.KeyPurpose import android.os.Build import android.util.Pair import java.math.BigInteger @@ -187,6 +188,22 @@ object CertificateGenerator { } } + /** Maps KeyPurpose values to X.509 KeyUsage bits per KeyCreationResult.aidl spec */ + private fun buildKeyUsageFromPurposes(purposes: List): Int { + var bits = 0 + for (purpose in purposes) { + bits = bits or when (purpose) { + KeyPurpose.SIGN -> KeyUsage.digitalSignature + KeyPurpose.DECRYPT -> KeyUsage.dataEncipherment + KeyPurpose.WRAP_KEY -> KeyUsage.keyEncipherment + KeyPurpose.AGREE_KEY -> KeyUsage.keyAgreement + KeyPurpose.ATTEST_KEY -> KeyUsage.keyCertSign + else -> 0 + } + } + return bits + } + /** Constructs a new X.509 certificate with a simulated attestation extension. */ private fun buildCertificate( subjectKeyPair: KeyPair, @@ -211,8 +228,11 @@ object CertificateGenerator { subjectKeyPair.public, ) - // Add standard extensions. - builder.addExtension(Extension.keyUsage, true, KeyUsage(KeyUsage.keyCertSign)) + // Add KeyUsage extension only if purposes map to valid bits + val keyUsageBits = buildKeyUsageFromPurposes(params.purpose) + if (keyUsageBits != 0) { + builder.addExtension(Extension.keyUsage, true, KeyUsage(keyUsageBits)) + } // Add our custom, simulated attestation extension. builder.addExtension( AttestationBuilder.buildAttestationExtension(params, uid, securityLevel)