Identity quote failure when using TPM devices with manufacturer certificates signed by ECC keys
See original GitHub issueEnvironment
- OS / version: OpenBMC Yocto “phosphor”, Ubuntu 20.04, Ubuntu 22.04
- Processor architecture: ARM cortex A7, AMD x86_64 (mostly irrelevant)
- TPM Manufacturer: Nuvoton TPM signed by
NUVO_1111.pem
, but reproducible with swtpm. - Keylime version: 6.4.0, but problem is reproducible with current master branch (Aug 8 2022)
Description
During the initial identity quote at the start of attestation the function tpm_main.verify_ek()
is invoked by the keylime tenant to ensure that the TPM device on the agent is genuine. The process involves listing all the manufacturer certificates in the tpm_cert_store
directory, finding one that has an Issuer that matches the EK cert’s, and then running verify().
When the manufacturer certificate signature algorithm is EC(*) the verify() function call fails, resulting in attestation failure.
Expected behavior vs. actual behavior
- Expected behavior: a Nuvoton device certified by the file keylime/tmp_cert_store/NUVO0_1111.pem should work.
- Actual behavior: said Nuvoton TPM device will never result in successful attestation, because the NUVO_1111.pem file is signed with an ECC key. The following error is generated during the identity quote phase by the tenant:
2022-08-09 14:43:15.313 - keylime.tpm - ERROR - verify() takes 4 positional arguments but 5 were given
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/keylime-6.4.0-py3.9.egg/keylime/tpm/tpm_main.py", line 857, in verify_ek
signcert.public_key().verify(
TypeError: verify() takes 4 positional arguments but 5 were given
Steps to reproduce problem
1A. Install keylime attestation on any system with a Nuvoton chip that is certified by the NUVO_1111.pem file.
1B. Alternatively, create a swtpm instance in which the manufacturer cert is signed by an ECC key.
2. Start the keylime agent and let it register. Registration should execute normally.
3. Attempt to start attestation with the keylime_tenant -c add
command. Expect the error message above to show up.
Root cause analysis
The problem is with the following sequence in the TPM code (keylime/tpm/tpm_main.py
):
signcert.public_key().verify(
ek509.signature,
ek509.tbs_certificate_bytes,
padding.PKCS1v15(),
ek509.signature_hash_algorithm,
)
The call to the verify() method makes an assumption that (including “self”) 5 arguments are needed. But on elliptic curve public keys only 4 arguments are expected (there is no padding).
-
Abstract method signature for RSA public keys: https://github.com/pyca/cryptography/blob/6b63cd56c746150ff49fdfe38c422523afaf21b8/src/cryptography/hazmat/primitives/asymmetric/rsa.py#L98-L104
-
Abstract method signature for ECC public keys: https://github.com/pyca/cryptography/blob/6b63cd56c746150ff49fdfe38c422523afaf21b8/src/cryptography/hazmat/primitives/asymmetric/ec.py#L153-L158
This discrepancy causes the problem.
Proposed (tentative) fix
Insert an if statement to handle the different verify() method signatures in python cryptography.
Issue Analytics
- State:
- Created a year ago
- Comments:9 (9 by maintainers)
Top GitHub Comments
@THS-on: yep. @kkaarreell is adding a test for this in #1175
@sergio-correia is this now fully fixed?