[PATCH] efi_loader: explicitly return EFI_UNSUPPORTED for TCG 1.0 compatibility

Stuart Yoder stuart.yoder at arm.com
Wed May 31 18:41:08 CEST 2023



On 5/31/23 2:48 AM, Ilias Apalodimas wrote:
> Hi Stuart,
> 
> On Wed, 31 May 2023 at 00:20, Stuart Yoder <stuart.yoder at arm.com> wrote:
>>
>>
>>
>> On 5/30/23 1:39 AM, Ilias Apalodimas wrote:
>>> In the EFI TCG spec EFI_TCG2_BOOT_SERVICE_CAPABILITY struct is
>>> versioned -- there are 1.0 and 1.1 versions of that struct.
>>> The spec [0] describes:
>>> "Version of the EFI_TCG2_BOOT_SERVICE_CAPABILITY
>>> structure itself. For this version of the protocol, the Major version
>>> SHALL be set to 1 and the Minor version SHALL be set to 1."
>>> which is what we currently support.
>>>
>>> The SCT tests perfromed By Arms SIE(Security interface extensions) [1]
>>> perform a check for clients supporting the older 1.0 version of the
>>> spec (Test 30.1.1.4). Given than this spec is 7 years old,  there should
>>> be no need for the older 1.0 version support.  Instead of returning
>>> EFI_BUFFER_TOO_SMALLL switch to EFI_UNSUPPORTED which is more
>>> appropriate.  It's worth noting that the spec doesn't explicitly
>>> describe the return value at the moment.
>>>
>>> [0] https://trustedcomputinggroup.org/wp-content/uploads/EFI-Protocol-Specification-rev13-160330final.pdf
>>> [1] https://github.com/stuyod01/edk2-test/blob/master/uefi-sct/Doc/UEFI-SCT-Case-Spec/30_Protocols_TCG2_Test.md
>>>
>>> Signed-off-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>
>>> ---
>>>
>>> Heinrich,  Stuart is investigating the chance of the spec getting updated
>>> adding EFI_UNSUPPORTED.  In any case I think the patch should be aplied since
>>> the new return code makes more sense.  If for some reason the spec change is
>>> rejected, I can go back and add support for 1.0 structure versions.
>>>
>>>    lib/efi_loader/efi_tcg2.c | 2 +-
>>>    1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
>>> index a83ae7a46cf3..220c442bdf93 100644
>>> --- a/lib/efi_loader/efi_tcg2.c
>>> +++ b/lib/efi_loader/efi_tcg2.c
>>> @@ -750,7 +750,7 @@ efi_tcg2_get_capability(struct efi_tcg2_protocol *this,
>>>
>>>        if (capability->size < sizeof(*capability)) {
>>>                capability->size = sizeof(*capability);
>>> -             efi_ret = EFI_BUFFER_TOO_SMALL;
>>> +             efi_ret = EFI_UNSUPPORTED;
>>>                goto out;
>>>        }
>>
>> Hi Ilias,
>>
>> I don't think this is the right fix.
>>
>> The struct looks like this:
>>
>> struct tdEFI_TCG2_BOOT_SERVICE_CAPABILITY {
>>     UINT8 Size;
>>     EFI_TCG2_VERSION StructureVersion;
>>     EFI_TCG2_VERSION ProtocolVersion;
>>     EFI_TCG2_EVENT_ALGORITHM_BITMAP HashAlgorithmBitmap
>>     EFI_TCG2_EVENT_LOG_BITMAP SupportedEventLogs
>>     BOOLEAN TPMPresentFlag
>>     UINT16 MaxCommandSize
>>     UINT16 MaxResponseSize
>>     UINT32 ManufacturerID
>>     UINT32 NumberOfPcrBanks
>>     EFI_TCG2_EVENT_ALGORITHM_BITMAP ActivePcrBanks
>> };
>>
>> The intent in the TCG spec is for the caller to be able to
>> determine the size of the struct by passing in a small
>> buffer (e.g. 1 byte buffer), and then the firmware
>> should return sizeof(EFI_TCG2_BOOT_SERVICE_CAPABILITY) in the
>> 1-byte "Size" field.  And the return value should be
>> EFI_BUFFER_TOO_SMALL as per the spec.
>>
>> In order to detect a 1.0 client, which you don't want to support,
>> I think you need a _new_ check that is something like this:
>>
>> // detect 1.0 client
>> if (capability->size < sizeof(*capability) &&
>>       capability->size >= offsetof(EFI_TCG2_BOOT_SERVICE_CAPABILITY,
>> NumberOfPcrBanks)) {
>>       efi_ret = EFI_UNSUPPORTED;
>>       goto out;
>> }
>>
>> The last field in the 1.0 struct was ManufacturerID, so you should
>> be able to detect 1.0 clients that expect that based on the size they
>> pass in.
> 
> The patch doesn't show the entire u-boot code there and is a bit misleading.
> There's another check that precedes the one I am patching, which if I
> am reading it correctly does exactly what you describe
> 
> #define BOOT_SERVICE_CAPABILITY_MIN \
>            offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks)
> if (capability->size < BOOT_SERVICE_CAPABILITY_MIN) {
>            capability->size = BOOT_SERVICE_CAPABILITY_MIN;
>            efi_ret = EFI_BUFFER_TOO_SMALL;
>            goto out;
> }

I took a look at the u-boot code.  What I think we want is this:

diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index b1c3abd097..6a46d9e51c 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -126,7 +126,7 @@ struct efi_tcg2_boot_service_capability {
  };

  /* up to and including the vendor ID (manufacturer_id) field */
-#define BOOT_SERVICE_CAPABILITY_MIN \
+#define BOOT_SERVICE_CAPABILITY_1_0 \
         offsetof(struct efi_tcg2_boot_service_capability, 
number_of_pcr_banks)

  #define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index a83ae7a46c..d37b896b7e 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -742,15 +742,15 @@ efi_tcg2_get_capability(struct efi_tcg2_protocol 
*this,
                 goto out;
         }

-       if (capability->size < BOOT_SERVICE_CAPABILITY_MIN) {
-               capability->size = BOOT_SERVICE_CAPABILITY_MIN;
+       if (capability->size < BOOT_SERVICE_CAPABILITY_1_0) {
+               capability->size = sizeof(*capability);
                 efi_ret = EFI_BUFFER_TOO_SMALL;
                 goto out;
         }

         if (capability->size < sizeof(*capability)) {
                 capability->size = sizeof(*capability);
-               efi_ret = EFI_BUFFER_TOO_SMALL;
+               efi_ret = EFI_UNSUPPORTED;
                 goto out;
         }

That is:

-if the passed in size is less than the 1.0 struct size
  then return sizeof() the full struct.  This allows
  client to query and determine the supported struct
  size

-to detect and reject 1.0 clients, if the passed in
  size is >= 1.0 struct size AND less than sizeof(*capability)
  then return EFI_UNSUPPORTED

Does that make sense?

Thanks,
Stuart


More information about the U-Boot mailing list