Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package pcr-oracle for openSUSE:Factory 
checked in at 2025-06-01 21:36:11
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/pcr-oracle (Old)
 and      /work/SRC/openSUSE:Factory/.pcr-oracle.new.16005 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "pcr-oracle"

Sun Jun  1 21:36:11 2025 rev:21 rq:1281086 version:0.5.7

Changes:
--------
--- /work/SRC/openSUSE:Factory/pcr-oracle/pcr-oracle.changes    2025-05-20 
09:31:00.979518421 +0200
+++ /work/SRC/openSUSE:Factory/.pcr-oracle.new.16005/pcr-oracle.changes 
2025-06-01 21:36:21.620808105 +0200
@@ -1,0 +2,9 @@
+Thu May 29 07:31:13 UTC 2025 - Gary Ching-Pang Lin <g...@suse.com>
+
+- Update to 0.5.7
+  + Support ppc64 events
+  + Fix the string comparison for the alternative event
+    (bsc#1241957)
+- Add the new BuildRequires: libelf-devel and libfdisk-devel
+
+-------------------------------------------------------------------

Old:
----
  pcr-oracle-0.5.6.tar.xz

New:
----
  pcr-oracle-0.5.7.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ pcr-oracle.spec ++++++
--- /var/tmp/diff_new_pack.EmBGID/_old  2025-06-01 21:36:22.136829479 +0200
+++ /var/tmp/diff_new_pack.EmBGID/_new  2025-06-01 21:36:22.140829644 +0200
@@ -18,13 +18,15 @@
 
 
 Name:           pcr-oracle
-Version:        0.5.6
+Version:        0.5.7
 Release:        0
 Summary:        Predict TPM PCR values
 License:        GPL-2.0-or-later
 Group:          System/Boot
 URL:            https://github.com/openSUSE/pcr-oracle
 Source:         %{name}-%{version}.tar.xz
+BuildRequires:  libelf-devel
+BuildRequires:  libfdisk-devel
 BuildRequires:  libopenssl-devel >= 3.0.0
 BuildRequires:  tpm2-0-tss-devel >= 2.4.0
 Requires:       libtss2-tcti-device0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.EmBGID/_old  2025-06-01 21:36:22.168830805 +0200
+++ /var/tmp/diff_new_pack.EmBGID/_new  2025-06-01 21:36:22.172830970 +0200
@@ -7,7 +7,7 @@
                <param 
name="url">https://github.com/openSUSE/pcr-oracle.git</param>
                <param name="filename">pcr-oracle</param>
                <param name="versionformat">@PARENT_TAG@</param>
-               <param name="revision">refs/tags/0.5.6</param>
+               <param name="revision">refs/tags/0.5.7</param>
        </service>
        <service name="recompress" mode="disabled">
                 <param name="file">pcr-oracle*.tar</param>

++++++ pcr-oracle-0.5.6.tar.xz -> pcr-oracle-0.5.7.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/Makefile.in 
new/pcr-oracle-0.5.7/Makefile.in
--- old/pcr-oracle-0.5.6/Makefile.in    2025-05-13 08:48:20.000000000 +0200
+++ new/pcr-oracle-0.5.7/Makefile.in    2025-05-29 09:26:41.000000000 +0200
@@ -3,9 +3,11 @@
 
 CCOPT          = -O0 -g
 FIRSTBOOTDIR   = /usr/share/jeos-firstboot
-CFLAGS         = -Wall @TSS2_ESYS_CFLAGS@ @JSON_CFLAGS@ $(CCOPT)
+CFLAGS         = -Wall @TSS2_ESYS_CFLAGS@ @JSON_CFLAGS@ @FDISK_CFLAGS@ 
@LIBELF_CFLAGS@ $(CCOPT)
 TSS2_LINK      = -ltss2-esys -ltss2-tctildr -ltss2-rc -ltss2-mu -lcrypto
 JSON_LINK      = -L@JSON_LIBDIR@ @JSON_LIBS@
+FDISK_LINK     = @FDISK_LIBS@
+LIBELF_LINK    = @LIBELF_LIBS@
 TOOLS          = pcr-oracle
 
 MANDIR         = @MANDIR@
@@ -35,7 +37,8 @@
                  util.c \
                  sd-boot.c \
                  uapi.c \
-                 secure_boot.c
+                 secure_boot.c \
+                 ieee1275-events.c
 ORACLE_OBJS    = $(addprefix build/,$(patsubst %.c,%.o,$(ORACLE_SRCS)))
 
 all: $(TOOLS) $(MANPAGES)
@@ -54,7 +57,7 @@
        rm -rf build
 
 pcr-oracle: $(ORACLE_OBJS)
-       $(CC) -o $@ $(ORACLE_OBJS) $(TSS2_LINK) $(JSON_LINK)
+       $(CC) -o $@ $(ORACLE_OBJS) $(TSS2_LINK) $(JSON_LINK) $(FDISK_LINK) 
$(LIBELF_LINK)
 
 build/%.o: src/%.c
        @mkdir -p build
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/configure 
new/pcr-oracle-0.5.7/configure
--- old/pcr-oracle-0.5.6/configure      2025-05-13 08:48:20.000000000 +0200
+++ new/pcr-oracle-0.5.7/configure      2025-05-29 09:26:41.000000000 +0200
@@ -12,9 +12,11 @@
 # Invoke with --help for a description of options
 #
 # microconf:begin
-# version 0.5.6
+# version 0.5.7
 # require libtss2
 # require json
+# require libfdisk
+# require libelf
 # disable debug-authenticode
 # microconf:end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/microconf/stage1/04-fdisk 
new/pcr-oracle-0.5.7/microconf/stage1/04-fdisk
--- old/pcr-oracle-0.5.6/microconf/stage1/04-fdisk      1970-01-01 
01:00:00.000000000 +0100
+++ new/pcr-oracle-0.5.7/microconf/stage1/04-fdisk      2025-05-29 
09:26:41.000000000 +0200
@@ -0,0 +1,11 @@
+uc_add_option_with libfdisk
+uc_with_libfdisk=detect
+
+uc_add_help <<EOH
+
+
+  Override libfdisk detection
+        --with-libfdisk=VERSION
+        --without-libfdisk
+
+EOH
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/microconf/stage1/05-libelf 
new/pcr-oracle-0.5.7/microconf/stage1/05-libelf
--- old/pcr-oracle-0.5.6/microconf/stage1/05-libelf     1970-01-01 
01:00:00.000000000 +0100
+++ new/pcr-oracle-0.5.7/microconf/stage1/05-libelf     2025-05-29 
09:26:41.000000000 +0200
@@ -0,0 +1,11 @@
+uc_add_option_with libelf
+uc_with_libelf=detect
+
+uc_add_help <<EOH
+
+
+  Override libelf detection
+        --with-libelf=VERSION
+        --without-libelf
+
+EOH
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/microconf/stage3/06-fdisk 
new/pcr-oracle-0.5.7/microconf/stage3/06-fdisk
--- old/pcr-oracle-0.5.6/microconf/stage3/06-fdisk      1970-01-01 
01:00:00.000000000 +0100
+++ new/pcr-oracle-0.5.7/microconf/stage3/06-fdisk      2025-05-29 
09:26:41.000000000 +0200
@@ -0,0 +1,6 @@
+##################################################################
+# libfdisk version
+##################################################################
+if [ -z "$uc_with_libfdisk" -o "$uc_with_libfdisk" = "detect" ]; then
+       uc_pkg_config_check_package fdisk
+fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/microconf/stage3/07-libelf 
new/pcr-oracle-0.5.7/microconf/stage3/07-libelf
--- old/pcr-oracle-0.5.6/microconf/stage3/07-libelf     1970-01-01 
01:00:00.000000000 +0100
+++ new/pcr-oracle-0.5.7/microconf/stage3/07-libelf     2025-05-29 
09:26:41.000000000 +0200
@@ -0,0 +1,6 @@
+##################################################################
+# libelf version
+##################################################################
+if [ -z "$uc_with_libelf" -o "$uc_with_libelf" = "detect" ]; then
+       uc_pkg_config_check_package libelf
+fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/microconf/version 
new/pcr-oracle-0.5.7/microconf/version
--- old/pcr-oracle-0.5.6/microconf/version      2025-05-13 08:48:20.000000000 
+0200
+++ new/pcr-oracle-0.5.7/microconf/version      2025-05-29 09:26:41.000000000 
+0200
@@ -1 +1 @@
-uc_version=0.5.6
+uc_version=0.5.7
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/src/efi-gpt.c 
new/pcr-oracle-0.5.7/src/efi-gpt.c
--- old/pcr-oracle-0.5.6/src/efi-gpt.c  2025-05-13 08:48:20.000000000 +0200
+++ new/pcr-oracle-0.5.7/src/efi-gpt.c  2025-05-29 09:26:41.000000000 +0200
@@ -39,6 +39,7 @@
 static void
 __tpm_event_efi_gpt_destroy(tpm_parsed_event_t *parsed)
 {
+       drop_string(&parsed->efi_gpt_event.sys_partition);
        drop_string(&parsed->efi_gpt_event.disk_device);
 }
 
@@ -166,14 +167,14 @@
        buffer_t *buffer = NULL;
        char *device;
 
-       if (evspec->efi_partition == NULL) {
-               error("Cannot determine EFI partition from event log\n");
+       if (evspec->sys_partition == NULL) {
+               error("Cannot determine system partition from event log\n");
                /* FIXME: just use the device that holds /boot/efi? */
                return NULL;
        }
 
-       if (!(device = runtime_disk_for_partition(evspec->efi_partition))) {
-               error("Unable to determine disk for partition %s\n", 
evspec->efi_partition);
+       if (!(device = runtime_disk_for_partition(evspec->sys_partition))) {
+               error("Unable to determine disk for partition %s\n", 
evspec->sys_partition);
                return NULL;
        }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/src/efi-variable.c 
new/pcr-oracle-0.5.7/src/efi-variable.c
--- old/pcr-oracle-0.5.6/src/efi-variable.c     2025-05-13 08:48:20.000000000 
+0200
+++ new/pcr-oracle-0.5.7/src/efi-variable.c     2025-05-29 09:26:41.000000000 
+0200
@@ -371,7 +371,7 @@
 
        var_short_name = parsed->efi_variable_event.variable_name;
 
-       if (!strcmp(var_short_name, "db") || !strcmp(var_short_name, 
"MokListRT"))
+       if (strcmp(var_short_name, "db") != 0 && strcmp(var_short_name, 
"MokListRT") != 0)
                return NULL;
 
        parsed_alt = malloc(sizeof(tpm_parsed_event_t));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/src/eventlog.c 
new/pcr-oracle-0.5.7/src/eventlog.c
--- old/pcr-oracle-0.5.6/src/eventlog.c 2025-05-13 08:48:20.000000000 +0200
+++ new/pcr-oracle-0.5.7/src/eventlog.c 2025-05-29 09:26:41.000000000 +0200
@@ -1089,6 +1089,8 @@
        return true;
 }
 
+#define GRUB_PREP_ENVBLK "PReP ENV Block"
+
 static bool
 __tpm_event_parse_ipl(tpm_event_t *ev, tpm_parsed_event_t *parsed, buffer_t 
*bp)
 {
@@ -1109,8 +1111,12 @@
        if (ev->pcr_index == 8)
                return __tpm_event_grub_command_event_parse(ev, parsed, value);
 
-       if (ev->pcr_index == 9)
-               return __tpm_event_grub_file_event_parse(ev, parsed, value);
+       if (ev->pcr_index == 9) {
+               if (strncmp(value, GRUB_PREP_ENVBLK, strlen(GRUB_PREP_ENVBLK)) 
== 0)
+                       return __tpm_event_grub_envblk_event_parse(ev, parsed, 
value);
+               else
+                       return __tpm_event_grub_file_event_parse(ev, parsed, 
value);
+       }
 
        if (ev->pcr_index == 12)
                return __tpm_event_systemd_event_parse(ev, parsed, value, len);
@@ -1146,6 +1152,9 @@
 
        case TPM2_EFI_GPT_EVENT:
                return __tpm_event_parse_efi_gpt(ev, parsed, &buf);
+
+       case TPM2_EVENT_COMPACT_HASH:
+               return __tpm_event_parse_compact_hash(ev, parsed, &buf);
        }
 
        return false;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/src/eventlog.h 
new/pcr-oracle-0.5.7/src/eventlog.h
--- old/pcr-oracle-0.5.6/src/eventlog.h 2025-05-13 08:48:20.000000000 +0200
+++ new/pcr-oracle-0.5.7/src/eventlog.h 2025-05-29 09:26:41.000000000 +0200
@@ -277,7 +277,7 @@
                } shim_event;
 
                struct efi_gpt_event {
-                       char *          efi_partition;
+                       char *          sys_partition;
                        char *          disk_device;
                } efi_gpt_event;
 
@@ -291,6 +291,14 @@
                        uint32_t        event_data_len;
                        char            event_data[52];
                } tag_event;
+
+               struct compact_hash_event {
+                       char *          prep_partition;
+               } compact_hash_event;
+
+               struct grub_envblk_event {
+                       char *          prep_partition;
+               } grub_envblk_event;
        };
 } tpm_parsed_event_t;
 
@@ -344,4 +352,6 @@
 
 extern bool                    secure_boot_enabled();
 
+extern bool                    __tpm_event_parse_compact_hash(tpm_event_t *, 
tpm_parsed_event_t *, buffer_t *);
+extern bool                    __tpm_event_grub_envblk_event_parse(tpm_event_t 
*, tpm_parsed_event_t *, const char *);
 #endif /* EVENTLOG_H */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/src/ieee1275-events.c 
new/pcr-oracle-0.5.7/src/ieee1275-events.c
--- old/pcr-oracle-0.5.6/src/ieee1275-events.c  1970-01-01 01:00:00.000000000 
+0100
+++ new/pcr-oracle-0.5.7/src/ieee1275-events.c  2025-05-29 09:26:41.000000000 
+0200
@@ -0,0 +1,126 @@
+/*
+ *   Copyright (C) 2025 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 Gary Lin <g...@suse.com>
+ */
+
+#include <stdbool.h>
+
+#include "bufparser.h"
+#include "eventlog.h"
+#include "runtime.h"
+
+/* Process Compact Hash Events */
+
+static void
+__tpm_event_compact_hash_destroy(tpm_parsed_event_t *parsed)
+{
+       drop_string(&parsed->compact_hash_event.prep_partition);
+}
+
+static const char *
+__tpm_event_compact_hash_describe(const tpm_parsed_event_t *parsed)
+{
+       return "Compact Hash";
+}
+
+static const tpm_evdigest_t *
+__prep_bootloader_rehash (const struct compact_hash_event *evspec, 
tpm_event_log_rehash_ctx_t *ctx)
+{
+       const tpm_evdigest_t *md;
+
+       debug("Computing digest of the bootloader in PReP partition\n");
+       if (evspec->prep_partition == NULL)
+               return NULL;
+
+       md = runtime_digest_prep_booloader(ctx->algo, evspec->prep_partition);
+
+       return md;
+}
+
+static const tpm_evdigest_t *
+__tpm_event_compact_hash_rehash(const tpm_event_t *ev, const 
tpm_parsed_event_t *parsed, tpm_event_log_rehash_ctx_t *ctx)
+{
+       const struct compact_hash_event *evspec = &parsed->compact_hash_event;
+
+       /* Copy the digest for the normal Compact Hash events */
+       if (evspec->prep_partition == NULL)
+               return tpm_event_get_digest(ev, ctx->algo);
+
+       /* Rehash the bootloader in the PReP partition */
+       return __prep_bootloader_rehash(evspec, ctx);
+}
+
+bool
+__tpm_event_parse_compact_hash(tpm_event_t *ev, tpm_parsed_event_t *parsed, 
buffer_t *bp)
+{
+       struct compact_hash_event *evspec = &parsed->compact_hash_event;
+
+       parsed->destroy = __tpm_event_compact_hash_destroy;
+       parsed->describe = __tpm_event_compact_hash_describe;
+       parsed->rehash = __tpm_event_compact_hash_rehash;
+
+       /* Only handle the Compact Hash event with "BOOTLOADER" in the event 
data */
+       if (bp->size != 10 || memcmp(bp->data, "BOOTLOADER", 10) != 0)
+               return true;
+
+       /* Locate the PReP partition */
+       if (!(evspec->prep_partition = runtime_locate_prep_partition()))
+               return false;
+
+       return true;
+}
+
+/* Process PReP ENV Block */
+static void
+__tpm_event_grub_envblk_destroy(tpm_parsed_event_t *parsed)
+{
+       drop_string(&parsed->grub_envblk_event.prep_partition);
+}
+
+static const char *
+__tpm_event_grub_envblk_describe(const tpm_parsed_event_t *parsed)
+{
+       return "GRUB ENV Block";
+}
+
+static const tpm_evdigest_t *
+__tpm_event_grub_envblk_rehash(const tpm_event_t *ev, const tpm_parsed_event_t 
*parsed, tpm_event_log_rehash_ctx_t *ctx)
+{
+       const struct grub_envblk_event *evspec = &parsed->grub_envblk_event;
+
+       if (evspec->prep_partition == NULL)
+               return NULL;
+
+       return runtime_digest_prep_envblk(ctx->algo, evspec->prep_partition);;
+}
+
+bool
+__tpm_event_grub_envblk_event_parse(tpm_event_t *ev, tpm_parsed_event_t 
*parsed, const char *value)
+{
+       struct grub_envblk_event *evspec = &parsed->grub_envblk_event;
+
+       parsed->destroy = __tpm_event_grub_envblk_destroy;
+       parsed->describe = __tpm_event_grub_envblk_describe;
+       parsed->rehash = __tpm_event_grub_envblk_rehash;
+
+       /* Locate the PReP partition */
+       if (!(evspec->prep_partition = runtime_locate_prep_partition()))
+               return false;
+
+       return true;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/src/oracle.c 
new/pcr-oracle-0.5.7/src/oracle.c
--- old/pcr-oracle-0.5.6/src/oracle.c   2025-05-13 08:48:20.000000000 +0200
+++ new/pcr-oracle-0.5.7/src/oracle.c   2025-05-29 09:26:41.000000000 +0200
@@ -487,7 +487,7 @@
  * Lookahead: when processing the GPT event, we need to know which hard disk
  * we're talking about.
  */
-static void
+static bool
 __predictor_lookahead_efi_partition(tpm_event_t *ev, 
tpm_event_log_rehash_ctx_t *ctx)
 {
        struct efi_gpt_event *gpt = &ev->__parsed->efi_gpt_event;
@@ -502,7 +502,31 @@
                if (!(parsed = ev->__parsed))
                        continue;
 
-               assign_string(&gpt->efi_partition, 
parsed->efi_bsa_event.efi_partition);
+               assign_string(&gpt->sys_partition, 
parsed->efi_bsa_event.efi_partition);
+               return true;
+       }
+       return false;
+}
+
+static void
+__predictor_lookahead_prep_partition(tpm_event_t *ev, 
tpm_event_log_rehash_ctx_t *ctx)
+{
+       struct efi_gpt_event *gpt = &ev->__parsed->efi_gpt_event;
+
+       while ((ev = ev->next) != NULL) {
+               tpm_parsed_event_t *parsed;
+
+               if (ev->event_type != TPM2_EVENT_COMPACT_HASH)
+                       continue;
+
+               /* Compact hash events have already been parsed during the 
pre-scan */
+               if (!(parsed = ev->__parsed))
+                       continue;
+
+               if (!parsed->compact_hash_event.prep_partition)
+                       continue;
+
+               assign_string(&gpt->sys_partition, 
parsed->compact_hash_event.prep_partition);
                return;
        }
 }
@@ -585,6 +609,12 @@
                 */
                TPM2_EFI_GPT_EVENT,
 
+               /*
+                * EVENT_COMPACT_HASH: used by SLOF for PCR4, to measure the 
bootloader with
+                *      'BOOTLOADER' in the event data.
+                */
+               TPM2_EVENT_COMPACT_HASH,
+
                -1,
        };
        static int copy_types[] = {
@@ -721,9 +751,16 @@
                         * BOOT_SERVICES event that would tell us which 
partition we're booting
                         * from.
                         * Scan ahead to the first BSA event to extract the EFI 
partition.
+                        *
+                        * For PowerPC 64, the firmware measures the bootloader 
in a Compact
+                        * Hash event instead of a BSA event. If there is no 
BSA event, we
+                        * go further to look for the Compact Hash event to set 
the PReP
+                        * partition.
                         */
-                       if (ev->event_type == TPM2_EFI_GPT_EVENT)
-                               __predictor_lookahead_efi_partition(ev, 
&rehash_ctx);
+                       if (ev->event_type == TPM2_EFI_GPT_EVENT) {
+                               if (!__predictor_lookahead_efi_partition(ev, 
&rehash_ctx))
+                                       
__predictor_lookahead_prep_partition(ev, &rehash_ctx);
+                       }
 
                        /* The shim loader emits an event that tells us which 
certificate it
                         * used to verify the second stage loader. We try to 
predict that
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/src/runtime.c 
new/pcr-oracle-0.5.7/src/runtime.c
--- old/pcr-oracle-0.5.6/src/runtime.c  2025-05-13 08:48:20.000000000 +0200
+++ new/pcr-oracle-0.5.7/src/runtime.c  2025-05-29 09:26:41.000000000 +0200
@@ -20,6 +20,9 @@
 
 #include <sys/stat.h>
 #include <sys/mount.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <string.h>
@@ -27,12 +30,23 @@
 #include <errno.h>
 #include <ctype.h>
 
+#include <libelf.h>
+#include <libfdisk.h>
+#include <linux/cdrom.h>
+
 #include "runtime.h"
 #include "bufparser.h"
 #include "digest.h"
 #include "testcase.h"
 #include "util.h"
 
+#define PROC_PARTITIONS_PATH   "/proc/partitions"
+#define SYSFS_BLOCK_PATH       "/sys/block"
+
+#define GPT_PREP_UUID          "9E1A2D38-C612-4316-AA26-8B49521E5A8B"
+#define DOS_PREP_TYPE          0x41
+
+
 struct file_locator {
        char *          partition;
        char *          relative_path;
@@ -290,6 +304,432 @@
        return result;
 }
 
+static bool
+is_parent_block(char *blkname)
+{
+       char buf[PATH_MAX];
+       struct stat f_stat;
+
+       /* Check /sys/block/<blkname>/dev */
+       snprintf(buf, PATH_MAX, "%s/%s/dev", SYSFS_BLOCK_PATH, blkname);
+
+       return (stat(buf, &f_stat) == 0);
+}
+
+#ifdef CDROM_GET_CAPABILITY
+static bool
+blkdev_is_cdrom(int fd)
+{
+       int ret;
+
+       if ((ret = ioctl(fd, CDROM_GET_CAPABILITY, NULL)) < 0)
+               return false;
+
+       return !!ret;
+}
+#else
+static bool
+blkdev_is_cdrom(int fd __attribute__((__unused__)))
+{
+       return false;
+}
+#endif
+
+static bool
+is_cdrom_or_tape(char *device)
+{
+       int fd;
+       bool ret;
+
+       if ((fd = open(device, O_RDONLY|O_NONBLOCK)) < 0)
+               return 0;
+       ret = blkdev_is_cdrom(fd);
+
+       close(fd);
+       return ret;
+}
+
+static char *
+next_proc_partition (FILE **f)
+{
+       char line[128 + 1];
+       char buf[PATH_MAX];
+       char devpath[PATH_MAX];
+
+       if (!*f) {
+               *f = fopen(PROC_PARTITIONS_PATH, "r");
+               if (!*f) {
+                       fprintf(stderr, "cannot open %s", PROC_PARTITIONS_PATH);
+                       return NULL;
+               }
+       }
+
+       /*
+        * Example of /proc/partitions
+        *
+        * major minor  #blocks  name
+        *
+        *    8        0   41943040 sda
+        *    8        1       8192 sda1
+        *    8        2   41933807 sda2
+        *  254        0   41917423 dm-0
+        */
+       while (fgets(line, sizeof(line), *f)) {
+               if (sscanf(line, " %*d %*d %*d %128[^\n ]", buf) != 1)
+                       continue;
+
+               /* The partition table is only available to the parent block 
device */
+               if (!is_parent_block(buf))
+                       continue;
+
+               if (snprintf(devpath, PATH_MAX, "/dev/%s", buf) < 0)
+                       return NULL;
+
+               if (!is_cdrom_or_tape(devpath))
+                       return strdup(devpath);
+       }
+       fclose(*f);
+       *f = NULL;
+
+       return NULL;
+}
+
+static int
+is_prep_partition(struct fdisk_parttype *ptype, int is_gpt)
+{
+       const char *typestr;
+
+       if (is_gpt) {
+               typestr = fdisk_parttype_get_string(ptype);
+               return !!(strcmp(typestr, GPT_PREP_UUID) == 0);
+       } else {
+               return !!(fdisk_parttype_get_code(ptype) == DOS_PREP_TYPE);
+       }
+       return 0;
+}
+
+static char *
+locate_prep_partition_real(char *devname)
+{
+       struct fdisk_context *cxt = NULL;
+       struct fdisk_table *tb = NULL;
+       struct fdisk_iter *itr = NULL;
+       struct fdisk_partition *part = NULL;
+       struct fdisk_parttype *ptype = NULL;
+       int is_gpt = 0;
+       char *prep_dev = NULL;
+
+       cxt = fdisk_new_context();
+
+       if (fdisk_assign_device(cxt, devname, 1) < 0)
+               goto done;
+
+       /* PReP partition only in GPT or MBR */
+       if (fdisk_is_labeltype(cxt, FDISK_DISKLABEL_GPT) == 1)
+               is_gpt = 1;
+       else if (fdisk_is_labeltype(cxt, FDISK_DISKLABEL_DOS) == 1)
+               is_gpt = 0;
+       else
+               goto done;
+
+       if (fdisk_get_partitions(cxt, &tb) || fdisk_table_get_nents(tb) <= 0)
+               goto done;
+
+       itr = fdisk_new_iter(FDISK_ITER_FORWARD);
+       if (itr == NULL) {
+               error("failed to allocate fdisk iterator\n");
+               goto done;
+       }
+
+       /* Go through the partitions to find PReP partition */
+       while (fdisk_table_next_partition(tb, itr, &part) == 0) {
+               ptype = fdisk_partition_get_type(part);
+               if (ptype == NULL)
+                       continue;
+
+               if (!is_prep_partition(ptype, is_gpt))
+                       continue;
+
+               fdisk_partition_to_string(part, cxt,
+                                         FDISK_FIELD_DEVICE,
+                                         &prep_dev);
+               break;
+       }
+done:
+       if (itr)
+               fdisk_free_iter(itr);
+       if (tb)
+               fdisk_unref_table(tb);
+       fdisk_unref_context(cxt);
+
+       return prep_dev;
+}
+
+char *
+runtime_locate_prep_partition(void)
+{
+       static char prep_dev[PATH_MAX];
+       FILE *f = NULL;
+       char *devname = NULL;
+       char *prep_tmp = NULL;
+
+       if (testcase_playback)
+               return testcase_playback_prep_partition(testcase_playback);
+
+       if (prep_dev[0] != '\0')
+               return strdup(prep_dev);
+
+       while ((devname = next_proc_partition(&f))) {
+               prep_tmp = locate_prep_partition_real(devname);
+               free(devname);
+
+               if (prep_tmp != NULL) {
+                       snprintf(prep_dev, PATH_MAX, "%s", prep_tmp);
+                       break;
+               }
+       }
+
+       if (testcase_recording)
+               testcase_record_prep_partition(testcase_recording, prep_tmp);
+       return prep_tmp;
+}
+
+static int
+calculate_elf32_size(Elf *elf, size_t max_size, size_t *result)
+{
+       Elf32_Ehdr *ehdr = NULL;
+       Elf32_Phdr *phdrs = NULL, *phdr = NULL;
+       Elf_Scn *scn = NULL;
+       Elf32_Shdr *shdr = NULL;
+       size_t elf_size = 0;
+       int i;
+
+       if (result == NULL)
+               return -1;
+
+       if ((ehdr = elf32_getehdr(elf)) == NULL)
+               return -1;
+
+       elf_size = ehdr->e_phoff;
+       phdrs = elf32_getphdr(elf);
+       if (phdrs == NULL)
+               return -1;
+
+       for (i = 0; i < ehdr->e_phnum; i++) {
+               phdr = phdrs + i;
+
+               elf_size = MAX(phdr->p_offset + phdr->p_filesz, elf_size);
+               if (elf_size > max_size)
+                       return -1;
+       }
+
+       for (i = 0; i < ehdr->e_shnum; i++) {
+               if ((scn = elf_getscn(elf, i)) == NULL)
+                       return -1;
+               if ((shdr = elf32_getshdr(scn)) == NULL)
+                       return -1;
+
+               elf_size = MAX(shdr->sh_offset + shdr->sh_size, elf_size);
+               if (elf_size > max_size)
+                       return -1;
+       }
+
+       *result = elf_size;
+
+       return 0;
+}
+
+static int
+calculate_elf64_size(Elf *elf, size_t max_size, size_t *result)
+{
+       Elf64_Ehdr *ehdr = NULL;
+       Elf64_Phdr *phdrs = NULL, *phdr = NULL;
+       Elf_Scn *scn = NULL;
+       Elf64_Shdr *shdr = NULL;
+       size_t elf_size = 0;
+       int i;
+
+       if (result == NULL)
+               return -1;
+
+       if ((ehdr = elf64_getehdr(elf)) == NULL)
+               return -1;
+
+       elf_size = ehdr->e_phoff;
+       phdrs = elf64_getphdr(elf);
+       if (phdrs == NULL)
+               return -1;
+
+       for (i = 0; i < ehdr->e_phnum; i++) {
+               phdr = phdrs + i;
+
+               elf_size = MAX(phdr->p_offset + phdr->p_filesz, elf_size);
+               if (elf_size > max_size)
+                       return -1;
+       }
+
+       for (i = 0; i < ehdr->e_shnum; i++) {
+               if ((scn = elf_getscn(elf, i)) == NULL)
+                       return -1;
+               if ((shdr = elf64_getshdr(scn)) == NULL)
+                       return -1;
+
+               elf_size = MAX(shdr->sh_offset + shdr->sh_size, elf_size);
+               if (elf_size > max_size)
+                       return -1;
+       }
+
+       *result = elf_size;
+
+       return 0;
+}
+
+static int
+prep_bootloader_size (block_dev_io_t *prep_io, size_t *result)
+{
+       buffer_t *buffer = NULL;
+       Elf *elf = NULL;
+       size_t part_size = 0;
+       size_t elf_size;
+       int ret = -1;
+
+       if (result == NULL)
+               return -1;
+
+       part_size = lseek(prep_io->fd, 0, SEEK_END);
+
+       /* The first two blocks (1KB) should be enough to cover all the ELF
+        * headers (ELF headers, program headers, and section headers). */
+       if ((buffer = runtime_blockdev_read_lba(prep_io, 0, 2)) == NULL) {
+               error("Unable to read the first two blocks\n");
+               goto failed;
+       }
+
+       /* Read the ELF structure  */
+       if ((elf = elf_memory((char *)buffer->data, buffer->size)) == NULL) {
+               error("Failed to initialize Elf\n");
+               goto failed;
+       }
+
+       if (elf32_getehdr(elf) != NULL) {
+               ret = calculate_elf32_size(elf, part_size, &elf_size);
+       } else if (elf64_getehdr(elf) != NULL) {
+               ret = calculate_elf64_size(elf, part_size, &elf_size);
+       } else {
+               error("invalid ELF header\n");
+               goto failed;
+       }
+
+       if (ret < 0) {
+               error("Failed get ELF size\n");
+               goto failed;
+       }
+
+       /* Follow SLOF to round up the size */
+       elf_size = roundup(elf_size, 4);
+
+       *result = elf_size;
+
+       ret = 0;
+failed:
+       if (buffer)
+               buffer_free(buffer);
+       if (elf)
+               elf_end(elf);
+
+       return ret;
+}
+
+const tpm_evdigest_t *
+runtime_digest_prep_booloader(const tpm_algo_info_t *algo, const char 
*prep_partition)
+{
+       buffer_t *buffer = NULL;
+       block_dev_io_t *prep_io;
+       size_t bootloader_size = 0;
+       unsigned int nsector;
+       const tpm_evdigest_t *md = NULL;
+
+       if ((prep_io = runtime_blockdev_open(prep_partition)) == NULL) {
+               error("Unable to open disk device %s: %m\n", prep_partition);
+               goto failed;
+       }
+
+       if (prep_bootloader_size(prep_io, &bootloader_size) < 0) {
+               error("%s: unable to get bootloader size\n", prep_partition);
+               goto failed;
+       }
+
+       nsector = runtime_blockdev_bytes_to_sectors(prep_io, bootloader_size);
+
+       if ((buffer = runtime_blockdev_read_lba(prep_io, 0, nsector)) == NULL) {
+               error("%s: unable to read the full bootloader\n", 
prep_partition);
+               goto failed;
+       }
+
+       md = digest_compute(algo, buffer->data, bootloader_size);
+
+failed:
+       if (prep_io >= 0)
+               runtime_blockdev_close(prep_io);
+       if (buffer)
+               buffer_free(buffer);
+
+       return md;
+}
+
+
+#define GRUB_ENVBLK_SIGNATURE   "# GRUB Environment Block\n"
+#define GRUB_ENVBLK_SIZE       4096
+
+const tpm_evdigest_t *
+runtime_digest_prep_envblk(const tpm_algo_info_t *algo, const char 
*prep_partition)
+{
+       buffer_t *buffer = NULL;
+       block_dev_io_t *io;
+       size_t nsector, start;
+       off_t part_size;
+       const tpm_evdigest_t *md = NULL;
+
+       if ((io = runtime_blockdev_open(prep_partition)) == NULL) {
+               error("Unable to open disk device %s: %m\n", prep_partition);
+               goto failed;
+       }
+
+       if ((part_size = lseek(io->fd, 0, SEEK_END)) < 0) {
+               error("block dev seek: %m\n");
+               goto failed;
+       }
+
+       /* read the last 4096 bytes */
+       if (part_size < GRUB_ENVBLK_SIZE) {
+               error("insufficient partition size\n");
+               goto failed;
+       }
+
+       start = runtime_blockdev_bytes_to_sectors(io, part_size - 
GRUB_ENVBLK_SIZE);
+       nsector = runtime_blockdev_bytes_to_sectors(io, GRUB_ENVBLK_SIZE);
+
+       if ((buffer = runtime_blockdev_read_lba(io, start, nsector)) == NULL) {
+               error("%s: unable to read envblk\n", prep_partition);
+               goto failed;
+       }
+
+       if (memcmp(buffer->data, GRUB_ENVBLK_SIGNATURE, 
strlen(GRUB_ENVBLK_SIGNATURE)) != 0) {
+               error("%s: invalid envblk signature\n", prep_partition);
+               goto failed;
+       }
+
+       md = digest_compute(algo, buffer->data, GRUB_ENVBLK_SIZE);
+
+failed:
+       if (io >= 0)
+               runtime_blockdev_close(io);
+       if (buffer)
+               buffer_free(buffer);
+
+       return md;
+}
+
 char *
 runtime_disk_for_partition(const char *part_dev)
 {
@@ -398,14 +838,14 @@
        free(io);
 }
 
-unsigned int
-runtime_blockdev_bytes_to_sectors(const block_dev_io_t *io, unsigned int size)
+size_t
+runtime_blockdev_bytes_to_sectors(const block_dev_io_t *io, size_t size)
 {
        return (size + io->sector_size - 1) / io->sector_size;
 }
 
 buffer_t *
-runtime_blockdev_read_lba(block_dev_io_t *io, unsigned int block, unsigned int 
count)
+runtime_blockdev_read_lba(block_dev_io_t *io, size_t block, size_t count)
 {
        unsigned long offset = block * io->sector_size;
        unsigned int bytes;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/src/runtime.h 
new/pcr-oracle-0.5.7/src/runtime.h
--- old/pcr-oracle-0.5.6/src/runtime.h  2025-05-13 08:48:20.000000000 +0200
+++ new/pcr-oracle-0.5.7/src/runtime.h  2025-05-29 09:26:41.000000000 +0200
@@ -40,13 +40,16 @@
 extern buffer_t *      runtime_read_efi_application(const char *partition, 
const char *application);
 extern const tpm_evdigest_t *runtime_digest_efi_file(const tpm_algo_info_t 
*algo, const char *path);
 extern const tpm_evdigest_t *runtime_digest_rootfs_file(const tpm_algo_info_t 
*algo, const char *path);
+extern char *          runtime_locate_prep_partition(void);
+extern const tpm_evdigest_t *runtime_digest_prep_booloader(const 
tpm_algo_info_t *algo, const char *prep_partition);
+extern const tpm_evdigest_t *runtime_digest_prep_envblk(const tpm_algo_info_t 
*algo, const char *prep_partition);
 extern char *          runtime_disk_for_partition(const char *part_dev);
 extern char *          runtime_blockdev_by_partuuid(const char *uuid);
 extern block_dev_io_t *        runtime_blockdev_open(const char *dev);
-extern buffer_t *      runtime_blockdev_read_lba(block_dev_io_t *, unsigned 
int block, unsigned int count);
+extern buffer_t *      runtime_blockdev_read_lba(block_dev_io_t *, size_t 
block, size_t count);
 extern void            runtime_blockdev_close(block_dev_io_t *);
 
-extern unsigned int    runtime_blockdev_bytes_to_sectors(const block_dev_io_t 
*, unsigned int size);
+extern size_t          runtime_blockdev_bytes_to_sectors(const block_dev_io_t 
*, size_t size);
 
 extern void            runtime_record_testcase(testcase_t *);
 extern void            runtime_replay_testcase(testcase_t *);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/src/testcase.c 
new/pcr-oracle-0.5.7/src/testcase.c
--- old/pcr-oracle-0.5.6/src/testcase.c 2025-05-13 08:48:20.000000000 +0200
+++ new/pcr-oracle-0.5.7/src/testcase.c 2025-05-29 09:26:41.000000000 +0200
@@ -42,6 +42,7 @@
        char *                  partition_directory;
        char *                  disk_directory;
        char *                  hash_log;
+       char *                  prep_partition;
 
        FILE *                  hash_log_fp;
 };
@@ -189,7 +190,8 @@
                fatal("Cannot read symlink %s: %m\n", path);
 
        if (target[0] != '/' && default_dir) {
-               snprintf(result, sizeof(result), "%s/%s", default_dir, target);
+               if (snprintf(result, sizeof(result), "%s/%s", default_dir, 
target) < 0)
+                       return NULL;
                return strdup(result);
        }
 
@@ -599,3 +601,38 @@
 {
        return testcase_playback_digest(tc, "efi", path, algo);
 }
+
+void
+testcase_record_prep_partition(testcase_t *tc, const char *path)
+{
+       int fd;
+
+       if ((fd = testcase_create_file(tc->base_directory, "prep_partition")) < 
0)
+               fatal("Failed to create PReP partition recording file: %m\n");
+
+       if (write(fd, path, strlen(path) + 1) < 0)
+               fatal("Failed to record PReP partition: %m\n");
+
+       close(fd);
+}
+
+char *
+testcase_playback_prep_partition(testcase_t *tc)
+{
+       int fd;
+       char buf[PATH_MAX];
+       ssize_t count;
+
+       if ((fd = testcase_open_file(tc->base_directory, "prep_partition")) < 0)
+               return NULL;
+
+       count = read(fd, buf, PATH_MAX - 1);
+       if (count < 0)
+               fatal("failed to read prep_partition: %m\n");
+
+       buf[count+1] = '\0';
+
+       close(fd);
+
+       return strdup(buf);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pcr-oracle-0.5.6/src/testcase.h 
new/pcr-oracle-0.5.7/src/testcase.h
--- old/pcr-oracle-0.5.6/src/testcase.h 2025-05-13 08:48:20.000000000 +0200
+++ new/pcr-oracle-0.5.7/src/testcase.h 2025-05-29 09:26:41.000000000 +0200
@@ -47,6 +47,8 @@
 extern const tpm_evdigest_t *  testcase_playback_rootfs_digest(testcase_t *, 
const char *path, const tpm_algo_info_t *algo);
 extern void                    testcase_record_efi_digest(testcase_t *, const 
char *path, const tpm_evdigest_t *md);
 extern const tpm_evdigest_t *  testcase_playback_efi_digest(testcase_t *, 
const char *path, const tpm_algo_info_t *algo);
+extern void                    testcase_record_prep_partition(testcase_t *, 
const char *path);
+extern char *                  testcase_playback_prep_partition(testcase_t *);
 
 #include <stdio.h>
 

Reply via email to