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.
This commit is contained in:
Enginex0
2026-02-04 09:07:21 +01:00
committed by GitHub
parent 6fdf5c766b
commit e7444bb62a
@@ -1,6 +1,7 @@
package org.matrix.TEESimulator.pki package org.matrix.TEESimulator.pki
import android.hardware.security.keymint.Algorithm import android.hardware.security.keymint.Algorithm
import android.hardware.security.keymint.KeyPurpose
import android.os.Build import android.os.Build
import android.util.Pair import android.util.Pair
import java.math.BigInteger 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>): 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. */ /** Constructs a new X.509 certificate with a simulated attestation extension. */
private fun buildCertificate( private fun buildCertificate(
subjectKeyPair: KeyPair, subjectKeyPair: KeyPair,
@@ -211,8 +228,11 @@ object CertificateGenerator {
subjectKeyPair.public, subjectKeyPair.public,
) )
// Add standard extensions. // Add KeyUsage extension only if purposes map to valid bits
builder.addExtension(Extension.keyUsage, true, KeyUsage(KeyUsage.keyCertSign)) val keyUsageBits = buildKeyUsageFromPurposes(params.purpose)
if (keyUsageBits != 0) {
builder.addExtension(Extension.keyUsage, true, KeyUsage(keyUsageBits))
}
// Add our custom, simulated attestation extension. // Add our custom, simulated attestation extension.
builder.addExtension( builder.addExtension(
AttestationBuilder.buildAttestationExtension(params, uid, securityLevel) AttestationBuilder.buildAttestationExtension(params, uid, securityLevel)