[v2,2/2] efi/libstub: Add get_event_log() support for CC platforms
Commit Message
To allow event log info access after boot, EFI boot stub extracts
the event log information and installs it in an EFI configuration
table. Currently, EFI boot stub only supports installation of event
log only for TPM 1.2 and TPM 2.0 protocols. Extend the same support
for CC protocol. Since CC platform also uses TCG2 format, reuse TPM2
support code as much as possible.
Link: https://uefi.org/specs/UEFI/2.10/38_Confidential_Computing.html#efi-cc-measurement-protocol [1]
Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
---
drivers/firmware/efi/libstub/efi-stub.c | 2 +-
drivers/firmware/efi/libstub/efistub.h | 4 +-
drivers/firmware/efi/libstub/tpm.c | 78 +++++++++++++++++--------
drivers/firmware/efi/libstub/x86-stub.c | 2 +-
include/linux/efi.h | 3 +
5 files changed, 61 insertions(+), 28 deletions(-)
Comments
On Thu, 15 Feb 2024 at 05:02, Kuppuswamy Sathyanarayanan
<sathyanarayanan.kuppuswamy@linux.intel.com> wrote:
>
> To allow event log info access after boot, EFI boot stub extracts
> the event log information and installs it in an EFI configuration
> table. Currently, EFI boot stub only supports installation of event
> log only for TPM 1.2 and TPM 2.0 protocols. Extend the same support
> for CC protocol. Since CC platform also uses TCG2 format, reuse TPM2
> support code as much as possible.
>
> Link: https://uefi.org/specs/UEFI/2.10/38_Confidential_Computing.html#efi-cc-measurement-protocol [1]
> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
[...]
> +void efi_retrieve_eventlog(void)
> +{
> + efi_physical_addr_t log_location = 0, log_last_entry = 0;
> + efi_guid_t cc_guid = EFI_CC_MEASUREMENT_PROTOCOL_GUID;
> + efi_guid_t tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
> + int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
> + efi_tcg2_protocol_t *tpm2 = NULL;
> + efi_cc_protocol_t *cc = NULL;
> + efi_bool_t truncated;
> + efi_status_t status;
> +
> + status = efi_bs_call(locate_protocol, &tpm2_guid, NULL, (void **)&tpm2);
> + if (status == EFI_SUCCESS) {
> + status = efi_call_proto(tpm2, get_event_log, version, &log_location,
> + &log_last_entry, &truncated);
> +
> + if (status != EFI_SUCCESS || !log_location) {
> + version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
> + status = efi_call_proto(tpm2, get_event_log, version,
> + &log_location, &log_last_entry,
> + &truncated);
> + if (status != EFI_SUCCESS || !log_location)
> + return;
> + }
> +
> + efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
> + truncated);
> + return;
> + }
> +
> + status = efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);
> + if (status == EFI_SUCCESS) {
> + version = EFI_CC_EVENT_LOG_FORMAT_TCG_2;
> + status = efi_call_proto(cc, get_event_log, version, &log_location,
> + &log_last_entry, &truncated);
> + if (status != EFI_SUCCESS || !log_location)
> + return;
> +
> + efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
> + truncated);
> + return;
> + }
> +}
[...]
I haven't looked into CC measurements much, but do we always want to
prioritize the tcg2 protocol? IOW if you have firmware that implements
both, shouldn't we prefer the CC protocol for VMs?
Thanks
/Ilias
Hi Ilias,
On 2/18/24 11:03 PM, Ilias Apalodimas wrote:
> On Thu, 15 Feb 2024 at 05:02, Kuppuswamy Sathyanarayanan
> <sathyanarayanan.kuppuswamy@linux.intel.com> wrote:
>> To allow event log info access after boot, EFI boot stub extracts
>> the event log information and installs it in an EFI configuration
>> table. Currently, EFI boot stub only supports installation of event
>> log only for TPM 1.2 and TPM 2.0 protocols. Extend the same support
>> for CC protocol. Since CC platform also uses TCG2 format, reuse TPM2
>> support code as much as possible.
>>
>> Link: https://uefi.org/specs/UEFI/2.10/38_Confidential_Computing.html#efi-cc-measurement-protocol [1]
>> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
> [...]
>
>> +void efi_retrieve_eventlog(void)
>> +{
>> + efi_physical_addr_t log_location = 0, log_last_entry = 0;
>> + efi_guid_t cc_guid = EFI_CC_MEASUREMENT_PROTOCOL_GUID;
>> + efi_guid_t tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
>> + int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
>> + efi_tcg2_protocol_t *tpm2 = NULL;
>> + efi_cc_protocol_t *cc = NULL;
>> + efi_bool_t truncated;
>> + efi_status_t status;
>> +
>> + status = efi_bs_call(locate_protocol, &tpm2_guid, NULL, (void **)&tpm2);
>> + if (status == EFI_SUCCESS) {
>> + status = efi_call_proto(tpm2, get_event_log, version, &log_location,
>> + &log_last_entry, &truncated);
>> +
>> + if (status != EFI_SUCCESS || !log_location) {
>> + version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
>> + status = efi_call_proto(tpm2, get_event_log, version,
>> + &log_location, &log_last_entry,
>> + &truncated);
>> + if (status != EFI_SUCCESS || !log_location)
>> + return;
>> + }
>> +
>> + efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
>> + truncated);
>> + return;
>> + }
>> +
>> + status = efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);
>> + if (status == EFI_SUCCESS) {
>> + version = EFI_CC_EVENT_LOG_FORMAT_TCG_2;
>> + status = efi_call_proto(cc, get_event_log, version, &log_location,
>> + &log_last_entry, &truncated);
>> + if (status != EFI_SUCCESS || !log_location)
>> + return;
>> +
>> + efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
>> + truncated);
>> + return;
>> + }
>> +}
> [...]
>
> I haven't looked into CC measurements much, but do we always want to
> prioritize the tcg2 protocol? IOW if you have firmware that implements
> both, shouldn't we prefer the CC protocol for VMs?
According the UEFI specification, sec "Conidential computing", if a firmware implements
the TPM, then it should be used and CC interfaces should not be published. So I think
we should check for TPM first, if it does not exist then try for CC.
https://uefi.org/specs/UEFI/2.10/38_Confidential_Computing.html#confidential-computing
> Thanks
> /Ilias
Apologies for the late reply,
On Mon, 19 Feb 2024 at 09:34, Kuppuswamy Sathyanarayanan
<sathyanarayanan.kuppuswamy@linux.intel.com> wrote:
>
> Hi Ilias,
>
> On 2/18/24 11:03 PM, Ilias Apalodimas wrote:
> > On Thu, 15 Feb 2024 at 05:02, Kuppuswamy Sathyanarayanan
> > <sathyanarayanan.kuppuswamy@linux.intel.com> wrote:
> >> To allow event log info access after boot, EFI boot stub extracts
> >> the event log information and installs it in an EFI configuration
> >> table. Currently, EFI boot stub only supports installation of event
> >> log only for TPM 1.2 and TPM 2.0 protocols. Extend the same support
> >> for CC protocol. Since CC platform also uses TCG2 format, reuse TPM2
> >> support code as much as possible.
> >>
> >> Link: https://uefi.org/specs/UEFI/2.10/38_Confidential_Computing.html#efi-cc-measurement-protocol [1]
> >> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
> > [...]
> >
> >> +void efi_retrieve_eventlog(void)
> >> +{
> >> + efi_physical_addr_t log_location = 0, log_last_entry = 0;
> >> + efi_guid_t cc_guid = EFI_CC_MEASUREMENT_PROTOCOL_GUID;
> >> + efi_guid_t tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
> >> + int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
> >> + efi_tcg2_protocol_t *tpm2 = NULL;
> >> + efi_cc_protocol_t *cc = NULL;
> >> + efi_bool_t truncated;
> >> + efi_status_t status;
> >> +
> >> + status = efi_bs_call(locate_protocol, &tpm2_guid, NULL, (void **)&tpm2);
> >> + if (status == EFI_SUCCESS) {
> >> + status = efi_call_proto(tpm2, get_event_log, version, &log_location,
> >> + &log_last_entry, &truncated);
> >> +
> >> + if (status != EFI_SUCCESS || !log_location) {
> >> + version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
> >> + status = efi_call_proto(tpm2, get_event_log, version,
> >> + &log_location, &log_last_entry,
> >> + &truncated);
> >> + if (status != EFI_SUCCESS || !log_location)
> >> + return;
> >> + }
> >> +
> >> + efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
> >> + truncated);
> >> + return;
> >> + }
> >> +
> >> + status = efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);
> >> + if (status == EFI_SUCCESS) {
> >> + version = EFI_CC_EVENT_LOG_FORMAT_TCG_2;
> >> + status = efi_call_proto(cc, get_event_log, version, &log_location,
> >> + &log_last_entry, &truncated);
> >> + if (status != EFI_SUCCESS || !log_location)
> >> + return;
> >> +
> >> + efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
> >> + truncated);
> >> + return;
> >> + }
> >> +}
> > [...]
> >
> > I haven't looked into CC measurements much, but do we always want to
> > prioritize the tcg2 protocol? IOW if you have firmware that implements
> > both, shouldn't we prefer the CC protocol for VMs?
>
> According the UEFI specification, sec "Conidential computing", if a firmware implements
> the TPM, then it should be used and CC interfaces should not be published. So I think
> we should check for TPM first, if it does not exist then try for CC.
Ok thanks, that makes sense. That document also says the services
should be implemented on a virtual firmware.
I am unsure at the moment though if it's worth checking that and
reporting an error otherwise. Thoughts?
Thanks
/Ilias
>
> https://uefi.org/specs/UEFI/2.10/38_Confidential_Computing.html#confidential-computing
>
> > Thanks
> > /Ilias
>
> --
> Sathyanarayanan Kuppuswamy
> Linux Kernel Developer
>
On 2/23/24 5:24 AM, Ilias Apalodimas wrote:
> Apologies for the late reply,
>
>
> On Mon, 19 Feb 2024 at 09:34, Kuppuswamy Sathyanarayanan
> <sathyanarayanan.kuppuswamy@linux.intel.com> wrote:
>> Hi Ilias,
>>
>> On 2/18/24 11:03 PM, Ilias Apalodimas wrote:
>>> On Thu, 15 Feb 2024 at 05:02, Kuppuswamy Sathyanarayanan
>>> <sathyanarayanan.kuppuswamy@linux.intel.com> wrote:
>>>> To allow event log info access after boot, EFI boot stub extracts
>>>> the event log information and installs it in an EFI configuration
>>>> table. Currently, EFI boot stub only supports installation of event
>>>> log only for TPM 1.2 and TPM 2.0 protocols. Extend the same support
>>>> for CC protocol. Since CC platform also uses TCG2 format, reuse TPM2
>>>> support code as much as possible.
>>>>
>>>> Link: https://uefi.org/specs/UEFI/2.10/38_Confidential_Computing.html#efi-cc-measurement-protocol [1]
>>>> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
>>> [...]
>>>
>>>> +void efi_retrieve_eventlog(void)
>>>> +{
>>>> + efi_physical_addr_t log_location = 0, log_last_entry = 0;
>>>> + efi_guid_t cc_guid = EFI_CC_MEASUREMENT_PROTOCOL_GUID;
>>>> + efi_guid_t tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
>>>> + int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
>>>> + efi_tcg2_protocol_t *tpm2 = NULL;
>>>> + efi_cc_protocol_t *cc = NULL;
>>>> + efi_bool_t truncated;
>>>> + efi_status_t status;
>>>> +
>>>> + status = efi_bs_call(locate_protocol, &tpm2_guid, NULL, (void **)&tpm2);
>>>> + if (status == EFI_SUCCESS) {
>>>> + status = efi_call_proto(tpm2, get_event_log, version, &log_location,
>>>> + &log_last_entry, &truncated);
>>>> +
>>>> + if (status != EFI_SUCCESS || !log_location) {
>>>> + version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
>>>> + status = efi_call_proto(tpm2, get_event_log, version,
>>>> + &log_location, &log_last_entry,
>>>> + &truncated);
>>>> + if (status != EFI_SUCCESS || !log_location)
>>>> + return;
>>>> + }
>>>> +
>>>> + efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
>>>> + truncated);
>>>> + return;
>>>> + }
>>>> +
>>>> + status = efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);
>>>> + if (status == EFI_SUCCESS) {
>>>> + version = EFI_CC_EVENT_LOG_FORMAT_TCG_2;
>>>> + status = efi_call_proto(cc, get_event_log, version, &log_location,
>>>> + &log_last_entry, &truncated);
>>>> + if (status != EFI_SUCCESS || !log_location)
>>>> + return;
>>>> +
>>>> + efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
>>>> + truncated);
>>>> + return;
>>>> + }
>>>> +}
>>> [...]
>>>
>>> I haven't looked into CC measurements much, but do we always want to
>>> prioritize the tcg2 protocol? IOW if you have firmware that implements
>>> both, shouldn't we prefer the CC protocol for VMs?
>> According the UEFI specification, sec "Conidential computing", if a firmware implements
>> the TPM, then it should be used and CC interfaces should not be published. So I think
>> we should check for TPM first, if it does not exist then try for CC.
> Ok thanks, that makes sense. That document also says the services
> should be implemented on a virtual firmware.
> I am unsure at the moment though if it's worth checking that and
> reporting an error otherwise. Thoughts?
IMO, it is not fatal for the firmware to implement both protocols. Although, it
violates the specification, does it makes sense to return error and skip
measurements? I think for such case, we can add a warning and proceed
with TPM if it exists.
>
> Thanks
> /Ilias
>> https://uefi.org/specs/UEFI/2.10/38_Confidential_Computing.html#confidential-computing
>>
>>> Thanks
>>> /Ilias
>> --
>> Sathyanarayanan Kuppuswamy
>> Linux Kernel Developer
>>
On Sat, 24 Feb 2024 at 09:31, Kuppuswamy Sathyanarayanan
<sathyanarayanan.kuppuswamy@linux.intel.com> wrote:
>
>
> On 2/23/24 5:24 AM, Ilias Apalodimas wrote:
> > Apologies for the late reply,
> >
> >
> > On Mon, 19 Feb 2024 at 09:34, Kuppuswamy Sathyanarayanan
> > <sathyanarayanan.kuppuswamy@linux.intel.com> wrote:
> >> Hi Ilias,
> >>
> >> On 2/18/24 11:03 PM, Ilias Apalodimas wrote:
> >>> On Thu, 15 Feb 2024 at 05:02, Kuppuswamy Sathyanarayanan
> >>> <sathyanarayanan.kuppuswamy@linux.intel.com> wrote:
> >>>> To allow event log info access after boot, EFI boot stub extracts
> >>>> the event log information and installs it in an EFI configuration
> >>>> table. Currently, EFI boot stub only supports installation of event
> >>>> log only for TPM 1.2 and TPM 2.0 protocols. Extend the same support
> >>>> for CC protocol. Since CC platform also uses TCG2 format, reuse TPM2
> >>>> support code as much as possible.
> >>>>
> >>>> Link: https://uefi.org/specs/UEFI/2.10/38_Confidential_Computing.html#efi-cc-measurement-protocol [1]
> >>>> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
> >>> [...]
> >>>
> >>>> +void efi_retrieve_eventlog(void)
> >>>> +{
> >>>> + efi_physical_addr_t log_location = 0, log_last_entry = 0;
> >>>> + efi_guid_t cc_guid = EFI_CC_MEASUREMENT_PROTOCOL_GUID;
> >>>> + efi_guid_t tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
> >>>> + int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
> >>>> + efi_tcg2_protocol_t *tpm2 = NULL;
> >>>> + efi_cc_protocol_t *cc = NULL;
> >>>> + efi_bool_t truncated;
> >>>> + efi_status_t status;
> >>>> +
> >>>> + status = efi_bs_call(locate_protocol, &tpm2_guid, NULL, (void **)&tpm2);
> >>>> + if (status == EFI_SUCCESS) {
> >>>> + status = efi_call_proto(tpm2, get_event_log, version, &log_location,
> >>>> + &log_last_entry, &truncated);
> >>>> +
> >>>> + if (status != EFI_SUCCESS || !log_location) {
> >>>> + version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
> >>>> + status = efi_call_proto(tpm2, get_event_log, version,
> >>>> + &log_location, &log_last_entry,
> >>>> + &truncated);
> >>>> + if (status != EFI_SUCCESS || !log_location)
> >>>> + return;
> >>>> + }
> >>>> +
> >>>> + efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
> >>>> + truncated);
> >>>> + return;
> >>>> + }
> >>>> +
> >>>> + status = efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);
> >>>> + if (status == EFI_SUCCESS) {
> >>>> + version = EFI_CC_EVENT_LOG_FORMAT_TCG_2;
> >>>> + status = efi_call_proto(cc, get_event_log, version, &log_location,
> >>>> + &log_last_entry, &truncated);
> >>>> + if (status != EFI_SUCCESS || !log_location)
> >>>> + return;
> >>>> +
> >>>> + efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
> >>>> + truncated);
> >>>> + return;
> >>>> + }
> >>>> +}
> >>> [...]
> >>>
> >>> I haven't looked into CC measurements much, but do we always want to
> >>> prioritize the tcg2 protocol? IOW if you have firmware that implements
> >>> both, shouldn't we prefer the CC protocol for VMs?
> >> According the UEFI specification, sec "Conidential computing", if a firmware implements
> >> the TPM, then it should be used and CC interfaces should not be published. So I think
> >> we should check for TPM first, if it does not exist then try for CC.
> > Ok thanks, that makes sense. That document also says the services
> > should be implemented on a virtual firmware.
> > I am unsure at the moment though if it's worth checking that and
> > reporting an error otherwise. Thoughts?
>
> IMO, it is not fatal for the firmware to implement both protocols. Although, it
> violates the specification, does it makes sense to return error and skip
> measurements? I think for such case, we can add a warning and proceed
> with TPM if it exists.
If you have a TPM, the current code wouldn't even look for CC (which
we agreed is correct).
The question is, should we care if a firmware exposes the CC protocol,
but isn't virtualized
Thanks
/Ilias
>
> >
> > Thanks
> > /Ilias
> >> https://uefi.org/specs/UEFI/2.10/38_Confidential_Computing.html#confidential-computing
> >>
> >>> Thanks
> >>> /Ilias
> >> --
> >> Sathyanarayanan Kuppuswamy
> >> Linux Kernel Developer
> >>
> --
> Sathyanarayanan Kuppuswamy
> Linux Kernel Developer
>
On 2/27/24 5:19 AM, Ilias Apalodimas wrote:
> On Sat, 24 Feb 2024 at 09:31, Kuppuswamy Sathyanarayanan
> <sathyanarayanan.kuppuswamy@linux.intel.com> wrote:
>>
>> On 2/23/24 5:24 AM, Ilias Apalodimas wrote:
>>> Apologies for the late reply,
>>>
>>>
>>> On Mon, 19 Feb 2024 at 09:34, Kuppuswamy Sathyanarayanan
>>> <sathyanarayanan.kuppuswamy@linux.intel.com> wrote:
>>>> Hi Ilias,
>>>>
>>>> On 2/18/24 11:03 PM, Ilias Apalodimas wrote:
>>>>> On Thu, 15 Feb 2024 at 05:02, Kuppuswamy Sathyanarayanan
>>>>> <sathyanarayanan.kuppuswamy@linux.intel.com> wrote:
>>>>>> To allow event log info access after boot, EFI boot stub extracts
>>>>>> the event log information and installs it in an EFI configuration
>>>>>> table. Currently, EFI boot stub only supports installation of event
>>>>>> log only for TPM 1.2 and TPM 2.0 protocols. Extend the same support
>>>>>> for CC protocol. Since CC platform also uses TCG2 format, reuse TPM2
>>>>>> support code as much as possible.
>>>>>>
>>>>>> Link: https://uefi.org/specs/UEFI/2.10/38_Confidential_Computing.html#efi-cc-measurement-protocol [1]
>>>>>> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
>>>>> [...]
>>>>>
>>>>>> +void efi_retrieve_eventlog(void)
>>>>>> +{
>>>>>> + efi_physical_addr_t log_location = 0, log_last_entry = 0;
>>>>>> + efi_guid_t cc_guid = EFI_CC_MEASUREMENT_PROTOCOL_GUID;
>>>>>> + efi_guid_t tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
>>>>>> + int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
>>>>>> + efi_tcg2_protocol_t *tpm2 = NULL;
>>>>>> + efi_cc_protocol_t *cc = NULL;
>>>>>> + efi_bool_t truncated;
>>>>>> + efi_status_t status;
>>>>>> +
>>>>>> + status = efi_bs_call(locate_protocol, &tpm2_guid, NULL, (void **)&tpm2);
>>>>>> + if (status == EFI_SUCCESS) {
>>>>>> + status = efi_call_proto(tpm2, get_event_log, version, &log_location,
>>>>>> + &log_last_entry, &truncated);
>>>>>> +
>>>>>> + if (status != EFI_SUCCESS || !log_location) {
>>>>>> + version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
>>>>>> + status = efi_call_proto(tpm2, get_event_log, version,
>>>>>> + &log_location, &log_last_entry,
>>>>>> + &truncated);
>>>>>> + if (status != EFI_SUCCESS || !log_location)
>>>>>> + return;
>>>>>> + }
>>>>>> +
>>>>>> + efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
>>>>>> + truncated);
>>>>>> + return;
>>>>>> + }
>>>>>> +
>>>>>> + status = efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);
>>>>>> + if (status == EFI_SUCCESS) {
>>>>>> + version = EFI_CC_EVENT_LOG_FORMAT_TCG_2;
>>>>>> + status = efi_call_proto(cc, get_event_log, version, &log_location,
>>>>>> + &log_last_entry, &truncated);
>>>>>> + if (status != EFI_SUCCESS || !log_location)
>>>>>> + return;
>>>>>> +
>>>>>> + efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
>>>>>> + truncated);
>>>>>> + return;
>>>>>> + }
>>>>>> +}
>>>>> [...]
>>>>>
>>>>> I haven't looked into CC measurements much, but do we always want to
>>>>> prioritize the tcg2 protocol? IOW if you have firmware that implements
>>>>> both, shouldn't we prefer the CC protocol for VMs?
>>>> According the UEFI specification, sec "Conidential computing", if a firmware implements
>>>> the TPM, then it should be used and CC interfaces should not be published. So I think
>>>> we should check for TPM first, if it does not exist then try for CC.
>>> Ok thanks, that makes sense. That document also says the services
>>> should be implemented on a virtual firmware.
>>> I am unsure at the moment though if it's worth checking that and
>>> reporting an error otherwise. Thoughts?
>> IMO, it is not fatal for the firmware to implement both protocols. Although, it
>> violates the specification, does it makes sense to return error and skip
>> measurements? I think for such case, we can add a warning and proceed
>> with TPM if it exists.
> If you have a TPM, the current code wouldn't even look for CC (which
> we agreed is correct).
> The question is, should we care if a firmware exposes the CC protocol,
> but isn't virtualized
AFAIK, even if a firmware improperly uses this protocol (in a non-virtual
environment), it should not be a fatal issue. So, if we add such a check,
it will be just a spec compliance check. Also, a firmware can improperly
use any existing EFI interfaces in n other ways. But, we cannot check for
all such cases, right? So personally I think it is not needed. But I am fine
either way.
If we want to add such check, I think we should either cc_platform_has()
or CPU feature flag check for it.
>
> Thanks
> /Ilias
>>> Thanks
>>> /Ilias
>>>> https://uefi.org/specs/UEFI/2.10/38_Confidential_Computing.html#confidential-computing
>>>>
>>>>> Thanks
>>>>> /Ilias
>>>> --
>>>> Sathyanarayanan Kuppuswamy
>>>> Linux Kernel Developer
>>>>
>> --
>> Sathyanarayanan Kuppuswamy
>> Linux Kernel Developer
>>
@@ -167,7 +167,7 @@ efi_status_t efi_stub_common(efi_handle_t handle,
si = setup_graphics();
- efi_retrieve_tpm2_eventlog();
+ efi_retrieve_eventlog();
/* Ask the firmware to clear memory on unclean shutdown */
efi_enable_reset_attack_mitigation();
@@ -928,6 +928,8 @@ typedef struct {
#define EFI_CC_BOOT_HASH_ALG_SHA384 0x00000004
+#define EFI_CC_EVENT_LOG_FORMAT_TCG_2 0x00000002
+
typedef union efi_cc_protocol efi_cc_protocol_t;
union efi_cc_protocol {
@@ -1134,7 +1136,7 @@ static inline void
efi_enable_reset_attack_mitigation(void) { }
#endif
-void efi_retrieve_tpm2_eventlog(void);
+void efi_retrieve_eventlog(void);
struct screen_info *alloc_screen_info(void);
struct screen_info *__alloc_screen_info(void);
@@ -47,39 +47,18 @@ void efi_enable_reset_attack_mitigation(void)
#endif
-void efi_retrieve_tpm2_eventlog(void)
+static void efi_retrieve_tcg2_eventlog(int version, efi_physical_addr_t log_location,
+ efi_physical_addr_t log_last_entry,
+ efi_bool_t truncated)
{
- efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID;
efi_status_t status;
- efi_physical_addr_t log_location = 0, log_last_entry = 0;
struct linux_efi_tpm_eventlog *log_tbl = NULL;
struct efi_tcg2_final_events_table *final_events_table = NULL;
unsigned long first_entry_addr, last_entry_addr;
size_t log_size, last_entry_size;
- efi_bool_t truncated;
- int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
- efi_tcg2_protocol_t *tcg2_protocol = NULL;
int final_events_size = 0;
- status = efi_bs_call(locate_protocol, &tcg2_guid, NULL,
- (void **)&tcg2_protocol);
- if (status != EFI_SUCCESS)
- return;
-
- status = efi_call_proto(tcg2_protocol, get_event_log, version,
- &log_location, &log_last_entry, &truncated);
-
- if (status != EFI_SUCCESS || !log_location) {
- version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
- status = efi_call_proto(tcg2_protocol, get_event_log, version,
- &log_location, &log_last_entry,
- &truncated);
- if (status != EFI_SUCCESS || !log_location)
- return;
-
- }
-
first_entry_addr = (unsigned long) log_location;
/*
@@ -93,8 +72,11 @@ void efi_retrieve_tpm2_eventlog(void)
* get_event_log only returns the address of the last entry.
* We need to calculate its size to deduce the full size of
* the logs.
+ *
+ * CC Event log also uses TCG2 format, handle it same as TPM2.
*/
- if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) {
+ if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 ||
+ version == EFI_CC_EVENT_LOG_FORMAT_TCG_2) {
/*
* The TCG2 log format has variable length entries,
* and the information to decode the hash algorithms
@@ -129,6 +111,8 @@ void efi_retrieve_tpm2_eventlog(void)
*/
if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
final_events_table = get_efi_config_table(LINUX_EFI_TPM_FINAL_LOG_GUID);
+ else if (version == EFI_CC_EVENT_LOG_FORMAT_TCG_2)
+ final_events_table = get_efi_config_table(LINUX_EFI_CC_FINAL_LOG_GUID);
if (final_events_table && final_events_table->nr_events) {
struct tcg_pcr_event2_head *header;
int offset;
@@ -165,3 +149,47 @@ void efi_retrieve_tpm2_eventlog(void)
err_free:
efi_bs_call(free_pool, log_tbl);
}
+
+void efi_retrieve_eventlog(void)
+{
+ efi_physical_addr_t log_location = 0, log_last_entry = 0;
+ efi_guid_t cc_guid = EFI_CC_MEASUREMENT_PROTOCOL_GUID;
+ efi_guid_t tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
+ int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
+ efi_tcg2_protocol_t *tpm2 = NULL;
+ efi_cc_protocol_t *cc = NULL;
+ efi_bool_t truncated;
+ efi_status_t status;
+
+ status = efi_bs_call(locate_protocol, &tpm2_guid, NULL, (void **)&tpm2);
+ if (status == EFI_SUCCESS) {
+ status = efi_call_proto(tpm2, get_event_log, version, &log_location,
+ &log_last_entry, &truncated);
+
+ if (status != EFI_SUCCESS || !log_location) {
+ version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
+ status = efi_call_proto(tpm2, get_event_log, version,
+ &log_location, &log_last_entry,
+ &truncated);
+ if (status != EFI_SUCCESS || !log_location)
+ return;
+ }
+
+ efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
+ truncated);
+ return;
+ }
+
+ status = efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);
+ if (status == EFI_SUCCESS) {
+ version = EFI_CC_EVENT_LOG_FORMAT_TCG_2;
+ status = efi_call_proto(cc, get_event_log, version, &log_location,
+ &log_last_entry, &truncated);
+ if (status != EFI_SUCCESS || !log_location)
+ return;
+
+ efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
+ truncated);
+ return;
+ }
+}
@@ -918,7 +918,7 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
efi_random_get_seed();
- efi_retrieve_tpm2_eventlog();
+ efi_retrieve_eventlog();
setup_graphics(boot_params);
@@ -440,6 +440,9 @@ void efi_native_runtime_setup(void);
/* OVMF protocol GUIDs */
#define OVMF_SEV_MEMORY_ACCEPTANCE_PROTOCOL_GUID EFI_GUID(0xc5a010fe, 0x38a7, 0x4531, 0x8a, 0x4a, 0x05, 0x00, 0xd2, 0xfd, 0x16, 0x49)
+/* CC GUIDs */
+#define LINUX_EFI_CC_FINAL_LOG_GUID EFI_GUID(0xdd4a4648, 0x2de7, 0x4665, 0x96, 0x4d, 0x21, 0xd9, 0xef, 0x5f, 0xb4, 0x46)
+
typedef struct {
efi_guid_t guid;
u64 table;