From patchwork Mon Nov 29 07:39:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ruchika Gupta X-Patchwork-Id: 519697 Delivered-To: patch@linaro.org Received: by 2002:ac0:c605:0:0:0:0:0 with SMTP id p5csp5728631imj; Sun, 28 Nov 2021 23:40:11 -0800 (PST) X-Google-Smtp-Source: ABdhPJw0FplaJUa9b52GWb/m+pRdbnD/PhyRozv5be/D0nUB6xgu+sUKJknBUFFJ8bwvPl6F/ARk X-Received: by 2002:a17:907:7f8f:: with SMTP id qk15mr57718621ejc.455.1638171611175; Sun, 28 Nov 2021 23:40:11 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1638171611; cv=none; d=google.com; s=arc-20160816; b=nCsIsPfyLZQzuO/8Fw4fwnE28supmXW09nhbmpPOslbMrDn/onxStsyWxyOUdy5y0U 7AFiROj7X+95+O/SA5wsFx/+OgKWY9pp5wRR04qGK/YLnaMJaa+Mkc8e3pYha9nDrbar fPIdAclH1yqJ2cb1fMT3ctsTB/Ky8bn4z2uVqulw/HUBDQ44ES0uDXm8+7uw++iKSZt1 9Wp5xpmYQXKFLM71NOmhFAXdR18aZvqlqQF68bxrX69gXYhqEjLnoupCj6iqe02m7o4y r+O4ClHrC3uuAJ4v9vqcYMBh8QdulmwOr9JlXSMJDZQhsSxvwu1ItnjdwqTrA+6oM7uW U3ag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:dkim-signature; bh=3HyBJN0RYd+G8WD8Oc6Vyhcyr6wWjHjHe2wpNpYRWlw=; b=sHdnSMtTj6qcrm7jb+FhpTdwZBFOspCOEWyPulUny9zWJhwEIkEFsWZTko9GvtEQib Is+4a7tiJbNYX/BlTwFoUCq+AvAkDI2ac/tuRRkcXIOyRbomZOOlrIorVjvXHkdOzK41 q282MZuaB4XivCVdSjilsqm/0gCO/zY9csK22WMo0jG+6b7dbKqgRUAjYQIKAcNSlrMj TMwdxZ4rHH1AO1crIy8VZTaZRhjCcZi+VBWmmZ1TTd4U5P3aEKH3Uoca+YPfPd+k7yNQ GfnOQhJGH7Q6GJqm+44bJxOsiqD46hKVivcNPtMo+WSyxQpQZb2uEJ3OhgKrCZYVd1S5 DVxA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=S4QDps9i; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [85.214.62.61]) by mx.google.com with ESMTPS id yc12si19884623ejb.695.2021.11.28.23.40.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 28 Nov 2021 23:40:11 -0800 (PST) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) client-ip=85.214.62.61; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=S4QDps9i; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 2C6F080F67; Mon, 29 Nov 2021 08:40:06 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="S4QDps9i"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 1D3AD8142F; Mon, 29 Nov 2021 08:40:03 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pj1-x1034.google.com (mail-pj1-x1034.google.com [IPv6:2607:f8b0:4864:20::1034]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id C44B180335 for ; Mon, 29 Nov 2021 08:39:57 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=ruchika.gupta@linaro.org Received: by mail-pj1-x1034.google.com with SMTP id h24so12055875pjq.2 for ; Sun, 28 Nov 2021 23:39:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=3HyBJN0RYd+G8WD8Oc6Vyhcyr6wWjHjHe2wpNpYRWlw=; b=S4QDps9i0nUW/BBEQCZXl4vHfrlT03gNoJVLpbRfJI+u5nn8kda3w9BckZRjkNM3yk T0bnGV68sXF3ADFaU4vBE0hOziQxa8hmHTHoyNbgmQePUtigjp8Tr0JFOoM5u6jLvHQo obY7Xs2SJkQ9ap06ztcgKzHIbLU1M/htoBCps2mNP6UNfqjXME4QC1Kfqf3wuVC+7xru +SfbQHC65GHYfOhNRm/agMeYUljP7XVgtnKnbq/JPDeEe+EtN+4oeCQNEBplRmZgy6B+ AED/yJsvB1kk5LwpIyAimAyy/qwJVj0yHXfF++2tl3YhOj00wAn2f+x250rdK3VvZ/ja Uy0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=3HyBJN0RYd+G8WD8Oc6Vyhcyr6wWjHjHe2wpNpYRWlw=; b=YJF/3THc6tZJfeoDu5co0k8bdcVQ4wkXROsQNa0agI49ZNvj2M9O9qksbHSUOsFxJy 6rMrxxn4hcvMtKustnuty5f4H3CIiefBLsM0o76CCtRehgPRvYRX9pnO/6XvqS8ICmjk qQVdZHzgQhR5wsOXzDmlDBMVEXCOf1cPlKH/YsqP+wcLIwztlS0h+U2VJ+hHFBuNN+Av Tge9BFvptSDPUhwCa5U8U6WSouQU3yslao1X+WdapvVagVCew2DkTbZWieio2gI9elmm zDBlkuEfeeehDy74O4s0hYNVb745sfdb+fGrUB37/nLdq706aku4C5laQ0oc8NQT9hWL 1YLA== X-Gm-Message-State: AOAM533F9VJ0TlZ79qriBq2UvN0uVuL/+8hyDz+6yZ5Wkf1ZV2fTybT0 Pn/dG9sErOTmwtj5PUH4hrFDZH1bJQ8AuQ== X-Received: by 2002:a17:90a:43c4:: with SMTP id r62mr37197191pjg.86.1638171595422; Sun, 28 Nov 2021 23:39:55 -0800 (PST) Received: from localhost.localdomain ([122.177.109.169]) by smtp.gmail.com with ESMTPSA id r16sm11785678pgk.45.2021.11.28.23.39.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 28 Nov 2021 23:39:54 -0800 (PST) From: Ruchika Gupta To: u-boot@lists.denx.de, ilias.apalodimas@linaro.org, xypron.glpk@gmx.de, agraf@csgraf.de, masahisa.kojima@linaro.org Cc: Ruchika Gupta Subject: [PATCH v8 1/3] efi_loader: Add check for event log passed from firmware Date: Mon, 29 Nov 2021 13:09:44 +0530 Message-Id: <20211129073946.1374496-1-ruchika.gupta@linaro.org> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.37 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Platforms may have support to measure their initial firmware components and pass the event log to u-boot. The event log address can be passed in property tpm_event_log_addr and tpm_event_log_size of the tpm node. Platforms may choose their own specific mechanism to do so. A weak function is added to check if even log has been passed to u-boot from earlier firmware components. If available, the eventlog is parsed to check for its correctness and further event logs are appended to the passed log. Signed-off-by: Ruchika Gupta Reviewed-by: Ilias Apalodimas Tested-by: Ilias Apalodimas --- v8: Addressed issues reported by cppcheck and warning on 32 bit builds v7: Addressed Heinrich's comments Changed functions not exported out of this file as static. Corrected function decsriptions and added few. Added declaration of weak function in header file Moved offset check to parse functions v6: No change v5: Shift the efi_init_event_log() to a different location in the file. This help fixes compilation issue introduced by calling efi_append_scrtm_version() from it. v4: Add SCRTM version to log only if previous firmware doesn't pass the eventlog v3: Return as soon as you detect error v2: Moved firmware eventlog code parsing to tcg2_get_fw_eventlog() include/efi_loader.h | 2 + lib/efi_loader/efi_tcg2.c | 469 ++++++++++++++++++++++++++++++++------ 2 files changed, 402 insertions(+), 69 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index d52e399841..67c40ca57a 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -988,4 +988,6 @@ efi_status_t efi_esrt_register(void); */ efi_status_t efi_esrt_populate(void); efi_status_t efi_load_capsule_drivers(void); + +efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz); #endif /* _EFI_LOADER_H */ diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 8c1f22e337..ce3e599c83 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -324,6 +324,45 @@ __weak efi_status_t platform_get_tpm2_device(struct udevice **dev) return EFI_NOT_FOUND; } +/** + * platform_get_eventlog() - retrieve the eventlog address and size + * + * This function retrieves the eventlog address and size if the underlying + * firmware has done some measurements and passed them. + * + * This function may be overridden based on platform specific method of + * passing the eventlog address and size. + * + * @dev: udevice + * @addr: eventlog address + * @sz: eventlog size + * Return: status code + */ +__weak efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, + u32 *sz) +{ + const u64 *basep; + const u32 *sizep; + + basep = dev_read_prop(dev, "tpm_event_log_addr", NULL); + if (!basep) + return EFI_NOT_FOUND; + + *addr = be64_to_cpup((__force __be64 *)basep); + + sizep = dev_read_prop(dev, "tpm_event_log_size", NULL); + if (!sizep) + return EFI_NOT_FOUND; + + *sz = be32_to_cpup((__force __be32 *)sizep); + if (*sz == 0) { + log_debug("event log empty\n"); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + /** * tpm2_get_max_command_size() - get the supported max command size * @@ -1181,6 +1220,280 @@ static const struct efi_tcg2_protocol efi_tcg2_protocol = { .get_result_of_set_active_pcr_banks = efi_tcg2_get_result_of_set_active_pcr_banks, }; +/** + * parse_event_log_header() - Parse and verify the event log header fields + * + * @buffer: Pointer to the start of the eventlog + * @size: Size of the eventlog + * @pos: Return offset of the next event in buffer right + * after the event header i.e specID + * + * Return: status code + */ +static efi_status_t parse_event_log_header(void *buffer, u32 size, u32 *pos) +{ + struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer; + int i = 0; + + if (size < sizeof(*event_header)) + return EFI_COMPROMISED_DATA; + + if (get_unaligned_le32(&event_header->pcr_index) != 0 || + get_unaligned_le32(&event_header->event_type) != EV_NO_ACTION) + return EFI_COMPROMISED_DATA; + + for (i = 0; i < sizeof(event_header->digest); i++) { + if (event_header->digest[i]) + return EFI_COMPROMISED_DATA; + } + + *pos += sizeof(*event_header); + + return EFI_SUCCESS; +} + +/** + * parse_specid_event() - Parse and verify the specID Event in the eventlog + * + * @dev: udevice + * @buffer: Pointer to the start of the eventlog + * @log_size: Size of the eventlog + * @pos: [in] Offset of specID event in the eventlog buffer + * [out] Return offset of the next event in the buffer + * after the specID + * @digest_list: list of digests in the event + * + * Return: status code + * @pos Offset in the eventlog where the specID event ends + * @digest_list: list of digests in the event + */ +static efi_status_t parse_specid_event(struct udevice *dev, void *buffer, + u32 log_size, u32 *pos, + struct tpml_digest_values *digest_list) +{ + struct tcg_efi_spec_id_event *spec_event; + struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer; + size_t spec_event_size; + u32 active = 0, supported = 0, pcr_count = 0, alg_count = 0; + u32 spec_active = 0; + u16 hash_alg; + u8 vendor_sz; + int err, i; + + if (*pos >= log_size || (*pos + sizeof(*spec_event)) > log_size) + return EFI_COMPROMISED_DATA; + + /* Check specID event data */ + spec_event = (struct tcg_efi_spec_id_event *)((uintptr_t)buffer + *pos); + /* Check for signature */ + if (memcmp(spec_event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03, + sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03))) { + log_err("specID Event: Signature mismatch\n"); + return EFI_COMPROMISED_DATA; + } + + if (spec_event->spec_version_minor != + TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 || + spec_event->spec_version_major != + TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2) + return EFI_COMPROMISED_DATA; + + if (spec_event->number_of_algorithms > MAX_HASH_COUNT || + spec_event->number_of_algorithms < 1) { + log_err("specID Event: Number of algorithms incorrect\n"); + return EFI_COMPROMISED_DATA; + } + + alg_count = spec_event->number_of_algorithms; + + err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_count); + if (err) + return EFI_DEVICE_ERROR; + + digest_list->count = 0; + /* + * We have to take care that the sequence of algorithms that we record + * in digest_list matches the sequence in eventlog. + */ + for (i = 0; i < alg_count; i++) { + hash_alg = + get_unaligned_le16(&spec_event->digest_sizes[i].algorithm_id); + + if (!(supported & alg_to_mask(hash_alg))) { + log_err("specID Event: Unsupported algorithm\n"); + return EFI_COMPROMISED_DATA; + } + digest_list->digests[digest_list->count++].hash_alg = hash_alg; + + spec_active |= alg_to_mask(hash_alg); + } + + /* + * TCG specification expects the event log to have hashes for all + * active PCR's + */ + if (spec_active != active) { + /* + * Previous stage bootloader should know all the active PCR's + * and use them in the Eventlog. + */ + log_err("specID Event: All active hash alg not present\n"); + return EFI_COMPROMISED_DATA; + } + + /* + * the size of the spec event and placement of vendor_info_size + * depends on supported algoriths + */ + spec_event_size = + offsetof(struct tcg_efi_spec_id_event, digest_sizes) + + alg_count * sizeof(spec_event->digest_sizes[0]); + + if (*pos + spec_event_size >= log_size) + return EFI_COMPROMISED_DATA; + + vendor_sz = *(uint8_t *)((uintptr_t)buffer + *pos + spec_event_size); + + spec_event_size += sizeof(vendor_sz) + vendor_sz; + *pos += spec_event_size; + + if (get_unaligned_le32(&event_header->event_size) != spec_event_size) { + log_err("specID event: header event size mismatch\n"); + /* Right way to handle this can be to call SetActive PCR's */ + return EFI_COMPROMISED_DATA; + } + + return EFI_SUCCESS; +} + +/** + * tcg2_parse_event() - Parse the event in the eventlog + * + * @dev: udevice + * @buffer: Pointer to the start of the eventlog + * @log_size: Size of the eventlog + * @offset: [in] Offset of the event in the eventlog buffer + * [out] Return offset of the next event in the buffer + * @digest_list: list of digests in the event + * @pcr Index of the PCR in the event + * + * Return: status code + */ +static efi_status_t tcg2_parse_event(struct udevice *dev, void *buffer, + u32 log_size, u32 *offset, + struct tpml_digest_values *digest_list, + u32 *pcr) +{ + struct tcg_pcr_event2 *event = NULL; + u32 count, size, event_size; + size_t pos; + + event_size = tcg_event_final_size(digest_list); + if (*offset >= log_size || *offset + event_size > log_size) { + log_err("Event exceeds log size\n"); + return EFI_COMPROMISED_DATA; + } + + event = (struct tcg_pcr_event2 *)((uintptr_t)buffer + *offset); + *pcr = get_unaligned_le32(&event->pcr_index); + + /* get the count */ + count = get_unaligned_le32(&event->digests.count); + if (count != digest_list->count) + return EFI_COMPROMISED_DATA; + + pos = offsetof(struct tcg_pcr_event2, digests); + pos += offsetof(struct tpml_digest_values, digests); + + for (int i = 0; i < digest_list->count; i++) { + u16 alg; + u16 hash_alg = digest_list->digests[i].hash_alg; + u8 *digest = (u8 *)&digest_list->digests[i].digest; + + alg = get_unaligned_le16((void *)((uintptr_t)event + pos)); + + if (alg != hash_alg) + return EFI_COMPROMISED_DATA; + + pos += offsetof(struct tpmt_ha, digest); + memcpy(digest, (void *)((uintptr_t)event + pos), alg_to_len(hash_alg)); + pos += alg_to_len(hash_alg); + } + + size = get_unaligned_le32((void *)((uintptr_t)event + pos)); + event_size += size; + pos += sizeof(u32); /* tcg_pcr_event2 event_size*/ + pos += size; + + /* make sure the calculated buffer is what we checked against */ + if (pos != event_size) + return EFI_COMPROMISED_DATA; + + if (pos > log_size) + return EFI_COMPROMISED_DATA; + + *offset += pos; + + return EFI_SUCCESS; +} + +/** + * tcg2_get_fw_eventlog() - Get the eventlog address and size + * + * If the previous firmware has passed some eventlog, this function get it's + * location and check for it's validity. + * + * @dev: udevice + * @log_buffer: eventlog address + * @log_sz: eventlog size + * + * Return: status code + */ +static efi_status_t tcg2_get_fw_eventlog(struct udevice *dev, void *log_buffer, + size_t *log_sz) +{ + struct tpml_digest_values digest_list; + void *buffer; + efi_status_t ret; + u32 pcr, pos; + u64 base; + u32 sz; + + ret = platform_get_eventlog(dev, &base, &sz); + if (ret != EFI_SUCCESS) + return ret; + + if (sz > TPM2_EVENT_LOG_SIZE) + return EFI_VOLUME_FULL; + + buffer = (void *)(uintptr_t)base; + pos = 0; + /* Parse the eventlog to check for its validity */ + ret = parse_event_log_header(buffer, sz, &pos); + if (ret) + return ret; + + ret = parse_specid_event(dev, buffer, sz, &pos, &digest_list); + if (ret) { + log_err("Error parsing SPEC ID Event\n"); + return ret; + } + + while (pos < sz) { + ret = tcg2_parse_event(dev, buffer, sz, &pos, &digest_list, + &pcr); + if (ret) { + log_err("Error parsing event\n"); + return ret; + } + } + + memcpy(log_buffer, buffer, sz); + *log_sz = sz; + + return ret; +} + /** * create_specid_event() - Create the first event in the eventlog * @@ -1312,69 +1625,6 @@ out: return ret; } -/** - * efi_init_event_log() - initialize an eventlog - */ -static efi_status_t efi_init_event_log(void) -{ - /* - * vendor_info_size is currently set to 0, we need to change the length - * and allocate the flexible array member if this changes - */ - struct tcg_pcr_event *event_header = NULL; - struct udevice *dev; - size_t spec_event_size; - efi_status_t ret; - - ret = platform_get_tpm2_device(&dev); - if (ret != EFI_SUCCESS) - goto out; - - ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, TPM2_EVENT_LOG_SIZE, - (void **)&event_log.buffer); - if (ret != EFI_SUCCESS) - goto out; - - /* - * initialize log area as 0xff so the OS can easily figure out the - * last log entry - */ - memset(event_log.buffer, 0xff, TPM2_EVENT_LOG_SIZE); - event_log.pos = 0; - event_log.last_event_size = 0; - event_log.get_event_called = false; - event_log.ebs_called = false; - event_log.truncated = false; - - /* - * The log header is defined to be in SHA1 event log entry format. - * Setup event header - */ - event_header = (struct tcg_pcr_event *)event_log.buffer; - put_unaligned_le32(0, &event_header->pcr_index); - put_unaligned_le32(EV_NO_ACTION, &event_header->event_type); - memset(&event_header->digest, 0, sizeof(event_header->digest)); - ret = create_specid_event(dev, (void *)((uintptr_t)event_log.buffer + sizeof(*event_header)), - &spec_event_size); - if (ret != EFI_SUCCESS) - goto free_pool; - put_unaligned_le32(spec_event_size, &event_header->event_size); - event_log.pos = spec_event_size + sizeof(*event_header); - event_log.last_event_size = event_log.pos; - - ret = create_final_event(); - if (ret != EFI_SUCCESS) - goto free_pool; - -out: - return ret; - -free_pool: - efi_free_pool(event_log.buffer); - event_log.buffer = NULL; - return ret; -} - /** * tcg2_measure_event() - common function to add event log and extend PCR * @@ -1427,6 +1677,93 @@ static efi_status_t efi_append_scrtm_version(struct udevice *dev) return ret; } +/** + * efi_init_event_log() - initialize an eventlog + * + * Return: status code + */ +static efi_status_t efi_init_event_log(void) +{ + /* + * vendor_info_size is currently set to 0, we need to change the length + * and allocate the flexible array member if this changes + */ + struct tcg_pcr_event *event_header = NULL; + struct udevice *dev; + size_t spec_event_size; + efi_status_t ret; + + ret = platform_get_tpm2_device(&dev); + if (ret != EFI_SUCCESS) + return ret; + + ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, TPM2_EVENT_LOG_SIZE, + (void **)&event_log.buffer); + if (ret != EFI_SUCCESS) + return ret; + + /* + * initialize log area as 0xff so the OS can easily figure out the + * last log entry + */ + memset(event_log.buffer, 0xff, TPM2_EVENT_LOG_SIZE); + + /* + * The log header is defined to be in SHA1 event log entry format. + * Setup event header + */ + event_header = (struct tcg_pcr_event *)event_log.buffer; + event_log.pos = 0; + event_log.last_event_size = 0; + event_log.get_event_called = false; + event_log.ebs_called = false; + event_log.truncated = false; + + /* + * Check if earlier firmware have passed any eventlog. Different + * platforms can use different ways to do so. + */ + ret = tcg2_get_fw_eventlog(dev, event_log.buffer, &event_log.pos); + /* + * If earlier firmware hasn't passed any eventlog, go ahead and + * create the eventlog header. + */ + if (ret == EFI_NOT_FOUND) { + put_unaligned_le32(0, &event_header->pcr_index); + put_unaligned_le32(EV_NO_ACTION, &event_header->event_type); + memset(&event_header->digest, 0, sizeof(event_header->digest)); + ret = create_specid_event(dev, + (void *)((uintptr_t)event_log.buffer + + sizeof(*event_header)), + &spec_event_size); + if (ret != EFI_SUCCESS) + goto free_pool; + put_unaligned_le32(spec_event_size, &event_header->event_size); + event_log.pos = spec_event_size + sizeof(*event_header); + event_log.last_event_size = event_log.pos; + + /* + * Add SCRTM version to the log if previous firmmware + * doesn't pass an eventlog. + */ + ret = efi_append_scrtm_version(dev); + } + + if (ret != EFI_SUCCESS) + goto free_pool; + + ret = create_final_event(); + if (ret != EFI_SUCCESS) + goto free_pool; + + return ret; + +free_pool: + efi_free_pool(event_log.buffer); + event_log.buffer = NULL; + return ret; +} + /** * tcg2_measure_variable() - add variable event log and extend PCR * @@ -1963,12 +2300,6 @@ efi_status_t efi_tcg2_register(void) if (ret != EFI_SUCCESS) goto fail; - ret = efi_append_scrtm_version(dev); - if (ret != EFI_SUCCESS) { - tcg2_uninit(); - goto fail; - } - ret = efi_add_protocol(efi_root, &efi_guid_tcg2_protocol, (void *)&efi_tcg2_protocol); if (ret != EFI_SUCCESS) {