Description
I’m trying to use a hardware TPM (SLB9673 over I²C) as the root of trust for a local Certificate Authority (CA). The key steps are:
Generate a private key inside the TPM (works ).
Persist the key and protect it with a password (works ).
Use the key to sign a self-signed X.509 certificate to act as a CA (fails if the key is protected by a password ).
Issue 1 : OpenSSL provider tpm2 does not support password input
I'm trying to sign a certificate directly using OpenSSL and the TPM key handle:
openssl req \
-provider tpm2 -provider default \
-propquery '?provider=tpm2' \
-new -x509 \
-subj "/C=CH/O=explCompany/CN=tpm_protected_ca2" \
-key handle:0x81010000 \
-days 365 \
-out ca.crt
However, there is no way to specify a password, so even though the key is protected inside the TPM, the user is not prompted for a password, defeating the purpose.
If i create the key without password, I'm able to create the certificate and later on use it to sign CSR.
Issue 2 : certify_x509 not supported by TPM
When using the certify_x509() method from tpm2-pytss, I get the following error:
TSS2_Exception: rmt:error(2.0): command code not supported
This happens on the following code:
key_handle = tpm.tr_from_tpmpublic(certificatConfig.get("TPM_HANDLE"))
session1 = ESYS_TR.PASSWORD
partial_der = build_partial_certificate(certificatConfig)
partial_cert = TPM2B_MAX_BUFFER(partial_der)
scheme = TPMT_SIG_SCHEME(scheme=TPM2_ALG.RSASSA)
scheme.details.rsassa.hashAlg = TPM2_ALG.SHA256
password = getpass.getpass(prompt="Enter password : ")
tpm.tr_set_auth(key_handle, password.encode())
added2cert, tbs_digest, sig = tpm.certify_x509(
object_handle = key_handle,
sign_handle = key_handle,
partial_certificate = partial_cert,
in_scheme = scheme,
session1 = session1,
)
full_tbs = partial_der + added2cert.buffer
tbs = asn1x509.TbsCertificate.load(full_tbs)
sig_alg = asn1x509.SignedDigestAlgorithm(
{"algorithm": "sha256_rsa"} # asn1crypto lève l’OID correct
)
raw_sig = bytes(sig.signature.rsassa.sig.buffer)
sig_bs = core.BitString.load(
b"\x03" +
core._encode_length(len(raw_sig) + 1) + # tag=3, longueur = sig+1
b"\x00" + # unused bits = 0
raw_sig
)
cert = asn1x509.Certificate({
"tbs_certificate": tbs,
"signature_algorithm": sig_alg,
"signature_value": sig_bs
})
pem = cert.public_bytes(encoding="pem").decode()
with open("ca_cert_from_tpm.crt", "w") as f:
f.write(pem)
print("Certificat CA TPM généré dans ca_cert_from_tpm.crt")
From what I understand, my TPM (Infineon SLB9673) does not support TPM2_CC_CertifyX509.
Firmware info (via tpm2_getcap properties-fixed):
TPM2_PT_FIRMWARE_VERSION_1: 0x1A000D
TPM2_PT_FIRMWARE_VERSION_2: 0x456A00
Questions
Is there a list of TPM models or firmware versions that support TPM2_CC_CertifyX509?
Is there a known alternative method to sign a certificate with a password-protected TPM key ?
Environment
TPM: Infineon SLB9673 (I²C)
OS: TorizonCore (Debian-based)
Python: 3.11
tpm2-pytss: Installed via git+https://github.com/tpm2-software/tpm2-pytss.git
TPM2-Tools: Installed and working
OpenSSL: Built with provider support (tpm2 and default)
Any advice or workaround would be very helpful! Thanks for the awesome work on the TPM2 software stack.