Compare commits
3 Commits
Author | SHA256 | Date | |
---|---|---|---|
e5396cdfab | |||
bf0f5a3f27 | |||
0055c35a87 |
2
_service
2
_service
@@ -7,7 +7,7 @@
|
|||||||
<param name="url">https://github.com/okirch/pcr-oracle.git</param>
|
<param name="url">https://github.com/okirch/pcr-oracle.git</param>
|
||||||
<param name="filename">pcr-oracle</param>
|
<param name="filename">pcr-oracle</param>
|
||||||
<param name="versionformat">@PARENT_TAG@</param>
|
<param name="versionformat">@PARENT_TAG@</param>
|
||||||
<param name="revision">refs/tags/0.5.4</param>
|
<param name="revision">refs/tags/0.4.6</param>
|
||||||
</service>
|
</service>
|
||||||
<service name="recompress" mode="disabled">
|
<service name="recompress" mode="disabled">
|
||||||
<param name="file">pcr-oracle*.tar</param>
|
<param name="file">pcr-oracle*.tar</param>
|
||||||
|
@@ -1,34 +0,0 @@
|
|||||||
From 55fe5c34cf41813fd91fff85281770da77913b68 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Gary Lin <glin@suse.com>
|
|
||||||
Date: Fri, 7 Mar 2025 16:40:36 +0800
|
|
||||||
Subject: [PATCH 2/2] Stop the SbatLevelRT prediction if .sbatlevel not
|
|
||||||
available
|
|
||||||
|
|
||||||
The SbatLevelRT prediction relies on the PCR4 events to locate shim.efi,
|
|
||||||
so PCR4 has to be a hard requirement.
|
|
||||||
|
|
||||||
Signed-off-by: Gary Lin <glin@suse.com>
|
|
||||||
---
|
|
||||||
src/efi-variable.c | 6 +++---
|
|
||||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/efi-variable.c b/src/efi-variable.c
|
|
||||||
index b70f63b..f8527cc 100644
|
|
||||||
--- a/src/efi-variable.c
|
|
||||||
+++ b/src/efi-variable.c
|
|
||||||
@@ -291,9 +291,9 @@ efi_variable_authority_get_record(const tpm_parsed_event_t *parsed, const char *
|
|
||||||
db_name = "MokList";
|
|
||||||
} else
|
|
||||||
if (!strcmp(var_short_name, "SbatLevel")) {
|
|
||||||
- if (ctx->sbatlevel != NULL)
|
|
||||||
- return efi_sbatlevel_get_record(ctx->sbatlevel);
|
|
||||||
- return runtime_read_efi_variable(var_name);
|
|
||||||
+ if (ctx->sbatlevel == NULL)
|
|
||||||
+ fatal("No reference .sbatlevel section. Please add PCR4 into the PCR index list\n");
|
|
||||||
+ return efi_sbatlevel_get_record(ctx->sbatlevel);
|
|
||||||
} else {
|
|
||||||
/* Read as-is (this could be SbatLevel, or some other variable that's not
|
|
||||||
* a signature db). */
|
|
||||||
--
|
|
||||||
2.43.0
|
|
||||||
|
|
@@ -1,103 +0,0 @@
|
|||||||
From 07e43365379ef5bd9fb53a45306af02025442b92 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Gary Lin <glin@suse.com>
|
|
||||||
Date: Fri, 7 Mar 2025 14:09:34 +0800
|
|
||||||
Subject: [PATCH 1/2] Fix SbatLevelRT prediction when Secure Boot is disabled
|
|
||||||
|
|
||||||
Since shim 15.8, instead of using SBAT automatic as the default
|
|
||||||
candidate, it always resets SbatLevel to SBAT_ORIGINAL. To make the
|
|
||||||
prediction work for shim >= 15.8, the additinal check is added to adjust
|
|
||||||
the SBAT candidate.
|
|
||||||
|
|
||||||
Also fix POLICY_RESET for not setting sbat_reset to true and a few
|
|
||||||
typos.
|
|
||||||
|
|
||||||
Signed-off-by: Gary Lin <glin@suse.com>
|
|
||||||
---
|
|
||||||
src/efi-variable.c | 30 ++++++++++++++++++++++++++----
|
|
||||||
1 file changed, 26 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/efi-variable.c b/src/efi-variable.c
|
|
||||||
index 9c56eec..b70f63b 100644
|
|
||||||
--- a/src/efi-variable.c
|
|
||||||
+++ b/src/efi-variable.c
|
|
||||||
@@ -100,6 +100,7 @@ __tpm_event_efi_variable_build_event(const tpm_parsed_event_t *parsed, const voi
|
|
||||||
#define POLICY_LATEST 1
|
|
||||||
#define POLICY_AUTOMATIC 2
|
|
||||||
#define POLICY_RESET 3
|
|
||||||
+#define POLICY_NOTREAD 255
|
|
||||||
|
|
||||||
#define SBAT_ORIGINAL "sbat,1,2021030218\n"
|
|
||||||
|
|
||||||
@@ -169,6 +170,7 @@ efi_sbatlevel_get_record(buffer_t *sbatlevel)
|
|
||||||
buffer_t *result = NULL;
|
|
||||||
uint8_t secureboot;
|
|
||||||
uint8_t sbatpolicy;
|
|
||||||
+ uint32_t auto_date;
|
|
||||||
uint32_t current_date;
|
|
||||||
uint32_t candidate_date;
|
|
||||||
bool sbat_reset = false;
|
|
||||||
@@ -178,6 +180,11 @@ efi_sbatlevel_get_record(buffer_t *sbatlevel)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ if (!fetch_sbat_datestamp(sbat_automatic, strlen(sbat_automatic), &auto_date)) {
|
|
||||||
+ error("Unable to get datestamp of SBAT automatic\n");
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
buffer = runtime_read_efi_variable(SECUREBOOT_VARNAME);
|
|
||||||
if (buffer == NULL || !buffer_get_u8(buffer, &secureboot))
|
|
||||||
secureboot = 0;
|
|
||||||
@@ -185,7 +192,7 @@ efi_sbatlevel_get_record(buffer_t *sbatlevel)
|
|
||||||
|
|
||||||
buffer = runtime_read_efi_variable(SBATPOLICY_VARNAME);
|
|
||||||
if (buffer == NULL || !buffer_get_u8(buffer, &sbatpolicy))
|
|
||||||
- sbatpolicy = POLICY_AUTOMATIC;
|
|
||||||
+ sbatpolicy = POLICY_NOTREAD;
|
|
||||||
buffer_free(buffer);
|
|
||||||
|
|
||||||
switch (sbatpolicy) {
|
|
||||||
@@ -200,9 +207,24 @@ efi_sbatlevel_get_record(buffer_t *sbatlevel)
|
|
||||||
infomsg("SBAT cannot be reset when Secure Boot is enabled.\n");
|
|
||||||
sbat_candidate = sbat_automatic;
|
|
||||||
} else {
|
|
||||||
+ sbat_reset = true;
|
|
||||||
sbat_candidate = SBAT_ORIGINAL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
+ case POLICY_NOTREAD:
|
|
||||||
+ if (secureboot == 1) {
|
|
||||||
+ sbat_candidate = sbat_automatic;
|
|
||||||
+ } else {
|
|
||||||
+ /* shim 15.8 always resets SbatLevel when Secure Boot is disabled.
|
|
||||||
+ * The automatic datestamp of shim 15.8 is 2023012900. */
|
|
||||||
+ if (auto_date >= 2023012900) {
|
|
||||||
+ sbat_reset = true;
|
|
||||||
+ sbat_candidate = SBAT_ORIGINAL;
|
|
||||||
+ } else {
|
|
||||||
+ sbat_candidate = sbat_automatic;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
default:
|
|
||||||
error("Invalid SBAT policy\n");
|
|
||||||
return NULL;
|
|
||||||
@@ -217,12 +239,12 @@ efi_sbatlevel_get_record(buffer_t *sbatlevel)
|
|
||||||
|
|
||||||
if (!fetch_sbat_datestamp(sbat_current, sbatlvlrt->size, ¤t_date)
|
|
||||||
|| !fetch_sbat_datestamp(sbat_candidate, strlen(sbat_candidate), &candidate_date)) {
|
|
||||||
- error("Unable to get SBAT timestamp\n");
|
|
||||||
+ error("Unable to get SBAT datestamp\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
- debug("Current SBAT datestampe: %u\n", current_date);
|
|
||||||
- debug("Candidate SBAT datestampe: %u\n", candidate_date);
|
|
||||||
+ debug("Current SBAT datestamp: %u\n", current_date);
|
|
||||||
+ debug("Candidate SBAT datestamp: %u\n", candidate_date);
|
|
||||||
|
|
||||||
if (current_date >= candidate_date && sbat_reset == false) {
|
|
||||||
debug("Use current SbatLevel\n");
|
|
||||||
--
|
|
||||||
2.43.0
|
|
||||||
|
|
@@ -1,422 +0,0 @@
|
|||||||
From 5f73c8d655465470498c91f238788d2ffa48de81 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Gary Lin <glin@suse.com>
|
|
||||||
Date: Tue, 25 Feb 2025 16:13:28 +0800
|
|
||||||
Subject: [PATCH 1/2] Locate .sbatlevel section in shim.efi
|
|
||||||
|
|
||||||
The .sbatlevel section in shim.efi will be used to set SbatLevelRT and
|
|
||||||
we need the section to predict SbatLevelRT.
|
|
||||||
|
|
||||||
Per PE format SPEC(*), the section name is
|
|
||||||
|
|
||||||
"An 8-byte, null-padded UTF-8 encoded string. If the string is exactly 8
|
|
||||||
8 characters long, there is no terminating null. For longer names, this
|
|
||||||
field contains a slash (/) that is followed by an ASCII representation
|
|
||||||
of a decimal number that is an offset into the string table."
|
|
||||||
|
|
||||||
Before looking for the .sbatlevel section, we have to get the string
|
|
||||||
table, To get the offset to the string table:
|
|
||||||
|
|
||||||
string_table_offset = symbol_table_offset +
|
|
||||||
(number_of_symbols * symbol_size)
|
|
||||||
|
|
||||||
With the offset, we can go further to look for the longer section names
|
|
||||||
and get the .sbatlevel section.
|
|
||||||
|
|
||||||
(*) https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
|
|
||||||
|
|
||||||
Signed-off-by: Gary Lin <glin@suse.com>
|
|
||||||
---
|
|
||||||
src/authenticode.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
src/authenticode.h | 2 ++
|
|
||||||
2 files changed, 77 insertions(+)
|
|
||||||
|
|
||||||
Index: pcr-oracle-0.5.4/src/authenticode.c
|
|
||||||
===================================================================
|
|
||||||
--- pcr-oracle-0.5.4.orig/src/authenticode.c
|
|
||||||
+++ pcr-oracle-0.5.4/src/authenticode.c
|
|
||||||
@@ -91,10 +91,14 @@ struct pecoff_image_info {
|
|
||||||
uint16_t machine_id;
|
|
||||||
uint16_t num_sections;
|
|
||||||
uint32_t symtab_offset;
|
|
||||||
+ uint32_t num_symbols;
|
|
||||||
uint16_t optional_hdr_size;
|
|
||||||
uint32_t optional_hdr_offset;
|
|
||||||
|
|
||||||
uint32_t section_table_offset;
|
|
||||||
+
|
|
||||||
+ uint32_t strtab_offset;
|
|
||||||
+ uint32_t strtab_size;
|
|
||||||
} pe_hdr;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
@@ -111,6 +115,9 @@ struct pecoff_image_info {
|
|
||||||
pecoff_section_t * section;
|
|
||||||
|
|
||||||
authenticode_image_info_t auth_info;
|
|
||||||
+
|
|
||||||
+ /* The contents of .sbatlevel */
|
|
||||||
+ buffer_t * sbatlevel;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MSDOS_STUB_PE_OFFSET 0x3c
|
|
||||||
@@ -147,6 +154,7 @@ void
|
|
||||||
pecoff_image_info_free(pecoff_image_info_t *img)
|
|
||||||
{
|
|
||||||
buffer_free(img->data);
|
|
||||||
+ buffer_free(img->sbatlevel);
|
|
||||||
free(img->display_name);
|
|
||||||
free(img->data_dirs);
|
|
||||||
free(img->section);
|
|
||||||
@@ -351,6 +359,8 @@ __pecoff_process_header(buffer_t *in, pe
|
|
||||||
|
|
||||||
if (!__pecoff_get_u32(in, img, PECOFF_HEADER_SYMTAB_POS_OFFSET, &img->pe_hdr.symtab_offset))
|
|
||||||
return false;
|
|
||||||
+ if (!__pecoff_get_u32(in, img, PECOFF_HEADER_SYMTAB_CNT_OFFSET, &img->pe_hdr.num_symbols))
|
|
||||||
+ return false;
|
|
||||||
|
|
||||||
img->pe_hdr.optional_hdr_offset = img->pe_hdr.offset + PECOFF_HEADER_LENGTH;
|
|
||||||
if (!__pecoff_get_u16(in, img, PECOFF_HEADER_OPTIONAL_HDR_SIZE_OFFSET, &img->pe_hdr.optional_hdr_size))
|
|
||||||
@@ -358,6 +368,19 @@ __pecoff_process_header(buffer_t *in, pe
|
|
||||||
|
|
||||||
img->pe_hdr.section_table_offset = img->pe_hdr.optional_hdr_offset + img->pe_hdr.optional_hdr_size;
|
|
||||||
|
|
||||||
+ /* String table follows symbol table immediately.
|
|
||||||
+ * One symbol is 18 bytes, so the offset to string table is
|
|
||||||
+ * symtab_offset + num_symbols * 18
|
|
||||||
+ *
|
|
||||||
+ * ref: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#coff-string-table
|
|
||||||
+ * https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#coff-symbol-table
|
|
||||||
+ */
|
|
||||||
+ if (img->pe_hdr.symtab_offset != 0) {
|
|
||||||
+ img->pe_hdr.strtab_offset = img->pe_hdr.symtab_offset + (img->pe_hdr.num_symbols * 18);
|
|
||||||
+ if (!__pecoff_get_u32(in, img, img->pe_hdr.strtab_offset, &img->pe_hdr.strtab_size))
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -451,6 +474,27 @@ __pecoff_process_optional_header(buffer_
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
+__pecoff_name_to_offset(char *sec_name, uint32_t *offset)
|
|
||||||
+{
|
|
||||||
+ uint32_t result = 0;
|
|
||||||
+ int i;
|
|
||||||
+
|
|
||||||
+ if (sec_name[0] != '/')
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ for (i = 1; i < 8 && sec_name[i] != '\0'; i++) {
|
|
||||||
+ if (sec_name[i] < '0' || sec_name[i] > '9')
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ result = result * 10 + sec_name[i] - '0';
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ *offset = result;
|
|
||||||
+
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static bool
|
|
||||||
__pecoff_process_sections(buffer_t *in, pecoff_image_info_t *info)
|
|
||||||
{
|
|
||||||
unsigned int tbl_offset = info->pe_hdr.section_table_offset;
|
|
||||||
@@ -458,6 +502,9 @@ __pecoff_process_sections(buffer_t *in,
|
|
||||||
buffer_t hdr;
|
|
||||||
unsigned int i;
|
|
||||||
pecoff_section_t *sec;
|
|
||||||
+ uint32_t str_offset;
|
|
||||||
+ char *long_name;
|
|
||||||
+ buffer_t *sec_buf;
|
|
||||||
|
|
||||||
pe_debug(" Processing %u sections (table at offset %u)\n", num_sections, tbl_offset);
|
|
||||||
|
|
||||||
@@ -483,6 +530,27 @@ __pecoff_process_sections(buffer_t *in,
|
|
||||||
|
|
||||||
pe_debug(" Section %-8s raw %7u at 0x%08x-0x%08x\n",
|
|
||||||
sec->name, sec->raw.size, sec->raw.addr, sec->raw.addr + sec->raw.size);
|
|
||||||
+ /* Process the section names longer than 8 bytes */
|
|
||||||
+ long_name = NULL;
|
|
||||||
+ if (__pecoff_name_to_offset(sec->name, &str_offset) &&
|
|
||||||
+ str_offset < info->pe_hdr.strtab_size) {
|
|
||||||
+ long_name = (char *)(in->data + info->pe_hdr.strtab_offset + str_offset);
|
|
||||||
+ pe_debug(" Long Name: %s\n", long_name);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Get sbatlevel from .sbatlevel section */
|
|
||||||
+ if (long_name != NULL && strcmp(long_name, ".sbatlevel") == 0) {
|
|
||||||
+ if (!(sec_buf = buffer_alloc_write(sec->raw.size)))
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ if (!buffer_seek_read(in, sec->raw.addr))
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ if (!buffer_copy(in, sec->raw.size, sec_buf))
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ info->sbatlevel = sec_buf;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We are supposed to sort the sections in ascending order, but we're not doing it here, we
|
|
||||||
@@ -506,6 +574,7 @@ __pecoff_show_header(pecoff_image_info_t
|
|
||||||
pe_debug(" Architecture: %s\n", __pecoff_get_machine(img));
|
|
||||||
pe_debug(" Number of sections: %d\n", img->pe_hdr.num_sections);
|
|
||||||
pe_debug(" Symbol table position: 0x%08x\n", img->pe_hdr.symtab_offset);
|
|
||||||
+ pe_debug(" String table position: 0x%08x\n", img->pe_hdr.strtab_offset);
|
|
||||||
pe_debug(" Optional header size: %d\n", img->pe_hdr.optional_hdr_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -751,3 +820,9 @@ authenticode_get_signer(const pecoff_ima
|
|
||||||
cert_table_free(cert_tbl);
|
|
||||||
return signer;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+buffer_t *
|
|
||||||
+pecoff_image_get_sbatlevel(pecoff_image_info_t *img)
|
|
||||||
+{
|
|
||||||
+ return img->sbatlevel;
|
|
||||||
+}
|
|
||||||
Index: pcr-oracle-0.5.4/src/authenticode.h
|
|
||||||
===================================================================
|
|
||||||
--- pcr-oracle-0.5.4.orig/src/authenticode.h
|
|
||||||
+++ pcr-oracle-0.5.4/src/authenticode.h
|
|
||||||
@@ -29,5 +29,7 @@ extern tpm_evdigest_t * authenticode_get
|
|
||||||
extern cert_table_t * authenticode_get_certificate_table(const pecoff_image_info_t *img);
|
|
||||||
extern parsed_cert_t * authenticode_get_signer(const pecoff_image_info_t *);
|
|
||||||
|
|
||||||
+extern buffer_t * pecoff_image_get_sbatlevel(pecoff_image_info_t *);
|
|
||||||
+
|
|
||||||
#endif /* AUTHENTICODE_H */
|
|
||||||
|
|
||||||
Index: pcr-oracle-0.5.4/src/efi-application.c
|
|
||||||
===================================================================
|
|
||||||
--- pcr-oracle-0.5.4.orig/src/efi-application.c
|
|
||||||
+++ pcr-oracle-0.5.4/src/efi-application.c
|
|
||||||
@@ -315,6 +315,7 @@ __tpm_event_efi_bsa_rehash(const tpm_eve
|
|
||||||
const struct efi_bsa_event *evspec = &parsed->efi_bsa_event;
|
|
||||||
const char *new_application;
|
|
||||||
struct efi_bsa_event evspec_clone;
|
|
||||||
+ buffer_t *sbatlevel;
|
|
||||||
|
|
||||||
/* Some BSA events do not refer to files, but to some data blobs residing somewhere on a device.
|
|
||||||
* We're not yet prepared to handle these, so we hope the user doesn't mess with them, and
|
|
||||||
@@ -348,6 +349,14 @@ __tpm_event_efi_bsa_rehash(const tpm_eve
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Set the sbatlevel section from shim.efi */
|
|
||||||
+ if (ctx->sbatlevel == NULL
|
|
||||||
+ && (sbatlevel = pecoff_image_get_sbatlevel(evspec->img_info)) != NULL) {
|
|
||||||
+ if ((ctx->sbatlevel = buffer_alloc_write(sbatlevel->size)) == NULL
|
|
||||||
+ || !buffer_copy(sbatlevel, sbatlevel->size, ctx->sbatlevel))
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (ctx->use_pesign)
|
|
||||||
return __efi_application_rehash_pesign(ctx, evspec->efi_partition, evspec->efi_application);
|
|
||||||
|
|
||||||
Index: pcr-oracle-0.5.4/src/efi-variable.c
|
|
||||||
===================================================================
|
|
||||||
--- pcr-oracle-0.5.4.orig/src/efi-variable.c
|
|
||||||
+++ pcr-oracle-0.5.4/src/efi-variable.c
|
|
||||||
@@ -93,6 +93,159 @@ __tpm_event_efi_variable_build_event(con
|
|
||||||
return bp;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#define SBATLEVELRT_VARNAME "SbatLevelRT-605dab50-e046-4300-abb6-3dd810dd8b23"
|
|
||||||
+#define SBATPOLICY_VARNAME "SbatPolicy-605dab50-e046-4300-abb6-3dd810dd8b23"
|
|
||||||
+#define SECUREBOOT_VARNAME "SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c"
|
|
||||||
+
|
|
||||||
+#define POLICY_LATEST 1
|
|
||||||
+#define POLICY_AUTOMATIC 2
|
|
||||||
+#define POLICY_RESET 3
|
|
||||||
+
|
|
||||||
+#define SBAT_ORIGINAL "sbat,1,2021030218\n"
|
|
||||||
+
|
|
||||||
+static bool
|
|
||||||
+parse_sbatlevel_section(buffer_t *sec, char **sbat_automatic, char **sbat_latest)
|
|
||||||
+{
|
|
||||||
+ uint32_t fmt_ver;
|
|
||||||
+ uint32_t offset_auto;
|
|
||||||
+ uint32_t offset_latest;
|
|
||||||
+
|
|
||||||
+ if (!buffer_get_u32le(sec, &fmt_ver)
|
|
||||||
+ || !buffer_get_u32le(sec, &offset_auto)
|
|
||||||
+ || !buffer_get_u32le(sec, &offset_latest))
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ if (offset_auto >= offset_latest)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ if (!buffer_seek_read(sec, offset_auto + 4))
|
|
||||||
+ return false;
|
|
||||||
+ *sbat_automatic = (char *)buffer_read_pointer(sec);
|
|
||||||
+
|
|
||||||
+ if (!buffer_seek_read(sec, offset_latest + 4))
|
|
||||||
+ return false;
|
|
||||||
+ *sbat_latest = (char *)(buffer_read_pointer(sec));
|
|
||||||
+
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static bool
|
|
||||||
+fetch_sbat_datestamp(const char *sbat, size_t size, uint32_t *datestamp)
|
|
||||||
+{
|
|
||||||
+ uint32_t date = 0;
|
|
||||||
+ size_t i;
|
|
||||||
+
|
|
||||||
+ /* Expected string: "sbat,X,YYYYYYYYYY\n" */
|
|
||||||
+ if (size < 17)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ if (strncmp(sbat, "sbat,", 5) != 0)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ for (i = 5; i < size && sbat[i] != ','; i++);
|
|
||||||
+ i++;
|
|
||||||
+ if (i >= size)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ for (; i < size && sbat[i] != '\n'; i++) {
|
|
||||||
+ if (sbat[i] < '0' || sbat[i] > '9')
|
|
||||||
+ return false;
|
|
||||||
+ date = date * 10 + sbat[i] - '0';
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ *datestamp = date;
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static buffer_t *
|
|
||||||
+efi_sbatlevel_get_record(buffer_t *sbatlevel)
|
|
||||||
+{
|
|
||||||
+ char *sbat_automatic;
|
|
||||||
+ char *sbat_latest;
|
|
||||||
+ const char *sbat_candidate;
|
|
||||||
+ const char *sbat_current;
|
|
||||||
+ buffer_t *buffer = NULL;
|
|
||||||
+ buffer_t *sbatlvlrt = NULL;
|
|
||||||
+ buffer_t *result = NULL;
|
|
||||||
+ uint8_t secureboot;
|
|
||||||
+ uint8_t sbatpolicy;
|
|
||||||
+ uint32_t current_date;
|
|
||||||
+ uint32_t candidate_date;
|
|
||||||
+ bool sbat_reset = false;
|
|
||||||
+
|
|
||||||
+ if (!parse_sbatlevel_section(sbatlevel, &sbat_automatic, &sbat_latest)) {
|
|
||||||
+ error("Unable to process SbatLevel\n");
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ buffer = runtime_read_efi_variable(SECUREBOOT_VARNAME);
|
|
||||||
+ if (buffer == NULL || !buffer_get_u8(buffer, &secureboot))
|
|
||||||
+ secureboot = 0;
|
|
||||||
+ buffer_free(buffer);
|
|
||||||
+
|
|
||||||
+ buffer = runtime_read_efi_variable(SBATPOLICY_VARNAME);
|
|
||||||
+ if (buffer == NULL || !buffer_get_u8(buffer, &sbatpolicy))
|
|
||||||
+ sbatpolicy = POLICY_AUTOMATIC;
|
|
||||||
+ buffer_free(buffer);
|
|
||||||
+
|
|
||||||
+ switch (sbatpolicy) {
|
|
||||||
+ case POLICY_LATEST:
|
|
||||||
+ sbat_candidate = sbat_latest;
|
|
||||||
+ break;
|
|
||||||
+ case POLICY_AUTOMATIC:
|
|
||||||
+ sbat_candidate = sbat_automatic;
|
|
||||||
+ break;
|
|
||||||
+ case POLICY_RESET:
|
|
||||||
+ if (secureboot == 1) {
|
|
||||||
+ infomsg("SBAT cannot be reset when Secure Boot is enabled.\n");
|
|
||||||
+ sbat_candidate = sbat_automatic;
|
|
||||||
+ } else {
|
|
||||||
+ sbat_candidate = SBAT_ORIGINAL;
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ error("Invalid SBAT policy\n");
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if ((sbatlvlrt = runtime_read_efi_variable(SBATLEVELRT_VARNAME)) == NULL) {
|
|
||||||
+ error("Unable to read SbatLevelRT\n");
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ sbat_current = (const char *)buffer_read_pointer(sbatlvlrt);
|
|
||||||
+
|
|
||||||
+ if (!fetch_sbat_datestamp(sbat_current, sbatlvlrt->size, ¤t_date)
|
|
||||||
+ || !fetch_sbat_datestamp(sbat_candidate, strlen(sbat_candidate), &candidate_date)) {
|
|
||||||
+ error("Unable to get SBAT timestamp\n");
|
|
||||||
+ goto fail;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ debug("Current SBAT datestampe: %u\n", current_date);
|
|
||||||
+ debug("Candidate SBAT datestampe: %u\n", candidate_date);
|
|
||||||
+
|
|
||||||
+ if (current_date >= candidate_date && sbat_reset == false) {
|
|
||||||
+ debug("Use current SbatLevel\n");
|
|
||||||
+ result = sbatlvlrt;
|
|
||||||
+ } else {
|
|
||||||
+ debug("Use candidate SbatLevel\n");
|
|
||||||
+ buffer_free(sbatlvlrt);
|
|
||||||
+
|
|
||||||
+ /* Copy the candidate SbatLevel string without the terminating null */
|
|
||||||
+ if ((result = buffer_alloc_write(strlen(sbat_candidate))) == NULL
|
|
||||||
+ || !buffer_put(result, sbat_candidate, strlen(sbat_candidate)))
|
|
||||||
+ goto fail;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return result;
|
|
||||||
+
|
|
||||||
+fail:
|
|
||||||
+ buffer_free(sbatlvlrt);
|
|
||||||
+ buffer_free(result);
|
|
||||||
+
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
enum {
|
|
||||||
HASH_STRATEGY_EVENT,
|
|
||||||
HASH_STRATEGY_DATA,
|
|
||||||
@@ -114,6 +267,11 @@ efi_variable_authority_get_record(const
|
|
||||||
} else
|
|
||||||
if (!strcmp(var_short_name, "MokListRT")) {
|
|
||||||
db_name = "MokList";
|
|
||||||
+ } else
|
|
||||||
+ if (!strcmp(var_short_name, "SbatLevel")) {
|
|
||||||
+ if (ctx->sbatlevel != NULL)
|
|
||||||
+ return efi_sbatlevel_get_record(ctx->sbatlevel);
|
|
||||||
+ return runtime_read_efi_variable(var_name);
|
|
||||||
} else {
|
|
||||||
/* Read as-is (this could be SbatLevel, or some other variable that's not
|
|
||||||
* a signature db). */
|
|
||||||
Index: pcr-oracle-0.5.4/src/eventlog.c
|
|
||||||
===================================================================
|
|
||||||
--- pcr-oracle-0.5.4.orig/src/eventlog.c
|
|
||||||
+++ pcr-oracle-0.5.4/src/eventlog.c
|
|
||||||
@@ -1148,6 +1148,7 @@ tpm_event_log_rehash_ctx_init(tpm_event_
|
|
||||||
void
|
|
||||||
tpm_event_log_rehash_ctx_destroy(tpm_event_log_rehash_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
+ buffer_free(ctx->sbatlevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Index: pcr-oracle-0.5.4/src/eventlog.h
|
|
||||||
===================================================================
|
|
||||||
--- pcr-oracle-0.5.4.orig/src/eventlog.h
|
|
||||||
+++ pcr-oracle-0.5.4/src/eventlog.h
|
|
||||||
@@ -209,6 +209,8 @@ typedef struct tpm_event_log_rehash_ctx
|
|
||||||
/* This get set when the user specifies --next-kernel */
|
|
||||||
char * boot_entry_path;
|
|
||||||
uapi_boot_entry_t * boot_entry;
|
|
||||||
+
|
|
||||||
+ buffer_t * sbatlevel;
|
|
||||||
} tpm_event_log_rehash_ctx_t;
|
|
||||||
|
|
||||||
#define GRUB_COMMAND_ARGV_MAX 32
|
|
@@ -1,35 +0,0 @@
|
|||||||
From bfd8520b4af3743a51046c83a1382fe1e66cc95a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Gary Lin <glin@suse.com>
|
|
||||||
Date: Thu, 26 Dec 2024 13:46:45 +0800
|
|
||||||
Subject: [PATCH] Fix event rehash for grub files on system partition
|
|
||||||
|
|
||||||
The crypto device logged by grub may not be 'crypto0'. It could begin
|
|
||||||
with the 'cryptouuid' prefix like this:
|
|
||||||
|
|
||||||
cryptouuid/4203418d2b034db5b9476f013ee3dc80
|
|
||||||
|
|
||||||
This commit adds the additional prefix matching for 'cryptouuid' to make
|
|
||||||
pcr-oracle to search the file on system partition.
|
|
||||||
|
|
||||||
Signed-off-by: Gary Lin <glin@suse.com>
|
|
||||||
---
|
|
||||||
src/eventlog.c | 3 ++-
|
|
||||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/src/eventlog.c b/src/eventlog.c
|
|
||||||
index 4277d42..c49599d 100644
|
|
||||||
--- a/src/eventlog.c
|
|
||||||
+++ b/src/eventlog.c
|
|
||||||
@@ -578,7 +578,8 @@ __tpm_event_grub_file_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *pa
|
|
||||||
const tpm_evdigest_t *md = NULL;
|
|
||||||
|
|
||||||
debug(" re-hashing %s\n", __tpm_event_grub_file_describe(parsed));
|
|
||||||
- if (evspec->device == NULL || !strcmp(evspec->device, "crypto0")) {
|
|
||||||
+ if (evspec->device == NULL || !strcmp(evspec->device, "crypto0") ||
|
|
||||||
+ !strncmp(evspec->device, "cryptouuid", strlen("cryptouuid"))) {
|
|
||||||
debug(" assuming the file resides on system partition\n");
|
|
||||||
md = runtime_digest_rootfs_file(ctx->algo, evspec->path);
|
|
||||||
} else {
|
|
||||||
--
|
|
||||||
2.43.0
|
|
||||||
|
|
@@ -1,58 +0,0 @@
|
|||||||
From 61f9b77634578c0bf0c3bf6c4b386057e8661a1c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Gary Lin <glin@suse.com>
|
|
||||||
Date: Wed, 12 Jun 2024 14:41:38 +0800
|
|
||||||
Subject: [PATCH] testcase: fix playback on empty EFI variables
|
|
||||||
|
|
||||||
For systems in UEFI Setup mode, there is no PK, KEK, or db. However,
|
|
||||||
those variables are still recorded in the TPM event log with zero
|
|
||||||
length. To avoid failing on reading those files, this commit changes the
|
|
||||||
file reading flag so that testcase playback won't stop on those EFI
|
|
||||||
variables.
|
|
||||||
|
|
||||||
Signed-off-by: Gary Lin <glin@suse.com>
|
|
||||||
---
|
|
||||||
src/testcase.c | 17 ++++++++++++++---
|
|
||||||
1 file changed, 14 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/testcase.c b/src/testcase.c
|
|
||||||
index f74238b..998aedd 100644
|
|
||||||
--- a/src/testcase.c
|
|
||||||
+++ b/src/testcase.c
|
|
||||||
@@ -224,12 +224,18 @@ testcase_write_file(const char *directory, const char *name, const buffer_t *bp)
|
|
||||||
}
|
|
||||||
|
|
||||||
static buffer_t *
|
|
||||||
-testcase_read_file(const char *directory, const char *name)
|
|
||||||
+__testcase_read_file(const char *directory, const char *name, int flags)
|
|
||||||
{
|
|
||||||
char path[PATH_MAX];
|
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/%s", directory, name);
|
|
||||||
- return runtime_read_file(path, 0);
|
|
||||||
+ return runtime_read_file(path, flags);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static buffer_t *
|
|
||||||
+testcase_read_file(const char *directory, const char *name)
|
|
||||||
+{
|
|
||||||
+ return __testcase_read_file(directory, name, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
testcase_t *
|
|
||||||
@@ -314,7 +320,12 @@ testcase_record_efi_variable(testcase_t *tc, const char *name, const buffer_t *d
|
|
||||||
buffer_t *
|
|
||||||
testcase_playback_efi_variable(testcase_t *tc, const char *name)
|
|
||||||
{
|
|
||||||
- return testcase_read_file(tc->efi_directory, name);
|
|
||||||
+ /* For systems in UEFI Setup mode, there is no PK, KEK, or db, but those
|
|
||||||
+ * variables are still recorded in the TPM event log with zero length.
|
|
||||||
+ * Set the file reading flag to skip those EFI variable files.
|
|
||||||
+ */
|
|
||||||
+ return __testcase_read_file(tc->efi_directory, name,
|
|
||||||
+ RUNTIME_MISSING_FILE_OKAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
--
|
|
||||||
2.35.3
|
|
||||||
|
|
@@ -1,412 +0,0 @@
|
|||||||
From 9489d98463a596ec8e4ba9f1f4a2b2af91c0968b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Alberto Planas <aplanas@suse.com>
|
|
||||||
Date: Wed, 10 Jan 2024 15:32:07 +0100
|
|
||||||
Subject: [PATCH 1/8] Print the measured kernel
|
|
||||||
|
|
||||||
The debug output can be missleading, as print information about the
|
|
||||||
current event log, but not about the measured element, that can be
|
|
||||||
different as in the kernel case.
|
|
||||||
|
|
||||||
Signed-off-by: Alberto Planas <aplanas@suse.com>
|
|
||||||
---
|
|
||||||
src/efi-application.c | 6 ++++++
|
|
||||||
1 file changed, 6 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/src/efi-application.c b/src/efi-application.c
|
|
||||||
index 3e80083..2fd33ec 100644
|
|
||||||
--- a/src/efi-application.c
|
|
||||||
+++ b/src/efi-application.c
|
|
||||||
@@ -292,6 +292,12 @@ __tpm_event_efi_bsa_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *pars
|
|
||||||
|
|
||||||
/* The next boot can have a different kernel */
|
|
||||||
if (sdb_is_kernel(evspec->efi_application) && ctx->boot_entry) {
|
|
||||||
+ /* TODO: the parsed data type did not change, so all
|
|
||||||
+ * the description correspond to the current event
|
|
||||||
+ * log, and not the asset that has been measured. The
|
|
||||||
+ * debug output can then be missleading.
|
|
||||||
+ */
|
|
||||||
+ debug("Measuring %s\n", ctx->boot_entry->image_path);
|
|
||||||
new_application = ctx->boot_entry->image_path;
|
|
||||||
if (new_application) {
|
|
||||||
evspec_clone = *evspec;
|
|
||||||
|
|
||||||
From d8d97a3c233e326e0b1836b77fa08f483ea8f410 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Alberto Planas <aplanas@suse.com>
|
|
||||||
Date: Wed, 10 Jan 2024 15:51:45 +0100
|
|
||||||
Subject: [PATCH 2/8] Rename variable to cmdline
|
|
||||||
|
|
||||||
Signed-off-by: Alberto Planas <aplanas@suse.com>
|
|
||||||
---
|
|
||||||
src/eventlog.c | 15 ++++++++-------
|
|
||||||
1 file changed, 8 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/eventlog.c b/src/eventlog.c
|
|
||||||
index 4277d42..377f4d6 100644
|
|
||||||
--- a/src/eventlog.c
|
|
||||||
+++ b/src/eventlog.c
|
|
||||||
@@ -790,8 +790,8 @@ static const tpm_evdigest_t *
|
|
||||||
__tpm_event_systemd_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *parsed, tpm_event_log_rehash_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
const uapi_boot_entry_t *boot_entry = ctx->boot_entry;
|
|
||||||
- char initrd[2048];
|
|
||||||
- char initrd_utf16[4096];
|
|
||||||
+ char cmdline[2048];
|
|
||||||
+ char cmdline_utf16[4096];
|
|
||||||
unsigned int len;
|
|
||||||
|
|
||||||
/* If no --next-kernel option was given, do not rehash anything */
|
|
||||||
@@ -804,15 +804,16 @@ __tpm_event_systemd_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *pars
|
|
||||||
}
|
|
||||||
|
|
||||||
debug("Next boot entry expected from: %s %s\n", boot_entry->title, boot_entry->version? : "");
|
|
||||||
- snprintf(initrd, sizeof(initrd), "initrd=%s %s",
|
|
||||||
+ snprintf(cmdline, sizeof(cmdline), "initrd=%s %s",
|
|
||||||
path_unix2dos(boot_entry->initrd_path),
|
|
||||||
boot_entry->options? : "");
|
|
||||||
+ debug("Measuring Kernel command line: %s\n", cmdline);
|
|
||||||
|
|
||||||
- len = (strlen(initrd) + 1) << 1;
|
|
||||||
- assert(len <= sizeof(initrd_utf16));
|
|
||||||
- __convert_to_utf16le(initrd, strlen(initrd) + 1, initrd_utf16, len);
|
|
||||||
+ len = (strlen(cmdline) + 1) << 1;
|
|
||||||
+ assert(len <= sizeof(cmdline_utf16));
|
|
||||||
+ __convert_to_utf16le(cmdline, strlen(cmdline) + 1, cmdline_utf16, len);
|
|
||||||
|
|
||||||
- return digest_compute(ctx->algo, initrd_utf16, len);
|
|
||||||
+ return digest_compute(ctx->algo, cmdline_utf16, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
From 4f8e3f4760ff7fe97df1e6af569d049e30f3ee06 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Alberto Planas <aplanas@suse.com>
|
|
||||||
Date: Wed, 10 Jan 2024 15:55:41 +0100
|
|
||||||
Subject: [PATCH 3/8] Add debug output for initrd
|
|
||||||
|
|
||||||
Signed-off-by: Alberto Planas <aplanas@suse.com>
|
|
||||||
---
|
|
||||||
src/eventlog.c | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/src/eventlog.c b/src/eventlog.c
|
|
||||||
index 377f4d6..3574a4d 100644
|
|
||||||
--- a/src/eventlog.c
|
|
||||||
+++ b/src/eventlog.c
|
|
||||||
@@ -877,6 +877,7 @@ __tpm_event_tag_initrd_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *p
|
|
||||||
}
|
|
||||||
|
|
||||||
debug("Next boot entry expected from: %s %s\n", boot_entry->title, boot_entry->version? : "");
|
|
||||||
+ debug("Measuring initrd: %s\n", boot_entry->initrd_path);
|
|
||||||
return runtime_digest_efi_file(ctx->algo, boot_entry->initrd_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
From 90ee8dab9d972b741bc0c27a04a872afbecdef82 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Alberto Planas <aplanas@suse.com>
|
|
||||||
Date: Wed, 10 Jan 2024 18:54:04 +0100
|
|
||||||
Subject: [PATCH 4/8] Add debug output during extension
|
|
||||||
|
|
||||||
Signed-off-by: Alberto Planas <aplanas@suse.com>
|
|
||||||
---
|
|
||||||
src/oracle.c | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/src/oracle.c b/src/oracle.c
|
|
||||||
index 1cafafc..0afd910 100644
|
|
||||||
--- a/src/oracle.c
|
|
||||||
+++ b/src/oracle.c
|
|
||||||
@@ -366,6 +366,7 @@ pcr_bank_extend_register(tpm_pcr_bank_t *bank, unsigned int pcr_index, const tpm
|
|
||||||
static void
|
|
||||||
predictor_extend_hash(struct predictor *pred, unsigned int pcr_index, const tpm_evdigest_t *d)
|
|
||||||
{
|
|
||||||
+ debug("Extend PCR#%d: %s\n", pcr_index, digest_print(d));
|
|
||||||
pcr_bank_extend_register(&pred->prediction, pcr_index, d);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
From 5133fe6f3c00a41aee362a51621a278dd472497e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Alberto Planas <aplanas@suse.com>
|
|
||||||
Date: Thu, 11 Jan 2024 14:09:03 +0100
|
|
||||||
Subject: [PATCH 5/8] Update the EFI image info before rehash
|
|
||||||
|
|
||||||
If the new EFI image is in a new place, the image information stored in
|
|
||||||
the parsed event should be updated, so the rehash will use this
|
|
||||||
information instead of the one from the event log.
|
|
||||||
|
|
||||||
Signed-off-by: Alberto Planas <aplanas@suse.com>
|
|
||||||
---
|
|
||||||
src/efi-application.c | 8 ++++----
|
|
||||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/efi-application.c b/src/efi-application.c
|
|
||||||
index 2fd33ec..842bca6 100644
|
|
||||||
--- a/src/efi-application.c
|
|
||||||
+++ b/src/efi-application.c
|
|
||||||
@@ -40,7 +40,7 @@
|
|
||||||
*/
|
|
||||||
static const tpm_evdigest_t * __tpm_event_efi_bsa_rehash(const tpm_event_t *, const tpm_parsed_event_t *, tpm_event_log_rehash_ctx_t *);
|
|
||||||
static bool __tpm_event_efi_bsa_extract_location(tpm_parsed_event_t *parsed);
|
|
||||||
-static bool __tpm_event_efi_bsa_inspect_image(tpm_parsed_event_t *parsed);
|
|
||||||
+static bool __tpm_event_efi_bsa_inspect_image(struct efi_bsa_event *evspec);
|
|
||||||
|
|
||||||
static void
|
|
||||||
__tpm_event_efi_bsa_destroy(tpm_parsed_event_t *parsed)
|
|
||||||
@@ -111,7 +111,7 @@ __tpm_event_parse_efi_bsa(tpm_event_t *ev, tpm_parsed_event_t *parsed, buffer_t
|
|
||||||
assign_string(&ctx->efi_partition, evspec->efi_partition);
|
|
||||||
else
|
|
||||||
assign_string(&evspec->efi_partition, ctx->efi_partition);
|
|
||||||
- __tpm_event_efi_bsa_inspect_image(parsed);
|
|
||||||
+ __tpm_event_efi_bsa_inspect_image(evspec);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
@@ -150,9 +150,8 @@ __tpm_event_efi_bsa_extract_location(tpm_parsed_event_t *parsed)
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
-__tpm_event_efi_bsa_inspect_image(tpm_parsed_event_t *parsed)
|
|
||||||
+__tpm_event_efi_bsa_inspect_image(struct efi_bsa_event *evspec)
|
|
||||||
{
|
|
||||||
- struct efi_bsa_event *evspec = &parsed->efi_bsa_event;
|
|
||||||
char path[PATH_MAX];
|
|
||||||
const char *display_name;
|
|
||||||
buffer_t *img_data;
|
|
||||||
@@ -302,6 +301,7 @@ __tpm_event_efi_bsa_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *pars
|
|
||||||
if (new_application) {
|
|
||||||
evspec_clone = *evspec;
|
|
||||||
evspec_clone.efi_application = strdup(new_application);
|
|
||||||
+ __tpm_event_efi_bsa_inspect_image(&evspec_clone);
|
|
||||||
evspec = &evspec_clone;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
From 93cbe02ca05297c638b1ac7f32b3da3a6cd2f684 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Alberto Planas <aplanas@suse.com>
|
|
||||||
Date: Thu, 11 Jan 2024 14:35:07 +0100
|
|
||||||
Subject: [PATCH 6/8] Bump version to 0.5.5
|
|
||||||
|
|
||||||
Signed-off-by: Alberto Planas <aplanas@suse.com>
|
|
||||||
---
|
|
||||||
configure | 2 +-
|
|
||||||
microconf/version | 2 +-
|
|
||||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/configure b/configure
|
|
||||||
index 1dccbdc..854cc0a 100755
|
|
||||||
--- a/configure
|
|
||||||
+++ b/configure
|
|
||||||
@@ -12,7 +12,7 @@
|
|
||||||
# Invoke with --help for a description of options
|
|
||||||
#
|
|
||||||
# microconf:begin
|
|
||||||
-# version 0.5.4
|
|
||||||
+# version 0.5.5
|
|
||||||
# require libtss2
|
|
||||||
# require json
|
|
||||||
# disable debug-authenticode
|
|
||||||
diff --git a/microconf/version b/microconf/version
|
|
||||||
index 7e913d9..591473f 100644
|
|
||||||
--- a/microconf/version
|
|
||||||
+++ b/microconf/version
|
|
||||||
@@ -1 +1 @@
|
|
||||||
-uc_version=0.5.4
|
|
||||||
+uc_version=0.5.5
|
|
||||||
|
|
||||||
From e622620a8de5eaf499265adf6c5e8d2ecdaa295b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Alberto Planas <aplanas@suse.com>
|
|
||||||
Date: Mon, 26 Feb 2024 13:34:13 +0100
|
|
||||||
Subject: [PATCH 7/8] Add secure boot detector
|
|
||||||
|
|
||||||
Signed-off-by: Alberto Planas <aplanas@suse.com>
|
|
||||||
---
|
|
||||||
Makefile.in | 3 ++-
|
|
||||||
src/eventlog.h | 2 ++
|
|
||||||
src/secure_boot.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
3 files changed, 48 insertions(+), 1 deletion(-)
|
|
||||||
create mode 100644 src/secure_boot.c
|
|
||||||
|
|
||||||
diff --git a/Makefile.in b/Makefile.in
|
|
||||||
index 02a915b..9698253 100644
|
|
||||||
--- a/Makefile.in
|
|
||||||
+++ b/Makefile.in
|
|
||||||
@@ -34,7 +34,8 @@ ORACLE_SRCS = oracle.c \
|
|
||||||
store.c \
|
|
||||||
util.c \
|
|
||||||
sd-boot.c \
|
|
||||||
- uapi.c
|
|
||||||
+ uapi.c \
|
|
||||||
+ secure_boot.c
|
|
||||||
ORACLE_OBJS = $(addprefix build/,$(patsubst %.c,%.o,$(ORACLE_SRCS)))
|
|
||||||
|
|
||||||
all: $(TOOLS) $(MANPAGES)
|
|
||||||
diff --git a/src/eventlog.h b/src/eventlog.h
|
|
||||||
index 3741b58..8af5eb0 100644
|
|
||||||
--- a/src/eventlog.h
|
|
||||||
+++ b/src/eventlog.h
|
|
||||||
@@ -323,4 +323,6 @@ extern bool shim_variable_name_valid(const char *name);
|
|
||||||
extern const char * shim_variable_get_rtname(const char *name);
|
|
||||||
extern const char * shim_variable_get_full_rtname(const char *name);
|
|
||||||
|
|
||||||
+extern bool secure_boot_enabled();
|
|
||||||
+
|
|
||||||
#endif /* EVENTLOG_H */
|
|
||||||
diff --git a/src/secure_boot.c b/src/secure_boot.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..215baa6
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/src/secure_boot.c
|
|
||||||
@@ -0,0 +1,44 @@
|
|
||||||
+/*
|
|
||||||
+ * Copyright (C) 2023 SUSE LLC
|
|
||||||
+ *
|
|
||||||
+ * This program is free software; you can redistribute it and/or modify
|
|
||||||
+ * it under the terms of the GNU General Public License as published by
|
|
||||||
+ * the Free Software Foundation; either version 2 of the License, or
|
|
||||||
+ * (at your option) any later version.
|
|
||||||
+ *
|
|
||||||
+ * This program is distributed in the hope that it will be useful,
|
|
||||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
+ * GNU General Public License for more details.
|
|
||||||
+ *
|
|
||||||
+ * You should have received a copy of the GNU General Public License
|
|
||||||
+ * along with this program; if not, write to the Free Software
|
|
||||||
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
+ *
|
|
||||||
+ * Written by Alberto Planas <aplanas@suse.com>
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include "bufparser.h"
|
|
||||||
+#include "runtime.h"
|
|
||||||
+
|
|
||||||
+#define SECURE_BOOT_EFIVAR_NAME "SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c"
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+bool
|
|
||||||
+secure_boot_enabled()
|
|
||||||
+{
|
|
||||||
+ buffer_t *data;
|
|
||||||
+ uint8_t enabled;
|
|
||||||
+
|
|
||||||
+ data = runtime_read_efi_variable(SECURE_BOOT_EFIVAR_NAME);
|
|
||||||
+ if (data == NULL) {
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (!buffer_get_u8(data, &enabled)) {
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return enabled == 1;
|
|
||||||
+}
|
|
||||||
|
|
||||||
From 211502ec5cac7e252f8af251ee34872f7adae9ca Mon Sep 17 00:00:00 2001
|
|
||||||
From: Alberto Planas <aplanas@suse.com>
|
|
||||||
Date: Mon, 26 Feb 2024 14:52:37 +0100
|
|
||||||
Subject: [PATCH 8/8] Detect when device path is missing for kernel
|
|
||||||
|
|
||||||
Signed-off-by: Alberto Planas <aplanas@suse.com>
|
|
||||||
---
|
|
||||||
src/efi-application.c | 48 ++++++++++++++++++++++++++++++++++++++++---
|
|
||||||
src/sd-boot.c | 3 +++
|
|
||||||
2 files changed, 48 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/efi-application.c b/src/efi-application.c
|
|
||||||
index 842bca6..1f434fc 100644
|
|
||||||
--- a/src/efi-application.c
|
|
||||||
+++ b/src/efi-application.c
|
|
||||||
@@ -42,6 +42,8 @@ static const tpm_evdigest_t * __tpm_event_efi_bsa_rehash(const tpm_event_t *, co
|
|
||||||
static bool __tpm_event_efi_bsa_extract_location(tpm_parsed_event_t *parsed);
|
|
||||||
static bool __tpm_event_efi_bsa_inspect_image(struct efi_bsa_event *evspec);
|
|
||||||
|
|
||||||
+static bool __is_shim_issue(const tpm_event_t *ev, const struct efi_bsa_event *evspec);
|
|
||||||
+
|
|
||||||
static void
|
|
||||||
__tpm_event_efi_bsa_destroy(tpm_parsed_event_t *parsed)
|
|
||||||
{
|
|
||||||
@@ -114,6 +116,15 @@ __tpm_event_parse_efi_bsa(tpm_event_t *ev, tpm_parsed_event_t *parsed, buffer_t
|
|
||||||
__tpm_event_efi_bsa_inspect_image(evspec);
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* When the shim issue is present the efi_application will be
|
|
||||||
+ * empty. The binary path will be reconstructed with the
|
|
||||||
+ * --next-kernel parameter, but to generate the full path the
|
|
||||||
+ * `efi_partition` is needed.
|
|
||||||
+ */
|
|
||||||
+ if (__is_shim_issue(ev, evspec))
|
|
||||||
+ assign_string(&evspec->efi_partition, ctx->efi_partition);
|
|
||||||
+
|
|
||||||
+
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -273,6 +284,31 @@ efi_application_extract_signer(const tpm_parsed_event_t *parsed)
|
|
||||||
return authenticode_get_signer(evspec->img_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static bool __is_shim_issue(const tpm_event_t *ev, const struct efi_bsa_event *evspec)
|
|
||||||
+{
|
|
||||||
+ /* When secure boot is enabled and shim is installed,
|
|
||||||
+ * systemd-boot installs some security overrides that will
|
|
||||||
+ * delegate into shim (via shim_validate from systemd-boot)
|
|
||||||
+ * the validation of the kernel signature.
|
|
||||||
+ *
|
|
||||||
+ * The shim_validate function receives the device path from
|
|
||||||
+ * the firmware, and is used to load the kernel into memory.
|
|
||||||
+ * At the end call shim_verify from shim, but pass only the
|
|
||||||
+ * buffer with the loaded image.
|
|
||||||
+ *
|
|
||||||
+ * The net result is that the event log
|
|
||||||
+ * EV_EFI_BOOT_SERVICES_APPLICATION registered by shim_verify
|
|
||||||
+ * will not contain the device path that pcr-oracle requires
|
|
||||||
+ * to rehash the binary.
|
|
||||||
+ *
|
|
||||||
+ * So far only the kernel is presenting this issue (when
|
|
||||||
+ * systemd-boot is used, GRUB2 needs to be evaluated), so this
|
|
||||||
+ * can be detected if there is an event registered in PCR 4
|
|
||||||
+ * without path.
|
|
||||||
+ */
|
|
||||||
+ return (secure_boot_enabled() && ev->pcr_index == 4 && !evspec->efi_application);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static const tpm_evdigest_t *
|
|
||||||
__tpm_event_efi_bsa_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *parsed, tpm_event_log_rehash_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
@@ -284,13 +320,19 @@ __tpm_event_efi_bsa_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *pars
|
|
||||||
* We're not yet prepared to handle these, so we hope the user doesn't mess with them, and
|
|
||||||
* return the original digest from the event log.
|
|
||||||
*/
|
|
||||||
- if (!evspec->efi_application) {
|
|
||||||
- debug("Unable to locate boot service application - probably not a file\n");
|
|
||||||
+ if (!evspec->efi_application && !(__is_shim_issue(ev, evspec) && ctx->boot_entry)) {
|
|
||||||
+ if (__is_shim_issue(ev, evspec) && !ctx->boot_entry)
|
|
||||||
+ debug("Unable to locate boot service application - missing device path because shim issue");
|
|
||||||
+ else
|
|
||||||
+ debug("Unable to locate boot service application - probably not a file\n");
|
|
||||||
return tpm_event_get_digest(ev, ctx->algo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The next boot can have a different kernel */
|
|
||||||
- if (sdb_is_kernel(evspec->efi_application) && ctx->boot_entry) {
|
|
||||||
+ if ((sdb_is_kernel(evspec->efi_application) || __is_shim_issue(ev, evspec)) && ctx->boot_entry) {
|
|
||||||
+ if (__is_shim_issue(ev, evspec))
|
|
||||||
+ debug("Empty device path for the kernel - building one based on next kernel\n");
|
|
||||||
+
|
|
||||||
/* TODO: the parsed data type did not change, so all
|
|
||||||
* the description correspond to the current event
|
|
||||||
* log, and not the asset that has been measured. The
|
|
||||||
diff --git a/src/sd-boot.c b/src/sd-boot.c
|
|
||||||
index cbdaa49..ede2569 100644
|
|
||||||
--- a/src/sd-boot.c
|
|
||||||
+++ b/src/sd-boot.c
|
|
||||||
@@ -138,6 +138,9 @@ sdb_is_kernel(const char *application)
|
|
||||||
char *path_copy;
|
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
+ if (!application)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
match = get_valid_kernel_entry_tokens();
|
|
||||||
path_copy = strdup(application);
|
|
||||||
|
|
@@ -1,335 +0,0 @@
|
|||||||
From fca4a51b9aac712b3adc5b6b187cc31a8391bcf6 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Alberto Planas <aplanas@suse.com>
|
|
||||||
Date: Fri, 22 Mar 2024 22:44:41 +0100
|
|
||||||
Subject: [PATCH] GRUB: predict cmdline, linux and initrd lines
|
|
||||||
|
|
||||||
Signed-off-by: Alberto Planas <aplanas@suse.com>
|
|
||||||
---
|
|
||||||
src/eventlog.c | 195 ++++++++++++++++++++++++++++++++++++++-----------
|
|
||||||
src/eventlog.h | 26 ++++---
|
|
||||||
2 files changed, 169 insertions(+), 52 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/eventlog.c b/src/eventlog.c
|
|
||||||
index db18f41..727f6a9 100644
|
|
||||||
--- a/src/eventlog.c
|
|
||||||
+++ b/src/eventlog.c
|
|
||||||
@@ -549,14 +549,66 @@ tpm_event_decode_uuid(const unsigned char *data)
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * For files residing on the EFI partition, grub usually formats these as
|
|
||||||
+ * (hdX,gptY)/EFI/BOOT/some.file
|
|
||||||
+ * Once it has determined the final root device, the device part will be
|
|
||||||
+ * omitted (eg for kernel and initrd).
|
|
||||||
+ */
|
|
||||||
+static bool
|
|
||||||
+__grub_file_parse(grub_file_t *grub_file, const char *value)
|
|
||||||
+{
|
|
||||||
+ if (value[0] == '/') {
|
|
||||||
+ grub_file->device = NULL;
|
|
||||||
+ grub_file->path = strdup(value);
|
|
||||||
+ } else if (value[0] == '(') {
|
|
||||||
+ char *copy = strdup(value);
|
|
||||||
+ char *path;
|
|
||||||
+
|
|
||||||
+ if ((path = strchr(copy, ')')) == NULL) {
|
|
||||||
+ free(copy);
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ *path++ = '\0';
|
|
||||||
+
|
|
||||||
+ grub_file->device = strdup(copy + 1);
|
|
||||||
+ grub_file->path = strdup(path);
|
|
||||||
+ free(copy);
|
|
||||||
+ } else {
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static const char *
|
|
||||||
+__grub_file_join(grub_file_t grub_file)
|
|
||||||
+{
|
|
||||||
+ static char path[PATH_MAX];
|
|
||||||
+
|
|
||||||
+ if (grub_file.device == NULL)
|
|
||||||
+ snprintf(path, sizeof(path), "%s", grub_file.path);
|
|
||||||
+ else
|
|
||||||
+ snprintf(path, sizeof(path), "(%s)%s", grub_file.device, grub_file.path);
|
|
||||||
+
|
|
||||||
+ return path;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+__grub_file_destroy(grub_file_t *grub_file)
|
|
||||||
+{
|
|
||||||
+ drop_string(&grub_file->device);
|
|
||||||
+ drop_string(&grub_file->path);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Handle IPL events, which grub2 and sd-boot uses to hide its stuff in
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
__tpm_event_grub_file_destroy(tpm_parsed_event_t *parsed)
|
|
||||||
{
|
|
||||||
- drop_string(&parsed->grub_file.device);
|
|
||||||
- drop_string(&parsed->grub_file.path);
|
|
||||||
+ __grub_file_destroy(&parsed->grub_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
@@ -564,10 +616,7 @@ __tpm_event_grub_file_describe(const tpm_parsed_event_t *parsed)
|
|
||||||
{
|
|
||||||
static char buffer[1024];
|
|
||||||
|
|
||||||
- if (parsed->grub_file.device == NULL)
|
|
||||||
- snprintf(buffer, sizeof(buffer), "grub2 file load from %s", parsed->grub_file.path);
|
|
||||||
- else
|
|
||||||
- snprintf(buffer, sizeof(buffer), "grub2 file load from (%s)%s", parsed->grub_file.device, parsed->grub_file.path);
|
|
||||||
+ snprintf(buffer, sizeof(buffer), "grub2 file load from %s", __grub_file_join(parsed->grub_file));
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -575,7 +624,7 @@ __tpm_event_grub_file_describe(const tpm_parsed_event_t *parsed)
|
|
||||||
static const tpm_evdigest_t *
|
|
||||||
__tpm_event_grub_file_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *parsed, tpm_event_log_rehash_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
- const struct grub_file_event *evspec = &parsed->grub_file;
|
|
||||||
+ const grub_file_event *evspec = &parsed->grub_file;
|
|
||||||
const tpm_evdigest_t *md = NULL;
|
|
||||||
|
|
||||||
debug(" re-hashing %s\n", __tpm_event_grub_file_describe(parsed));
|
|
||||||
@@ -606,35 +655,11 @@ __tpm_event_grub_file_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *pa
|
|
||||||
return md;
|
|
||||||
}
|
|
||||||
|
|
||||||
-/*
|
|
||||||
- * For files residing on the EFI partition, grub usually formats these as
|
|
||||||
- * (hdX,gptY)/EFI/BOOT/some.file
|
|
||||||
- * Once it has determined the final root device, the device part will be
|
|
||||||
- * omitted (eg for kernel and initrd).
|
|
||||||
- */
|
|
||||||
static bool
|
|
||||||
__tpm_event_grub_file_event_parse(tpm_event_t *ev, tpm_parsed_event_t *parsed, const char *value)
|
|
||||||
{
|
|
||||||
- if (value[0] == '/') {
|
|
||||||
- parsed->grub_file.device = NULL;
|
|
||||||
- parsed->grub_file.path = strdup(value);
|
|
||||||
- } else if (value[0] == '(') {
|
|
||||||
- char *copy = strdup(value);
|
|
||||||
- char *path;
|
|
||||||
-
|
|
||||||
- if ((path = strchr(copy, ')')) == NULL) {
|
|
||||||
- free(copy);
|
|
||||||
- return false;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- *path++ = '\0';
|
|
||||||
-
|
|
||||||
- parsed->grub_file.device = strdup(copy + 1);
|
|
||||||
- parsed->grub_file.path = strdup(path);
|
|
||||||
- free(copy);
|
|
||||||
- } else {
|
|
||||||
+ if (!__grub_file_parse(&parsed->grub_file, value))
|
|
||||||
return false;
|
|
||||||
- }
|
|
||||||
|
|
||||||
parsed->event_subtype = GRUB_EVENT_FILE;
|
|
||||||
parsed->destroy = __tpm_event_grub_file_destroy;
|
|
||||||
@@ -658,21 +683,87 @@ static const char *
|
|
||||||
__tpm_event_grub_command_describe(const tpm_parsed_event_t *parsed)
|
|
||||||
{
|
|
||||||
static char buffer[128];
|
|
||||||
+ static char *topic = NULL;
|
|
||||||
+
|
|
||||||
+ switch (parsed->event_subtype) {
|
|
||||||
+ case GRUB_EVENT_COMMAND:
|
|
||||||
+ topic = "grub2 command";
|
|
||||||
+ break;
|
|
||||||
+ case GRUB_EVENT_COMMAND_LINUX:
|
|
||||||
+ topic = "grub2 linux command";
|
|
||||||
+ break;
|
|
||||||
+ case GRUB_EVENT_COMMAND_INITRD:
|
|
||||||
+ topic = "grub2 initrd command";
|
|
||||||
+ break;
|
|
||||||
+ case GRUB_EVENT_KERNEL_CMDLINE:
|
|
||||||
+ topic = "grub2 kernel cmdline";
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ snprintf(buffer, sizeof(buffer), "%s \"%s\"", topic, parsed->grub_command.string);
|
|
||||||
|
|
||||||
- if (parsed->event_subtype == GRUB_EVENT_COMMAND)
|
|
||||||
- snprintf(buffer, sizeof(buffer), "grub2 command \"%s\"", parsed->grub_command.string);
|
|
||||||
- else
|
|
||||||
- snprintf(buffer, sizeof(buffer), "grub2 kernel cmdline \"%s\"", parsed->grub_command.string);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const tpm_evdigest_t *
|
|
||||||
__tpm_event_grub_command_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *parsed, tpm_event_log_rehash_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
- if (parsed->grub_command.string == NULL)
|
|
||||||
- return NULL;
|
|
||||||
+ char *str = NULL;
|
|
||||||
+ size_t sz = 0;
|
|
||||||
+ const tpm_evdigest_t *digest = NULL;
|
|
||||||
+ grub_file_t file;
|
|
||||||
+
|
|
||||||
+ switch (parsed->event_subtype) {
|
|
||||||
+ case GRUB_EVENT_COMMAND:
|
|
||||||
+ str = strdup(parsed->grub_command.string);
|
|
||||||
+ break;
|
|
||||||
+ case GRUB_EVENT_COMMAND_LINUX:
|
|
||||||
+ if (ctx->boot_entry && parsed->grub_command.file.path) {
|
|
||||||
+ file = (grub_file_t) {
|
|
||||||
+ .device = parsed->grub_command.file.device,
|
|
||||||
+ .path = ctx->boot_entry->image_path,
|
|
||||||
+ };
|
|
||||||
+ sz = snprintf(NULL, 0, "linux %s %s", __grub_file_join(file), ctx->boot_entry->options);
|
|
||||||
+ str = malloc(sz + 1);
|
|
||||||
+ snprintf(str, sz + 1, "linux %s %s", __grub_file_join(file), ctx->boot_entry->options);
|
|
||||||
+ debug("Hashed linux command: %s\n", str);
|
|
||||||
+ } else
|
|
||||||
+ str = strdup(parsed->grub_command.string);
|
|
||||||
+ break;
|
|
||||||
+ case GRUB_EVENT_COMMAND_INITRD:
|
|
||||||
+ if (ctx->boot_entry && parsed->grub_command.file.path) {
|
|
||||||
+ file = (grub_file_t) {
|
|
||||||
+ .device = parsed->grub_command.file.device,
|
|
||||||
+ .path = ctx->boot_entry->initrd_path,
|
|
||||||
+ };
|
|
||||||
+ sz = snprintf(NULL, 0, "initrd %s", __grub_file_join(file));
|
|
||||||
+ str = malloc(sz + 1);
|
|
||||||
+ snprintf(str, sz + 1, "initrd %s", __grub_file_join(file));
|
|
||||||
+ debug("Hashed initrd command: %s\n", str);
|
|
||||||
+ } else
|
|
||||||
+ str = strdup(parsed->grub_command.string);
|
|
||||||
+ break;
|
|
||||||
+ case GRUB_EVENT_KERNEL_CMDLINE:
|
|
||||||
+ if (ctx->boot_entry && parsed->grub_command.file.path) {
|
|
||||||
+ file = (grub_file_t) {
|
|
||||||
+ .device = parsed->grub_command.file.device,
|
|
||||||
+ .path = ctx->boot_entry->image_path,
|
|
||||||
+ };
|
|
||||||
+ sz = snprintf(NULL, 0, "%s %s", __grub_file_join(file), ctx->boot_entry->options);
|
|
||||||
+ str = malloc(sz + 1);
|
|
||||||
+ snprintf(str, sz + 1, "%s %s", __grub_file_join(file), ctx->boot_entry->options);
|
|
||||||
+ debug("Hashed kernel cmdline: %s\n", str);
|
|
||||||
+ } else
|
|
||||||
+ str = strdup(parsed->grub_command.string);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (str) {
|
|
||||||
+ digest = digest_compute(ctx->algo, str, strlen(str));
|
|
||||||
+ free(str);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- return digest_compute(ctx->algo, parsed->grub_command.string, strlen(parsed->grub_command.string));
|
|
||||||
+ return digest;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -703,15 +794,29 @@ __tpm_event_grub_command_event_parse(tpm_event_t *ev, tpm_parsed_event_t *parsed
|
|
||||||
keyword = copy;
|
|
||||||
arg = copy + wordlen;
|
|
||||||
|
|
||||||
+ if (!strcmp(keyword, "grub_cmd") && !strncmp(arg, "linux", strlen("linux"))) {
|
|
||||||
+ for (wordlen = 0; (cc = arg[wordlen]) && (cc != ' '); ++wordlen)
|
|
||||||
+ ;
|
|
||||||
+ if (arg[wordlen] == ' ' && !__grub_file_parse(&parsed->grub_command.file, arg + wordlen + 1))
|
|
||||||
+ goto failed;
|
|
||||||
+ parsed->event_subtype = GRUB_EVENT_COMMAND_LINUX;
|
|
||||||
+ } else
|
|
||||||
+ if (!strcmp(keyword, "grub_cmd") && !strncmp(arg, "initrd", strlen("initrd"))) {
|
|
||||||
+ for (wordlen = 0; (cc = arg[wordlen]) && (cc != ' '); ++wordlen)
|
|
||||||
+ ;
|
|
||||||
+ if (arg[wordlen] == ' ' && !__grub_file_parse(&parsed->grub_command.file, arg + wordlen + 1))
|
|
||||||
+ goto failed;
|
|
||||||
+ parsed->event_subtype = GRUB_EVENT_COMMAND_INITRD;
|
|
||||||
+ } else
|
|
||||||
if (!strcmp(keyword, "grub_cmd")) {
|
|
||||||
parsed->event_subtype = GRUB_EVENT_COMMAND;
|
|
||||||
} else
|
|
||||||
if (!strcmp(keyword, "kernel_cmdline")) {
|
|
||||||
+ if (!__grub_file_parse(&parsed->grub_command.file, arg))
|
|
||||||
+ goto failed;
|
|
||||||
parsed->event_subtype = GRUB_EVENT_KERNEL_CMDLINE;
|
|
||||||
- } else {
|
|
||||||
- free(copy);
|
|
||||||
- return false;
|
|
||||||
- }
|
|
||||||
+ } else
|
|
||||||
+ goto failed;
|
|
||||||
|
|
||||||
parsed->grub_command.string = strdup(arg);
|
|
||||||
for (argc = 0, s = strtok(arg, " \t"); s && argc < GRUB_COMMAND_ARGV_MAX - 1; s = strtok(NULL, " \t")) {
|
|
||||||
@@ -725,6 +830,10 @@ __tpm_event_grub_command_event_parse(tpm_event_t *ev, tpm_parsed_event_t *parsed
|
|
||||||
|
|
||||||
free(copy);
|
|
||||||
return true;
|
|
||||||
+
|
|
||||||
+failed:
|
|
||||||
+ free(copy);
|
|
||||||
+ return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
diff --git a/src/eventlog.h b/src/eventlog.h
|
|
||||||
index d142744..6a8c3a4 100644
|
|
||||||
--- a/src/eventlog.h
|
|
||||||
+++ b/src/eventlog.h
|
|
||||||
@@ -89,10 +89,12 @@ enum {
|
|
||||||
enum {
|
|
||||||
/* IPL subtypes for grub */
|
|
||||||
GRUB_EVENT_COMMAND = 0x0001,
|
|
||||||
- GRUB_EVENT_FILE = 0x0002,
|
|
||||||
- GRUB_EVENT_KERNEL_CMDLINE = 0x0003,
|
|
||||||
- SHIM_EVENT_VARIABLE = 0x0004,
|
|
||||||
- SYSTEMD_EVENT_VARIABLE = 0x0005,
|
|
||||||
+ GRUB_EVENT_COMMAND_LINUX = 0x0002,
|
|
||||||
+ GRUB_EVENT_COMMAND_INITRD = 0x0003,
|
|
||||||
+ GRUB_EVENT_FILE = 0x0004,
|
|
||||||
+ GRUB_EVENT_KERNEL_CMDLINE = 0x0005,
|
|
||||||
+ SHIM_EVENT_VARIABLE = 0x0006,
|
|
||||||
+ SYSTEMD_EVENT_VARIABLE = 0x0007,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
@@ -208,6 +210,13 @@ typedef struct tpm_event_log_rehash_ctx {
|
|
||||||
|
|
||||||
#define GRUB_COMMAND_ARGV_MAX 32
|
|
||||||
|
|
||||||
+typedef struct grub_file {
|
|
||||||
+ char * device;
|
|
||||||
+ char * path;
|
|
||||||
+} grub_file_t;
|
|
||||||
+
|
|
||||||
+typedef grub_file_t grub_file_event;
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Parsed event types
|
|
||||||
*/
|
|
||||||
@@ -247,13 +256,12 @@ typedef struct tpm_parsed_event {
|
|
||||||
/* for GRUB_COMMAND, GRUB_KERNEL_CMDLINE */
|
|
||||||
struct grub_command_event {
|
|
||||||
char * string;
|
|
||||||
- char * argv[GRUB_COMMAND_ARGV_MAX];
|
|
||||||
+ char * argv[GRUB_COMMAND_ARGV_MAX];
|
|
||||||
+ grub_file_t file;
|
|
||||||
} grub_command;
|
|
||||||
|
|
||||||
- struct grub_file_event {
|
|
||||||
- char * device;
|
|
||||||
- char * path;
|
|
||||||
- } grub_file;
|
|
||||||
+ /* for GRUB_FILE */
|
|
||||||
+ grub_file_event grub_file;
|
|
||||||
|
|
||||||
struct shim_event {
|
|
||||||
char * string;
|
|
@@ -1,188 +0,0 @@
|
|||||||
From b0c4c5fbdcc89b44cee2300c5a12cb5e8de0e446 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Alberto Planas <aplanas@suse.com>
|
|
||||||
Date: Wed, 13 Mar 2024 22:57:17 +0100
|
|
||||||
Subject: [PATCH] GRUB with BLS measure boot entries
|
|
||||||
|
|
||||||
This includes the boot entry file, the kernel and the initrd specified
|
|
||||||
in the entry file.
|
|
||||||
|
|
||||||
Signed-off-by: Alberto Planas <aplanas@suse.com>
|
|
||||||
---
|
|
||||||
src/eventlog.c | 21 +++++++++++++++++++--
|
|
||||||
src/eventlog.h | 1 +
|
|
||||||
src/oracle.c | 12 +++++++++---
|
|
||||||
src/sd-boot.c | 28 ++++++++++++++++++++++++----
|
|
||||||
src/sd-boot.h | 2 ++
|
|
||||||
src/uapi.h | 3 ++-
|
|
||||||
6 files changed, 57 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/eventlog.c b/src/eventlog.c
|
|
||||||
index 3574a4d..db18f41 100644
|
|
||||||
--- a/src/eventlog.c
|
|
||||||
+++ b/src/eventlog.c
|
|
||||||
@@ -33,6 +33,7 @@
|
|
||||||
#include "digest.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "uapi.h"
|
|
||||||
+#include "sd-boot.h"
|
|
||||||
|
|
||||||
#define TPM_EVENT_LOG_MAX_ALGOS 64
|
|
||||||
|
|
||||||
@@ -582,8 +583,24 @@ __tpm_event_grub_file_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *pa
|
|
||||||
debug(" assuming the file resides on system partition\n");
|
|
||||||
md = runtime_digest_rootfs_file(ctx->algo, evspec->path);
|
|
||||||
} else {
|
|
||||||
- debug(" assuming the file resides on EFI boot partition\n");
|
|
||||||
- md = runtime_digest_efi_file(ctx->algo, evspec->path);
|
|
||||||
+ if (sdb_is_boot_entry(evspec->path) && ctx->boot_entry_path) {
|
|
||||||
+ debug(" getting different boot entry file from EFI boot partition: %s\n",
|
|
||||||
+ ctx->boot_entry_path);
|
|
||||||
+ md = runtime_digest_rootfs_file(ctx->algo, ctx->boot_entry_path);
|
|
||||||
+ } else
|
|
||||||
+ if (sdb_is_kernel(evspec->path) && ctx->boot_entry) {
|
|
||||||
+ debug(" getting different kernel from EFI boot partition: %s\n",
|
|
||||||
+ ctx->boot_entry->image_path);
|
|
||||||
+ md = runtime_digest_efi_file(ctx->algo, ctx->boot_entry->image_path);
|
|
||||||
+ } else
|
|
||||||
+ if (sdb_is_initrd(evspec->path) && ctx->boot_entry) {
|
|
||||||
+ debug(" getting different initrd from EFI boot partition: %s\n",
|
|
||||||
+ ctx->boot_entry->initrd_path);
|
|
||||||
+ md = runtime_digest_efi_file(ctx->algo, ctx->boot_entry->initrd_path);
|
|
||||||
+ } else {
|
|
||||||
+ debug(" assuming the file resides on EFI boot partition\n");
|
|
||||||
+ md = runtime_digest_efi_file(ctx->algo, evspec->path);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
return md;
|
|
||||||
diff --git a/src/eventlog.h b/src/eventlog.h
|
|
||||||
index 8af5eb0..d142744 100644
|
|
||||||
--- a/src/eventlog.h
|
|
||||||
+++ b/src/eventlog.h
|
|
||||||
@@ -202,6 +202,7 @@ typedef struct tpm_event_log_rehash_ctx {
|
|
||||||
const pecoff_image_info_t *next_stage_img;
|
|
||||||
|
|
||||||
/* This get set when the user specifies --next-kernel */
|
|
||||||
+ char * boot_entry_path;
|
|
||||||
uapi_boot_entry_t * boot_entry;
|
|
||||||
} tpm_event_log_rehash_ctx_t;
|
|
||||||
|
|
||||||
diff --git a/src/oracle.c b/src/oracle.c
|
|
||||||
index 0afd910..ac48823 100644
|
|
||||||
--- a/src/oracle.c
|
|
||||||
+++ b/src/oracle.c
|
|
||||||
@@ -23,6 +23,7 @@
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
+#include <limits.h>
|
|
||||||
|
|
||||||
#include "oracle.h"
|
|
||||||
#include "util.h"
|
|
||||||
@@ -653,6 +654,7 @@ predictor_update_eventlog(struct predictor *pred)
|
|
||||||
tpm_event_log_rehash_ctx_t rehash_ctx;
|
|
||||||
tpm_event_t *ev, *stop_event = NULL;
|
|
||||||
bool okay = true;
|
|
||||||
+ char boot_entry_path[PATH_MAX];
|
|
||||||
|
|
||||||
predictor_pre_scan_eventlog(pred, &stop_event);
|
|
||||||
|
|
||||||
@@ -663,9 +665,13 @@ predictor_update_eventlog(struct predictor *pred)
|
|
||||||
* systemd ID of the next kernel entry to be booted.
|
|
||||||
* FIXME: we should probably hide this behind a target_platform function.
|
|
||||||
*/
|
|
||||||
- if (pred->boot_entry_id != NULL
|
|
||||||
- && !(rehash_ctx.boot_entry = sdb_identify_boot_entry(pred->boot_entry_id)))
|
|
||||||
- fatal("unable to identify next kernel \"%s\"\n", pred->boot_entry_id);
|
|
||||||
+ if (pred->boot_entry_id != NULL) {
|
|
||||||
+ snprintf(boot_entry_path, sizeof(boot_entry_path),
|
|
||||||
+ "%s/%s", UAPI_BOOT_DIRECTORY, pred->boot_entry_id);
|
|
||||||
+ assign_string(&rehash_ctx.boot_entry_path, boot_entry_path);
|
|
||||||
+ if (!(rehash_ctx.boot_entry = sdb_identify_boot_entry(pred->boot_entry_id)))
|
|
||||||
+ fatal("unable to identify next kernel \"%s\"\n", pred->boot_entry_id);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
for (ev = pred->event_log; ev; ev = ev->next) {
|
|
||||||
tpm_evdigest_t *pcr;
|
|
||||||
diff --git a/src/sd-boot.c b/src/sd-boot.c
|
|
||||||
index ede2569..a16f814 100644
|
|
||||||
--- a/src/sd-boot.c
|
|
||||||
+++ b/src/sd-boot.c
|
|
||||||
@@ -130,10 +130,9 @@ get_valid_kernel_entry_tokens(void)
|
|
||||||
/*
|
|
||||||
* This should probably use UAPI boot entry logic as well
|
|
||||||
*/
|
|
||||||
-bool
|
|
||||||
-sdb_is_kernel(const char *application)
|
|
||||||
+static bool
|
|
||||||
+is_valid_entry_token(const char *application, const char *prefix)
|
|
||||||
{
|
|
||||||
- static const char prefix[] = "linux-";
|
|
||||||
const uapi_kernel_entry_tokens_t *match;
|
|
||||||
char *path_copy;
|
|
||||||
int found = 0;
|
|
||||||
@@ -151,7 +150,7 @@ sdb_is_kernel(const char *application)
|
|
||||||
|
|
||||||
if (!strcmp(ptr, token))
|
|
||||||
found |= 1;
|
|
||||||
- else if (!strncmp(ptr, prefix, sizeof(prefix) - 1))
|
|
||||||
+ else if (!strncmp(ptr, prefix, strlen(prefix)))
|
|
||||||
found |= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -160,6 +159,27 @@ sdb_is_kernel(const char *application)
|
|
||||||
return (found == 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
+bool
|
|
||||||
+sdb_is_kernel(const char *application)
|
|
||||||
+{
|
|
||||||
+ return is_valid_entry_token(application, "linux-");
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+bool
|
|
||||||
+sdb_is_initrd(const char *application)
|
|
||||||
+{
|
|
||||||
+ return is_valid_entry_token(application, "initrd-");
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+bool
|
|
||||||
+sdb_is_boot_entry(const char *application)
|
|
||||||
+{
|
|
||||||
+ if (!application)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ return !strncmp(application, UAPI_BOOT_DIRECTORY_EFI, sizeof(UAPI_BOOT_DIRECTORY_EFI) - 1);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Identify the next kernel and initrd given an ID
|
|
||||||
*/
|
|
||||||
diff --git a/src/sd-boot.h b/src/sd-boot.h
|
|
||||||
index 0472320..ceab13d 100644
|
|
||||||
--- a/src/sd-boot.h
|
|
||||||
+++ b/src/sd-boot.h
|
|
||||||
@@ -43,7 +43,9 @@ typedef struct sdb_entry_list {
|
|
||||||
} sdb_entry_list_t;
|
|
||||||
|
|
||||||
extern uapi_boot_entry_t * sdb_identify_boot_entry(const char *id);
|
|
||||||
+extern bool sdb_is_boot_entry(const char *application);
|
|
||||||
extern bool sdb_is_kernel(const char *application);
|
|
||||||
+extern bool sdb_is_initrd(const char *application);
|
|
||||||
|
|
||||||
/* This will have to update the systemd json file, and add a new entry. */
|
|
||||||
extern bool sdb_policy_file_add_entry(const char *filename,
|
|
||||||
diff --git a/src/uapi.h b/src/uapi.h
|
|
||||||
index 96ca7ed..8bcb94f 100644
|
|
||||||
--- a/src/uapi.h
|
|
||||||
+++ b/src/uapi.h
|
|
||||||
@@ -41,7 +41,8 @@ typedef struct uapi_kernel_entry_tokens {
|
|
||||||
char * entry_token[UAPI_MAX_ENTRY_TOKENS];
|
|
||||||
} uapi_kernel_entry_tokens_t;
|
|
||||||
|
|
||||||
-#define UAPI_BOOT_DIRECTORY "/boot/efi/loader/entries"
|
|
||||||
+#define UAPI_BOOT_DIRECTORY_EFI "/loader/entries"
|
|
||||||
+#define UAPI_BOOT_DIRECTORY "/boot/efi" UAPI_BOOT_DIRECTORY_EFI
|
|
||||||
|
|
||||||
extern uapi_boot_entry_t * uapi_get_boot_entry(const char *id);
|
|
||||||
extern uapi_boot_entry_t * uapi_find_boot_entry(const uapi_kernel_entry_tokens_t *match, const char *machine_id);
|
|
@@ -1,79 +0,0 @@
|
|||||||
From c2453df75ecdbc547e4637268dccde5cdc012881 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Alberto Planas <aplanas@suse.com>
|
|
||||||
Date: Tue, 20 Feb 2024 19:12:08 +0100
|
|
||||||
Subject: [PATCH] Measure systemd-boot loader.conf
|
|
||||||
|
|
||||||
Since systemd-boot v255 the /loader/loader.conf file can be measured
|
|
||||||
under a EV_EVENT_TAG event in PCR#5.
|
|
||||||
|
|
||||||
This commit measure the file in the ESP.
|
|
||||||
|
|
||||||
Fix #49
|
|
||||||
|
|
||||||
Signed-off-by: Alberto Planas <aplanas@suse.com>
|
|
||||||
---
|
|
||||||
src/eventlog.c | 18 ++++++++++++++++++
|
|
||||||
src/eventlog.h | 7 +++++--
|
|
||||||
2 files changed, 23 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/eventlog.c b/src/eventlog.c
|
|
||||||
index 4277d42..2e29b0e 100644
|
|
||||||
--- a/src/eventlog.c
|
|
||||||
+++ b/src/eventlog.c
|
|
||||||
@@ -842,6 +842,19 @@ __tpm_event_tag_destroy(tpm_parsed_event_t *parsed)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
+static const char *
|
|
||||||
+__tpm_event_tag_loader_conf_describe(const tpm_parsed_event_t *parsed)
|
|
||||||
+{
|
|
||||||
+ return "/loader/loader.conf (measured by systemd-boot)";
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static const tpm_evdigest_t *
|
|
||||||
+__tpm_event_tag_loader_conf_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *parsed, tpm_event_log_rehash_ctx_t *ctx)
|
|
||||||
+{
|
|
||||||
+ debug(" re-hashing /loader/loader.conf");
|
|
||||||
+ return runtime_digest_efi_file(ctx->algo, "/loader/loader.conf");
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static const char *
|
|
||||||
__tpm_event_tag_options_describe(const tpm_parsed_event_t *parsed)
|
|
||||||
{
|
|
||||||
@@ -880,6 +893,7 @@ __tpm_event_tag_initrd_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *p
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
+ * Generated by systemd-boot (PCR#5), to measure loader.conf
|
|
||||||
* Generated by the kernel (PCR#9), to measure the cmdline and initrd
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
@@ -900,6 +914,10 @@ __tpm_event_parse_tag(tpm_event_t *ev, tpm_parsed_event_t *parsed, buffer_t *bp)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
parsed->destroy = __tpm_event_tag_destroy;
|
|
||||||
+ if (evspec->event_id == LOADER_CONF_EVENT_TAG_ID) {
|
|
||||||
+ parsed->rehash = __tpm_event_tag_loader_conf_rehash;
|
|
||||||
+ parsed->describe = __tpm_event_tag_loader_conf_describe;
|
|
||||||
+ } else
|
|
||||||
if (evspec->event_id == LOAD_OPTIONS_EVENT_TAG_ID) {
|
|
||||||
parsed->rehash = __tpm_event_tag_options_rehash;
|
|
||||||
parsed->describe = __tpm_event_tag_options_describe;
|
|
||||||
diff --git a/src/eventlog.h b/src/eventlog.h
|
|
||||||
index 3741b58..d78e3da 100644
|
|
||||||
--- a/src/eventlog.h
|
|
||||||
+++ b/src/eventlog.h
|
|
||||||
@@ -96,8 +96,11 @@ enum {
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
- LOAD_OPTIONS_EVENT_TAG_ID = 0x8F3B22EDU,
|
|
||||||
- INITRD_EVENT_TAG_ID = 0x8F3B22ECU,
|
|
||||||
+ /* systemd-boot */
|
|
||||||
+ LOADER_CONF_EVENT_TAG_ID = 0xF5BC582A,
|
|
||||||
+ /* kernel */
|
|
||||||
+ LOAD_OPTIONS_EVENT_TAG_ID = 0x8F3B22ED,
|
|
||||||
+ INITRD_EVENT_TAG_ID = 0x8F3B22EC,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define EFI_DEVICE_PATH_MAX 16
|
|
BIN
pcr-oracle-0.4.6.tar.xz
(Stored with Git LFS)
Normal file
BIN
pcr-oracle-0.4.6.tar.xz
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
pcr-oracle-0.5.4.tar.xz
(Stored with Git LFS)
BIN
pcr-oracle-0.5.4.tar.xz
(Stored with Git LFS)
Binary file not shown.
@@ -1,120 +1,3 @@
|
|||||||
-------------------------------------------------------------------
|
|
||||||
Fri Mar 7 06:19:42 UTC 2025 - Gary Ching-Pang Lin <glin@suse.com>
|
|
||||||
|
|
||||||
- Add fix-bsc1230316-predict-sbatlevelrt-sb-off.patch to fix the
|
|
||||||
prediction of SbatLevelRT when Secure Boot is disabled
|
|
||||||
(bsc#1230316)
|
|
||||||
- Add fix-bsc1230316-make-pcr4-hard-requirement.patch to make PCR4
|
|
||||||
a hard requirement for SbatLevelRT prediction (bsc#1230316)
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
Wed Feb 26 07:31:47 UTC 2025 - Gary Ching-Pang Lin <glin@suse.com>
|
|
||||||
|
|
||||||
- Add fix-bsc1230316-predict-sbatlevelrt.patch to predict
|
|
||||||
SbatLevelRT for the next boot (bsc#1230316)
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
Fri Feb 21 02:20:27 UTC 2025 - Gary Ching-Pang Lin <glin@suse.com>
|
|
||||||
|
|
||||||
- Update the License tag to GPL-2.0-or-later to match the license
|
|
||||||
declaration in the source files
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
Thu Dec 26 05:57:07 UTC 2024 - Gary Ching-Pang Lin <glin@suse.com>
|
|
||||||
|
|
||||||
- Add fix-event-reshash-for-cryptouuid.patch to detect the crypto
|
|
||||||
device with the 'cryptouuid' prefix
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
Mon Aug 5 06:11:52 UTC 2024 - Gary Ching-Pang Lin <glin@suse.com>
|
|
||||||
|
|
||||||
- Add support-ecc-srk.patch to support ECC SRK
|
|
||||||
- Add fix-testcase-empty-efi-variables.patch to fix the testcase
|
|
||||||
playback on empty EFI variables
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
Mon Mar 25 20:16:53 UTC 2024 - Alberto Planas Dominguez <aplanas@suse.com>
|
|
||||||
|
|
||||||
- Add fix_grub_bls_cmdline.patch to include the measurements of the
|
|
||||||
cmdline and the linux and initrd grub commands
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
Thu Mar 14 10:33:23 UTC 2024 - Alberto Planas Dominguez <aplanas@suse.com>
|
|
||||||
|
|
||||||
- Add fix_grub_bls_entry.patch to measure boot entries in GRUB BLS
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
Mon Feb 26 15:14:37 UTC 2024 - Alberto Planas Dominguez <aplanas@suse.com>
|
|
||||||
|
|
||||||
- Remove fix_efi_measure.patch
|
|
||||||
- Add fix_efi_measure_and_shim.patch (bsc#1219807)
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
Tue Feb 20 18:16:53 UTC 2024 - Alberto Planas Dominguez <aplanas@suse.com>
|
|
||||||
|
|
||||||
- Add fix_loader_conf.patch to measure the systemd-boot loader.conf file
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
Fri Jan 12 07:28:55 UTC 2024 - Alberto Planas Dominguez <aplanas@suse.com>
|
|
||||||
|
|
||||||
- Add fix_efi_measure.patch to fix the measurement of EFI binaries
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
Fri Dec 8 07:17:35 UTC 2023 - Gary Ching-Pang Lin <glin@suse.com>
|
|
||||||
|
|
||||||
- Update to 0.5.4
|
|
||||||
- Improve systemd-boot support
|
|
||||||
- Add --boot-entry for systemd-boot
|
|
||||||
- Manpage fixes
|
|
||||||
- Fix PCR index in JSON file
|
|
||||||
- Fix GrubPcrSnapshot parsing
|
|
||||||
- Drop upstreamed patches: boot_entry.patch and fix_pcr_index.patch
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
Wed Nov 29 15:56:39 UTC 2023 - Alberto Planas Dominguez <aplanas@suse.com>
|
|
||||||
|
|
||||||
- Update to 0.5.3
|
|
||||||
- Improve documentation
|
|
||||||
- Detect key format store via extension
|
|
||||||
- Replace --key-format and --policy-format options with a single
|
|
||||||
--target-platform option
|
|
||||||
- The json file can contain multiple predictions
|
|
||||||
- Remove fix_rsa.patch as is already upstream
|
|
||||||
- Add boot_entry.patch to add new parameter to point to a new systemd
|
|
||||||
boot entry
|
|
||||||
- Add fix_pcr_index.patch to fix the PCR index number in the JSON file
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
Mon Nov 20 10:24:32 UTC 2023 - Alberto Planas Dominguez <aplanas@suse.com>
|
|
||||||
|
|
||||||
- Add fix_rsa.patch to support the export in PEM format of the public
|
|
||||||
key
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
Mon Nov 20 10:16:20 UTC 2023 - Alberto Planas Dominguez <aplanas@suse.com>
|
|
||||||
|
|
||||||
- FAPI is not present until tpm2-tss >= 2.4.0. Express that in the
|
|
||||||
BuildRequirement
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
Wed Nov 15 20:54:57 UTC 2023 - Alberto Planas Dominguez <aplanas@suse.com>
|
|
||||||
|
|
||||||
- Update to 0.5.2
|
|
||||||
- Support EV_EVENT_TAG events from the kernel (PCR9 for the cmdline
|
|
||||||
and the kernel)
|
|
||||||
- Fix cmdline measurements
|
|
||||||
- Update to 0.5.1
|
|
||||||
- Measure the kernel as an EFI binary (PCR4)
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
Mon Nov 13 10:53:20 UTC 2023 - Alberto Planas Dominguez <aplanas@suse.com>
|
|
||||||
|
|
||||||
- Update to 0.5.0
|
|
||||||
- Support systemd-cryptenroll JSON files
|
|
||||||
- Generate RSA keys in more scenarios
|
|
||||||
- Select RSA key size
|
|
||||||
- Drop systemd-boot.patch (already present in upstream)
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Thu Oct 19 11:01:10 UTC 2023 - Alberto Planas Dominguez <aplanas@suse.com>
|
Thu Oct 19 11:01:10 UTC 2023 - Alberto Planas Dominguez <aplanas@suse.com>
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# spec file for package pcr-oracle
|
# spec file for package pcr-oracle
|
||||||
#
|
#
|
||||||
# Copyright (c) 2025 SUSE LLC
|
# Copyright (c) 2023 SUSE LLC
|
||||||
#
|
#
|
||||||
# All modifications and additions to the file contributed by third parties
|
# All modifications and additions to the file contributed by third parties
|
||||||
# remain the property of their copyright owners, unless otherwise agreed
|
# remain the property of their copyright owners, unless otherwise agreed
|
||||||
@@ -18,36 +18,17 @@
|
|||||||
|
|
||||||
|
|
||||||
Name: pcr-oracle
|
Name: pcr-oracle
|
||||||
Version: 0.5.4
|
Version: 0.4.6
|
||||||
Release: 0
|
Release: 0
|
||||||
Summary: Predict TPM PCR values
|
Summary: Predict TPM PCR values
|
||||||
License: GPL-2.0-or-later
|
License: GPL-2.0-only
|
||||||
Group: System/Boot
|
Group: System/Boot
|
||||||
URL: https://github.com/okirch/pcr-oracle
|
URL: https://github.com/okirch/pcr-oracle
|
||||||
Source: %{name}-%{version}.tar.xz
|
Source: %{name}-%{version}.tar.xz
|
||||||
# PATCH-FIX-UPSTREAM fix_efi_measure_and_shim.patch gh#okirch/pcr-oracle!47
|
# PATCH-FEATURE-UPSTREAM systemd-boot.patch gh#okirch/pcr-oracle#31
|
||||||
# PATCH-FIX-UPSTREAM fix_efi_measure_and_shim.patch gh#okirch/pcr-oracle!51
|
Patch01: systemd-boot.patch
|
||||||
Patch0: fix_efi_measure_and_shim.patch
|
|
||||||
# PATCH-FIX-UPSTREAM fix_loader_conf.patch gh#okirch/pcr-oracle!50
|
|
||||||
Patch1: fix_loader_conf.patch
|
|
||||||
# PATCH-FIX-UPSTREAM fix_grub_bls_entry.patch gh#okirch/pcr-oracle!52
|
|
||||||
Patch2: fix_grub_bls_entry.patch
|
|
||||||
# PATCH-FIX-UPSTREAM fix_grub_bls_cmdline.patch gh#okirch/pcr-oracle!52 (cont)
|
|
||||||
Patch3: fix_grub_bls_cmdline.patch
|
|
||||||
# PATCH-FIX-UPSTREAM support-ecc-srk.patch gh#okirch/pcr-oracle!56
|
|
||||||
Patch4: support-ecc-srk.patch
|
|
||||||
# PATCH-FIX-UPSTREAM fix-testcase-empty-efi-variables.patch gh#okirch/pcr-oracle!58
|
|
||||||
Patch5: fix-testcase-empty-efi-variables.patch
|
|
||||||
# PATCH-FIX-UPSTREAM fix-event-reshash-for-cryptouuid.patch gh#okirch/pcr-oracle!60
|
|
||||||
Patch6: fix-event-reshash-for-cryptouuid.patch
|
|
||||||
# PATCH-FIX-UPSTREAM fix-bsc1230316-predict-sbatlevelrt.patch gh#okirch/pcr-oracle!61
|
|
||||||
Patch7: fix-bsc1230316-predict-sbatlevelrt.patch
|
|
||||||
# PATCH-FIX-UPSTREAM fix-bsc1230316-predict-sbatlevelrt-sb-off.patch gh#okirch/pcr-oracle!61
|
|
||||||
Patch8: fix-bsc1230316-predict-sbatlevelrt-sb-off.patch
|
|
||||||
# PATCH-FIX-UPSTREAM fix-bsc1230316-make-pcr4-hard-requirement.patch gh#okirch/pcr-oracle!61
|
|
||||||
Patch9: fix-bsc1230316-make-pcr4-hard-requirement.patch
|
|
||||||
BuildRequires: libopenssl-devel >= 0.9.8
|
BuildRequires: libopenssl-devel >= 0.9.8
|
||||||
BuildRequires: tpm2-0-tss-devel >= 2.4.0
|
BuildRequires: tpm2-0-tss-devel
|
||||||
Requires: libtss2-tcti-device0
|
Requires: libtss2-tcti-device0
|
||||||
ExclusiveArch: x86_64 aarch64 ppc64le riscv64
|
ExclusiveArch: x86_64 aarch64 ppc64le riscv64
|
||||||
|
|
||||||
|
@@ -1,413 +0,0 @@
|
|||||||
From 60ce42dbf61ce89012d9bc71c92c5cc92759b02c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Gary Lin <glin@suse.com>
|
|
||||||
Date: Wed, 3 Apr 2024 14:41:49 +0800
|
|
||||||
Subject: [PATCH 1/3] Update the comment for SRK template
|
|
||||||
|
|
||||||
USERWITHAUTH and NODA are set according to "TCG TPM v2.0 Provisioning
|
|
||||||
Guidance". This commit updates the comment to add the reference.
|
|
||||||
|
|
||||||
Signed-off-by: Gary Lin <glin@suse.com>
|
|
||||||
---
|
|
||||||
src/pcr-policy.c | 5 +++--
|
|
||||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/pcr-policy.c b/src/pcr-policy.c
|
|
||||||
index 8f2c42c..f03b6e0 100644
|
|
||||||
--- a/src/pcr-policy.c
|
|
||||||
+++ b/src/pcr-policy.c
|
|
||||||
@@ -67,8 +67,9 @@ static TPM2B_PUBLIC SRK_template = {
|
|
||||||
.publicArea = {
|
|
||||||
.type = TPM2_ALG_RSA,
|
|
||||||
.nameAlg = TPM2_ALG_SHA256,
|
|
||||||
- /* For reasons not clear to me, grub2 derives the SRK using the NODA attribute,
|
|
||||||
- * which means it is not subject to dictionary attack protections. */
|
|
||||||
+ /* Per "Storage Primary Key (SRK) Templates" in section 7.5.1 of
|
|
||||||
+ * TCG TPM v2.0 Provisioning Guidance 1.0 Revision 1.0, the
|
|
||||||
+ * template for shared SRKs sets USERWITHAUTH and NODA. */
|
|
||||||
.objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT \
|
|
||||||
|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT \
|
|
||||||
|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH \
|
|
||||||
--
|
|
||||||
2.35.3
|
|
||||||
|
|
||||||
|
|
||||||
From 0085c5a6a47f433dc69739c54b9db11796aff62e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Gary Lin <glin@suse.com>
|
|
||||||
Date: Wed, 10 Apr 2024 16:20:44 +0800
|
|
||||||
Subject: [PATCH 2/3] Support SRK template with ECC_NIST_P256
|
|
||||||
|
|
||||||
When sealing data with SRK, the data is actually encrypted with the
|
|
||||||
symmetric key, and the selection of the asymmetric algorithm is only
|
|
||||||
a parameter for KDF to derive the symmetric key. Compared with RSA,
|
|
||||||
ECC NIST-P256 provides the faster key generation, so it's a better
|
|
||||||
choice for the SRK template in general.
|
|
||||||
|
|
||||||
This commit adds a new option, '--ecc-srk', to switch the default SRK
|
|
||||||
template from the RSA one to the ECC one, so that the user can specify
|
|
||||||
the SRK template when sealing/unsealing data.
|
|
||||||
|
|
||||||
Signed-off-by: Gary Lin <glin@suse.com>
|
|
||||||
---
|
|
||||||
src/oracle.c | 7 +++++++
|
|
||||||
src/pcr-policy.c | 44 +++++++++++++++++++++++++++++++++++++++++---
|
|
||||||
src/pcr.h | 1 +
|
|
||||||
3 files changed, 49 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/oracle.c b/src/oracle.c
|
|
||||||
index 1cafafc..f391430 100644
|
|
||||||
--- a/src/oracle.c
|
|
||||||
+++ b/src/oracle.c
|
|
||||||
@@ -92,6 +92,7 @@ enum {
|
|
||||||
OPT_RSA_PUBLIC_KEY,
|
|
||||||
OPT_RSA_GENERATE_KEY,
|
|
||||||
OPT_RSA_BITS,
|
|
||||||
+ OPT_ECC_SRK,
|
|
||||||
OPT_INPUT,
|
|
||||||
OPT_OUTPUT,
|
|
||||||
OPT_AUTHORIZED_POLICY,
|
|
||||||
@@ -125,6 +126,7 @@ static struct option options[] = {
|
|
||||||
{ "public-key", required_argument, 0, OPT_RSA_PUBLIC_KEY },
|
|
||||||
{ "rsa-generate-key", no_argument, 0, OPT_RSA_GENERATE_KEY },
|
|
||||||
{ "rsa-bits", required_argument, 0, OPT_RSA_BITS },
|
|
||||||
+ { "ecc-srk", no_argument, 0, OPT_ECC_SRK },
|
|
||||||
{ "input", required_argument, 0, OPT_INPUT },
|
|
||||||
{ "output", required_argument, 0, OPT_OUTPUT },
|
|
||||||
{ "authorized-policy", required_argument, 0, OPT_AUTHORIZED_POLICY },
|
|
||||||
@@ -1042,6 +1044,8 @@ main(int argc, char **argv)
|
|
||||||
unsigned int rsa_bits = 2048;
|
|
||||||
int c, exit_code = 0;
|
|
||||||
|
|
||||||
+ set_srk_alg("RSA");
|
|
||||||
+
|
|
||||||
while ((c = getopt_long(argc, argv, "dhA:CF:LSZ", options, NULL)) != EOF) {
|
|
||||||
switch (c) {
|
|
||||||
case 'A':
|
|
||||||
@@ -1109,6 +1113,9 @@ main(int argc, char **argv)
|
|
||||||
case OPT_RSA_BITS:
|
|
||||||
opt_rsa_bits = optarg;
|
|
||||||
break;
|
|
||||||
+ case OPT_ECC_SRK:
|
|
||||||
+ set_srk_alg("ECC");
|
|
||||||
+ break;
|
|
||||||
case OPT_INPUT:
|
|
||||||
opt_input = optarg;
|
|
||||||
break;
|
|
||||||
diff --git a/src/pcr-policy.c b/src/pcr-policy.c
|
|
||||||
index f03b6e0..f65becf 100644
|
|
||||||
--- a/src/pcr-policy.c
|
|
||||||
+++ b/src/pcr-policy.c
|
|
||||||
@@ -62,7 +62,7 @@ struct target_platform {
|
|
||||||
const stored_key_t *public_key_file);
|
|
||||||
};
|
|
||||||
|
|
||||||
-static TPM2B_PUBLIC SRK_template = {
|
|
||||||
+static TPM2B_PUBLIC RSA_SRK_template = {
|
|
||||||
.size = sizeof(TPMT_PUBLIC),
|
|
||||||
.publicArea = {
|
|
||||||
.type = TPM2_ALG_RSA,
|
|
||||||
@@ -88,6 +88,35 @@ static TPM2B_PUBLIC SRK_template = {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
+static TPM2B_PUBLIC ECC_SRK_template = {
|
|
||||||
+ .size = sizeof(TPMT_PUBLIC),
|
|
||||||
+ .publicArea = {
|
|
||||||
+ .type = TPM2_ALG_ECC,
|
|
||||||
+ .nameAlg = TPM2_ALG_SHA256,
|
|
||||||
+ /* Per "Storage Primary Key (SRK) Templates" in section 7.5.1 of
|
|
||||||
+ * TCG TPM v2.0 Provisioning Guidance 1.0 Revision 1.0, the
|
|
||||||
+ * template for shared SRKs sets USERWITHAUTH and NODA. */
|
|
||||||
+ .objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT \
|
|
||||||
+ |TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT \
|
|
||||||
+ |TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH \
|
|
||||||
+ |TPMA_OBJECT_NODA,
|
|
||||||
+ .parameters = {
|
|
||||||
+ .eccDetail = {
|
|
||||||
+ .symmetric = {
|
|
||||||
+ .algorithm = TPM2_ALG_AES,
|
|
||||||
+ .keyBits = { .sym = 128 },
|
|
||||||
+ .mode = { .sym = TPM2_ALG_CFB },
|
|
||||||
+ },
|
|
||||||
+ .scheme = { TPM2_ALG_NULL },
|
|
||||||
+ .curveID = TPM2_ECC_NIST_P256,
|
|
||||||
+ .kdf.scheme = TPM2_ALG_NULL
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static const TPM2B_PUBLIC *SRK_template;
|
|
||||||
+
|
|
||||||
static const TPM2B_PUBLIC seal_public_template = {
|
|
||||||
.size = sizeof(TPMT_PUBLIC),
|
|
||||||
.publicArea = {
|
|
||||||
@@ -107,10 +136,19 @@ static const TPM2B_PUBLIC seal_public_template = {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
+void
|
|
||||||
+set_srk_alg (const char *alg)
|
|
||||||
+{
|
|
||||||
+ if (strcmp(alg, "RSA") == 0)
|
|
||||||
+ SRK_template = &RSA_SRK_template;
|
|
||||||
+ else
|
|
||||||
+ SRK_template = &ECC_SRK_template;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
set_srk_rsa_bits (const unsigned int rsa_bits)
|
|
||||||
{
|
|
||||||
- SRK_template.publicArea.parameters.rsaDetail.keyBits = rsa_bits;
|
|
||||||
+ RSA_SRK_template.publicArea.parameters.rsaDetail.keyBits = rsa_bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline const tpm_evdigest_t *
|
|
||||||
@@ -609,7 +647,7 @@ esys_create_primary(ESYS_CONTEXT *esys_context, ESYS_TR *handle_ret)
|
|
||||||
t0 = timing_begin();
|
|
||||||
rc = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER,
|
|
||||||
ESYS_TR_PASSWORD,
|
|
||||||
- ESYS_TR_NONE, ESYS_TR_NONE, &in_sensitive, &SRK_template,
|
|
||||||
+ ESYS_TR_NONE, ESYS_TR_NONE, &in_sensitive, SRK_template,
|
|
||||||
NULL, &creation_pcr, handle_ret,
|
|
||||||
NULL, NULL,
|
|
||||||
NULL, NULL);
|
|
||||||
diff --git a/src/pcr.h b/src/pcr.h
|
|
||||||
index 4d8f816..f1dc9af 100644
|
|
||||||
--- a/src/pcr.h
|
|
||||||
+++ b/src/pcr.h
|
|
||||||
@@ -39,6 +39,7 @@ typedef struct tpm_pcr_selection {
|
|
||||||
const tpm_algo_info_t * algo_info;
|
|
||||||
} tpm_pcr_selection_t;
|
|
||||||
|
|
||||||
+extern void set_srk_alg (const char *alg);
|
|
||||||
extern void set_srk_rsa_bits (const unsigned int rsa_bits);
|
|
||||||
extern void pcr_bank_initialize(tpm_pcr_bank_t *bank, unsigned int pcr_mask, const tpm_algo_info_t *algo);
|
|
||||||
extern bool pcr_bank_wants_pcr(tpm_pcr_bank_t *bank, unsigned int index);
|
|
||||||
--
|
|
||||||
2.35.3
|
|
||||||
|
|
||||||
|
|
||||||
From 207bd496868d65455e63aa9586bfc6e02900a4a1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Gary Lin <glin@suse.com>
|
|
||||||
Date: Wed, 24 Apr 2024 14:53:25 +0800
|
|
||||||
Subject: [PATCH 3/3] Update to conform the latest TPM 2.0 Key File
|
|
||||||
|
|
||||||
For TPM 2.0 Key File, the default asymmetric algorithm of SRK is ECC
|
|
||||||
NIST-P256, not RSA 2048. A new field 'rsaParent' is introduced to note
|
|
||||||
the key is sealed with RSA SRK.
|
|
||||||
|
|
||||||
This commit implements two new fields: description and rsaParent in
|
|
||||||
tpm2key.c/tpm2key-asn.h and sets rsaParent when RSA SRK is used to seal
|
|
||||||
the key. When unsealing a tpm2key, the SRK template is set to the RSA
|
|
||||||
template if rsaParent is TRUE. Otherwise, the SRK template is switched
|
|
||||||
to the ECC SRK template.
|
|
||||||
|
|
||||||
A new testing script, test-tpm2key-ecc.sh, is also added to test the
|
|
||||||
tpm2key file sealed with ECC SRK.
|
|
||||||
|
|
||||||
Signed-off-by: Gary Lin <glin@suse.com>
|
|
||||||
---
|
|
||||||
src/pcr-policy.c | 8 +++
|
|
||||||
src/tpm2key-asn.h | 4 ++
|
|
||||||
src/tpm2key.c | 2 +
|
|
||||||
test-tpm2key-ecc.sh | 127 ++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
4 files changed, 141 insertions(+)
|
|
||||||
create mode 100755 test-tpm2key-ecc.sh
|
|
||||||
|
|
||||||
diff --git a/src/pcr-policy.c b/src/pcr-policy.c
|
|
||||||
index f65becf..90f60ff 100644
|
|
||||||
--- a/src/pcr-policy.c
|
|
||||||
+++ b/src/pcr-policy.c
|
|
||||||
@@ -1505,6 +1505,11 @@ tpm2key_unseal_secret(const char *input_path, const char *output_path,
|
|
||||||
if (!tpm2key_read_file(input_path, &tpm2key))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
+ if (tpm2key->rsaParent == 1)
|
|
||||||
+ SRK_template = &RSA_SRK_template;
|
|
||||||
+ else
|
|
||||||
+ SRK_template = &ECC_SRK_template;
|
|
||||||
+
|
|
||||||
buffer_init_read(&buf, tpm2key->pubkey->data, tpm2key->pubkey->length);
|
|
||||||
rc = Tss2_MU_TPM2B_PUBLIC_Unmarshal(buf.data, buf.size, &buf.rpos, &pub);
|
|
||||||
if (rc != TSS2_RC_SUCCESS)
|
|
||||||
@@ -1634,6 +1639,9 @@ tpm2key_write_sealed_secret(const char *pathname,
|
|
||||||
if (!tpm2key_basekey(&tpm2key, TPM2_RH_OWNER, sealed_public, sealed_private))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
+ if (SRK_template->publicArea.type == TPM2_ALG_RSA)
|
|
||||||
+ tpm2key->rsaParent = 1;
|
|
||||||
+
|
|
||||||
if (pcr_sel && !tpm2key_add_policy_policypcr(tpm2key, pcr_sel))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
diff --git a/src/tpm2key-asn.h b/src/tpm2key-asn.h
|
|
||||||
index 3f1c0d7..d0cdfaa 100644
|
|
||||||
--- a/src/tpm2key-asn.h
|
|
||||||
+++ b/src/tpm2key-asn.h
|
|
||||||
@@ -77,6 +77,8 @@ DEFINE_STACK_OF(TSSAUTHPOLICY);
|
|
||||||
* policy [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL
|
|
||||||
* secret [2] EXPLICIT OCTET STRING OPTIONAL
|
|
||||||
* authPolicy [3] EXPLICIT SEQUENCE OF TPMAuthPolicy OPTIONAL
|
|
||||||
+ * description [4] EXPLICIT UTF8String OPTIONAL
|
|
||||||
+ * rsaParent [5] EXPLICIT BOOLEAN OPTIONAL
|
|
||||||
* parent INTEGER
|
|
||||||
* pubkey OCTET STRING
|
|
||||||
* privkey OCTET STRING
|
|
||||||
@@ -89,6 +91,8 @@ typedef struct {
|
|
||||||
STACK_OF(TSSOPTPOLICY) *policy;
|
|
||||||
ASN1_OCTET_STRING *secret;
|
|
||||||
STACK_OF(TSSAUTHPOLICY) *authPolicy;
|
|
||||||
+ ASN1_UTF8STRING description;
|
|
||||||
+ ASN1_BOOLEAN rsaParent;
|
|
||||||
ASN1_INTEGER *parent;
|
|
||||||
ASN1_OCTET_STRING *pubkey;
|
|
||||||
ASN1_OCTET_STRING *privkey;
|
|
||||||
diff --git a/src/tpm2key.c b/src/tpm2key.c
|
|
||||||
index cabd791..af4c984 100644
|
|
||||||
--- a/src/tpm2key.c
|
|
||||||
+++ b/src/tpm2key.c
|
|
||||||
@@ -278,6 +278,8 @@ ASN1_SEQUENCE(TSSPRIVKEY) = {
|
|
||||||
ASN1_EXP_SEQUENCE_OF_OPT(TSSPRIVKEY, policy, TSSOPTPOLICY, 1),
|
|
||||||
ASN1_EXP_OPT(TSSPRIVKEY, secret, ASN1_OCTET_STRING, 2),
|
|
||||||
ASN1_EXP_SEQUENCE_OF_OPT(TSSPRIVKEY, authPolicy, TSSAUTHPOLICY, 3),
|
|
||||||
+ ASN1_EXP_OPT(TSSPRIVKEY, description, ASN1_UTF8STRING, 4),
|
|
||||||
+ ASN1_EXP_OPT(TSSPRIVKEY, rsaParent, ASN1_BOOLEAN, 5),
|
|
||||||
ASN1_SIMPLE(TSSPRIVKEY, parent, ASN1_INTEGER),
|
|
||||||
ASN1_SIMPLE(TSSPRIVKEY, pubkey, ASN1_OCTET_STRING),
|
|
||||||
ASN1_SIMPLE(TSSPRIVKEY, privkey, ASN1_OCTET_STRING)
|
|
||||||
diff --git a/test-tpm2key-ecc.sh b/test-tpm2key-ecc.sh
|
|
||||||
new file mode 100755
|
|
||||||
index 0000000..d87acff
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/test-tpm2key-ecc.sh
|
|
||||||
@@ -0,0 +1,127 @@
|
|
||||||
+#!/bin/bash
|
|
||||||
+#
|
|
||||||
+# This script needs to be run with root privilege
|
|
||||||
+#
|
|
||||||
+
|
|
||||||
+# TESTDIR=policy.test
|
|
||||||
+PCR_MASK=0,2,4,12
|
|
||||||
+
|
|
||||||
+pcr_oracle=pcr-oracle
|
|
||||||
+if [ -x pcr-oracle ]; then
|
|
||||||
+ pcr_oracle=$PWD/pcr-oracle
|
|
||||||
+fi
|
|
||||||
+
|
|
||||||
+function call_oracle {
|
|
||||||
+
|
|
||||||
+ echo "****************"
|
|
||||||
+ echo "pcr-oracle $*"
|
|
||||||
+ $pcr_oracle --target-platform tpm2.0 -d "$@"
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+if [ -z "$TESTDIR" ]; then
|
|
||||||
+ tmpdir=$(mktemp -d /tmp/pcrtestXXXXXX)
|
|
||||||
+ trap "cd / && rm -rf $tmpdir" 0 1 2 10 11 15
|
|
||||||
+
|
|
||||||
+ TESTDIR=$tmpdir
|
|
||||||
+fi
|
|
||||||
+
|
|
||||||
+trap "echo 'FAIL: command exited with error'; exit 1" ERR
|
|
||||||
+
|
|
||||||
+echo "This is super secret" >$TESTDIR/secret
|
|
||||||
+
|
|
||||||
+set -e
|
|
||||||
+cd $TESTDIR
|
|
||||||
+
|
|
||||||
+echo "Seal the secret with PCR policy"
|
|
||||||
+call_oracle \
|
|
||||||
+ --from current \
|
|
||||||
+ --input secret \
|
|
||||||
+ --output sealed \
|
|
||||||
+ --ecc-srk \
|
|
||||||
+ seal-secret $PCR_MASK
|
|
||||||
+
|
|
||||||
+echo "Unseal the sealed with PCR policy"
|
|
||||||
+call_oracle \
|
|
||||||
+ --input sealed \
|
|
||||||
+ --output recovered \
|
|
||||||
+ unseal-secret
|
|
||||||
+
|
|
||||||
+if ! cmp secret recovered; then
|
|
||||||
+ echo "BAD: Unable to recover original secret"
|
|
||||||
+ echo "Secret:"
|
|
||||||
+ od -tx1c secret
|
|
||||||
+ echo "Recovered:"
|
|
||||||
+ od -tx1c recovered
|
|
||||||
+ exit 1
|
|
||||||
+else
|
|
||||||
+ echo "NICE: we were able to recover the original secret"
|
|
||||||
+fi
|
|
||||||
+
|
|
||||||
+rm -f sealed recovered
|
|
||||||
+
|
|
||||||
+call_oracle \
|
|
||||||
+ --rsa-generate-key \
|
|
||||||
+ --private-key policy-key.pem \
|
|
||||||
+ --auth authorized.policy \
|
|
||||||
+ create-authorized-policy $PCR_MASK
|
|
||||||
+
|
|
||||||
+call_oracle \
|
|
||||||
+ --private-key policy-key.pem \
|
|
||||||
+ --public-key policy-pubkey \
|
|
||||||
+ store-public-key
|
|
||||||
+
|
|
||||||
+call_oracle \
|
|
||||||
+ --auth authorized.policy \
|
|
||||||
+ --input secret \
|
|
||||||
+ --output sealed \
|
|
||||||
+ --ecc-srk \
|
|
||||||
+ seal-secret
|
|
||||||
+
|
|
||||||
+for attempt in first second; do
|
|
||||||
+ echo "Sign the set of PCRs we want to authorize"
|
|
||||||
+ call_oracle \
|
|
||||||
+ --policy-name "authorized-policy-test" \
|
|
||||||
+ --private-key policy-key.pem \
|
|
||||||
+ --from current \
|
|
||||||
+ --input sealed \
|
|
||||||
+ --output sealed-signed \
|
|
||||||
+ sign $PCR_MASK
|
|
||||||
+
|
|
||||||
+ echo "$attempt attempt to unseal the secret"
|
|
||||||
+ call_oracle \
|
|
||||||
+ --input sealed-signed \
|
|
||||||
+ --output recovered \
|
|
||||||
+ unseal-secret
|
|
||||||
+
|
|
||||||
+ if ! cmp secret recovered; then
|
|
||||||
+ echo "BAD: Unable to recover original secret"
|
|
||||||
+ echo "Secret:"
|
|
||||||
+ od -tx1c secret
|
|
||||||
+ echo "Recovered:"
|
|
||||||
+ od -tx1c recovered
|
|
||||||
+ exit 1
|
|
||||||
+ else
|
|
||||||
+ echo "NICE: we were able to recover the original secret"
|
|
||||||
+ fi
|
|
||||||
+
|
|
||||||
+ if [ "$attempt" = "second" ]; then
|
|
||||||
+ break
|
|
||||||
+ fi
|
|
||||||
+
|
|
||||||
+ echo "Extend PCR 12. Unsealing should fail afterwards"
|
|
||||||
+ tpm2_pcrextend 12:sha256=21d2013e3081f1e455fdd5ba6230a8620c3cfc9a9c31981d857fe3891f79449e
|
|
||||||
+ rm -f recovered
|
|
||||||
+ call_oracle \
|
|
||||||
+ --input sealed-signed \
|
|
||||||
+ --output recovered \
|
|
||||||
+ unseal-secret || true
|
|
||||||
+
|
|
||||||
+ if [ -s recovered ] && ! cmp secret recovered; then
|
|
||||||
+ echo "BAD: We were still able to recover the original secret. Something stinks"
|
|
||||||
+ exit 1
|
|
||||||
+ else
|
|
||||||
+ echo "GOOD: After changing a PCR, the secret can no longer be unsealed"
|
|
||||||
+ fi
|
|
||||||
+
|
|
||||||
+ echo "Now recreate the signed PCR policy"
|
|
||||||
+done
|
|
||||||
--
|
|
||||||
2.35.3
|
|
||||||
|
|
1091
systemd-boot.patch
Normal file
1091
systemd-boot.patch
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user