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 2026-02-02 14:55:17 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pcr-oracle (Old) and /work/SRC/openSUSE:Factory/.pcr-oracle.new.1995 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "pcr-oracle" Mon Feb 2 14:55:17 2026 rev:24 rq:1330345 version:0.5.9 Changes: -------- --- /work/SRC/openSUSE:Factory/pcr-oracle/pcr-oracle.changes 2026-01-28 15:08:10.524565970 +0100 +++ /work/SRC/openSUSE:Factory/.pcr-oracle.new.1995/pcr-oracle.changes 2026-02-02 14:55:57.388451121 +0100 @@ -1,0 +2,7 @@ +Mon Feb 2 07:38:47 UTC 2026 - Gary Ching-Pang Lin <[email protected]> + +- Update to 0.5.9 + + Fix event skipping due to double increment + + Add '--persistent-srk' to make SRK persistent (bsc#1248516) + +------------------------------------------------------------------- Old: ---- pcr-oracle-0.5.8.tar.xz New: ---- pcr-oracle-0.5.9.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pcr-oracle.spec ++++++ --- /var/tmp/diff_new_pack.HY9uTE/_old 2026-02-02 14:55:57.980476145 +0100 +++ /var/tmp/diff_new_pack.HY9uTE/_new 2026-02-02 14:55:57.984476313 +0100 @@ -1,7 +1,7 @@ # # spec file for package pcr-oracle # -# Copyright (c) 2025 SUSE LLC +# Copyright (c) 2026 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ Name: pcr-oracle -Version: 0.5.8 +Version: 0.5.9 Release: 0 Summary: Predict TPM PCR values License: GPL-2.0-or-later ++++++ _service ++++++ --- /var/tmp/diff_new_pack.HY9uTE/_old 2026-02-02 14:55:58.016477666 +0100 +++ /var/tmp/diff_new_pack.HY9uTE/_new 2026-02-02 14:55:58.024478004 +0100 @@ -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.8</param> + <param name="revision">refs/tags/0.5.9</param> </service> <service name="recompress" mode="disabled"> <param name="file">pcr-oracle*.tar</param> ++++++ pcr-oracle-0.5.8.tar.xz -> pcr-oracle-0.5.9.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcr-oracle-0.5.8/configure new/pcr-oracle-0.5.9/configure --- old/pcr-oracle-0.5.8/configure 2025-10-07 04:39:23.000000000 +0200 +++ new/pcr-oracle-0.5.9/configure 2026-02-02 08:35:19.000000000 +0100 @@ -12,7 +12,7 @@ # Invoke with --help for a description of options # # microconf:begin -# version 0.5.8 +# version 0.5.9 # require libtss2 # require json # require libfdisk diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcr-oracle-0.5.8/microconf/version new/pcr-oracle-0.5.9/microconf/version --- old/pcr-oracle-0.5.8/microconf/version 2025-10-07 04:39:23.000000000 +0200 +++ new/pcr-oracle-0.5.9/microconf/version 2026-02-02 08:35:19.000000000 +0100 @@ -1 +1 @@ -uc_version=0.5.8 +uc_version=0.5.9 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcr-oracle-0.5.8/src/oracle.c new/pcr-oracle-0.5.9/src/oracle.c --- old/pcr-oracle-0.5.8/src/oracle.c 2025-10-07 04:39:23.000000000 +0200 +++ new/pcr-oracle-0.5.9/src/oracle.c 2026-02-02 08:35:19.000000000 +0100 @@ -104,6 +104,7 @@ OPT_TARGET_PLATFORM, OPT_BOOT_ENTRY, OPT_COMPARE_CURRENT, + OPT_PERSISTENT_SRK, }; static struct option options[] = { @@ -139,6 +140,7 @@ { "target-platform", required_argument, 0, OPT_TARGET_PLATFORM }, { "next-kernel", required_argument, 0, OPT_BOOT_ENTRY }, { "compare-current", no_argument, 0, OPT_COMPARE_CURRENT }, + { "persistent-srk", required_argument, 0, OPT_PERSISTENT_SRK }, { NULL } }; @@ -948,7 +950,7 @@ tpm_event_t *ev, *ev_cmp; const tpm_evdigest_t *predicted_digest, *cmp_digest; - for(ev = pred->event_log, ev_cmp = pred_cmp->event_log; ev; ev = ev->next, ev_cmp = ev_cmp->next) { + for(ev = pred->event_log, ev_cmp = pred_cmp->event_log; ev; ev = ev->next) { bool stop = false; stop = (ev == stop_event); if (stop && !pred->stop_event.after) { @@ -1175,6 +1177,7 @@ char *opt_target_platform = NULL; char *opt_boot_entry = NULL; bool opt_compare_current = false; + char *opt_persistent_srk = NULL; const target_platform_t *target; unsigned int action_flags = 0; unsigned int rsa_bits = 2048; @@ -1281,6 +1284,9 @@ case OPT_COMPARE_CURRENT: opt_compare_current = true; break; + case OPT_PERSISTENT_SRK: + opt_persistent_srk = optarg; + break; case 'h': usage(0, NULL); default: @@ -1443,7 +1449,7 @@ /* When sealing a secret against an authorized policy, there's no need to * mess around with PCR values. That's the beauty of it... */ if (action == ACTION_SEAL && opt_authorized_policy) { - if (!pcr_authorized_policy_seal_secret(target, opt_authorized_policy, opt_input, opt_output)) + if (!pcr_authorized_policy_seal_secret(target, opt_authorized_policy, opt_persistent_srk, opt_input, opt_output)) return 1; return 0; @@ -1491,7 +1497,7 @@ predictor_report(pred); } else if (action == ACTION_SEAL) { - if (!pcr_seal_secret(target, &pred->prediction, opt_input, opt_output)) + if (!pcr_seal_secret(target, &pred->prediction, opt_persistent_srk, opt_input, opt_output)) return 1; } else if (action == ACTION_SIGN) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcr-oracle-0.5.8/src/pcr-policy.c new/pcr-oracle-0.5.9/src/pcr-policy.c --- old/pcr-oracle-0.5.8/src/pcr-policy.c 2025-10-07 04:39:23.000000000 +0200 +++ new/pcr-oracle-0.5.9/src/pcr-policy.c 2026-02-02 08:35:19.000000000 +0100 @@ -47,6 +47,7 @@ unsigned int unseal_flags; bool (*write_sealed_secret)(const char *pathname, + const TPM2_HANDLE persistent_addr, const TPML_PCR_SELECTION *pcr_sel, const TPM2B_PRIVATE *sealed_private, const TPM2B_PUBLIC *sealed_public); @@ -660,6 +661,69 @@ } static bool +esys_make_handle_persistent(ESYS_CONTEXT *esys_context, ESYS_TR handle, TPMI_DH_PERSISTENT persistent_handle, ESYS_TR *obj_handle) +{ + ESYS_TR tmp_obj; + TSS2_RC rc; + + if (obj_handle == NULL) + return false; + + /* Try to make the object persistent */ + infomsg("Making SRK persistent in 0x%X\n", persistent_handle); + rc = Esys_EvictControl(esys_context, + ESYS_TR_RH_OWNER, /* auth */ + handle, /* objectHandle */ + ESYS_TR_PASSWORD, /* shandle1 */ + ESYS_TR_NONE, /* shandle2 */ + ESYS_TR_NONE, /* shandle3 */ + persistent_handle, /* persistentHandle */ + obj_handle /* newObjectHandle */ + ); + + /* If a persistent object already exists in the persistent handle (address), + * TPM2_EvictControl returns TPM2_RC_NV_DEFINED. */ + if (rc == TSS2_RC_SUCCESS) + return true; + else if (rc != TPM2_RC_NV_DEFINED && !tss_check_error(rc, "Esys_EvictControl failed")) + return false; + + /* Remove the object from the specified persistent handle (address) */ + infomsg("Removing the previous persistent object from 0x%X\n", persistent_handle); + rc = Esys_TR_FromTPMPublic(esys_context, persistent_handle, + ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &tmp_obj); + if (!tss_check_error(rc, "Esys_TR_FromTPMPublic failed")) + return false; + rc = Esys_EvictControl(esys_context, + ESYS_TR_RH_OWNER, /* auth */ + tmp_obj, /* objectHandle */ + ESYS_TR_PASSWORD, /* shandle1 */ + ESYS_TR_NONE, /* shandle2 */ + ESYS_TR_NONE, /* shandle3 */ + persistent_handle, /* persistentHandle */ + &tmp_obj /* newObjectHandle */ + ); + if (!tss_check_error(rc, "Esys_EvictControl failed")) + return false; + + /* Try again to make the object persistent */ + infomsg("Making SRK persistent in 0x%X again\n", persistent_handle); + rc = Esys_EvictControl(esys_context, + ESYS_TR_RH_OWNER, /* auth */ + handle, /* objectHandle */ + ESYS_TR_PASSWORD, /* shandle1 */ + ESYS_TR_NONE, /* shandle2 */ + ESYS_TR_NONE, /* shandle3 */ + persistent_handle, /* persistentHandle */ + obj_handle /* newObjectHandle */ + ); + if (!tss_check_error(rc, "Esys_EvictControl failed")) + return false; + + return true; +} + +static bool esys_create(ESYS_CONTEXT *esys_context, ESYS_TR srk_handle, TPM2B_DIGEST *authorized_policy, TPM2B_SENSITIVE_DATA *secret, TPM2B_PRIVATE **out_private, TPM2B_PUBLIC **out_public) @@ -690,12 +754,14 @@ static bool esys_seal_secret(const target_platform_t *platform, ESYS_CONTEXT *esys_context, TPM2B_DIGEST *policy, const TPML_PCR_SELECTION *pcr_sel, - const char *input_path, const char *output_path) + const char *opt_persistent_srk, const char *input_path, const char *output_path) { TPM2B_SENSITIVE_DATA *secret = NULL; TPM2B_PRIVATE *sealed_private = NULL; TPM2B_PUBLIC *sealed_public = NULL; ESYS_TR srk_handle = ESYS_TR_NONE; + ESYS_TR obj_handle = ESYS_TR_NONE; + TPM2_HANDLE persistent_handle = 0; bool ok = false; if (!(secret = read_secret(input_path))) @@ -706,10 +772,24 @@ if (!esys_create_primary(esys_context, &srk_handle)) goto cleanup; + /* Make SRK persistent if requested */ + if (opt_persistent_srk != NULL) { + /* Convert opt_persistent_srk to TPM2 handle */ + persistent_handle = strtoul(opt_persistent_srk, NULL, 16); + if ((persistent_handle >> TPM2_HR_SHIFT) != TPM2_HT_PERSISTENT) { + error("Not a valid persistent handle, e.g. 0x81000000\n"); + goto cleanup; + } + + if (!esys_make_handle_persistent(esys_context, srk_handle, + persistent_handle, &obj_handle)) + goto cleanup; + } + if (!esys_create(esys_context, srk_handle, policy, secret, &sealed_private, &sealed_public)) goto cleanup; - ok = platform->write_sealed_secret(output_path, pcr_sel, sealed_private, sealed_public); + ok = platform->write_sealed_secret(output_path, persistent_handle, pcr_sel, sealed_private, sealed_public); if (ok) infomsg("Sealed secret written to %s\n", output_path?: "(standard output)"); @@ -1052,7 +1132,7 @@ bool pcr_seal_secret(const target_platform_t *platform, const tpm_pcr_bank_t *bank, - const char *input_path, const char *output_path) + const char *opt_persistent_srk, const char *input_path, const char *output_path) { ESYS_CONTEXT *esys_context = tss_esys_context(); TPM2B_DIGEST *pcr_policy = NULL; @@ -1066,7 +1146,7 @@ return false; ok = esys_seal_secret(platform, esys_context, pcr_policy, &pcr_sel, - input_path, output_path); + opt_persistent_srk, input_path, output_path); free(pcr_policy); return ok; @@ -1127,7 +1207,8 @@ bool pcr_authorized_policy_seal_secret(const target_platform_t *platform, const char *authpolicy_path, - const char *input_path, const char *output_path) + const char *opt_persistent_srk, const char *input_path, + const char *output_path) { ESYS_CONTEXT *esys_context = tss_esys_context(); TPM2B_DIGEST *authorized_policy = NULL; @@ -1137,7 +1218,7 @@ return false; ok = esys_seal_secret(platform, esys_context, authorized_policy, NULL, - input_path, output_path); + opt_persistent_srk, input_path, output_path); free(authorized_policy); return ok; } @@ -1450,6 +1531,7 @@ buffer_t buf; TPM2B_PUBLIC pub = { 0 }; TPM2B_PRIVATE priv = { 0 }; + TPM2_HANDLE tmp_handle; ESYS_TR primary_handle = ESYS_TR_NONE; ESYS_TR sealed_object_handle = ESYS_TR_NONE; TPM2B_SENSITIVE_DATA *unsealed = NULL; @@ -1474,7 +1556,14 @@ if (rc != TSS2_RC_SUCCESS) goto cleanup; - if (!esys_create_primary(esys_context, &primary_handle)) + tmp_handle = ASN1_INTEGER_get(tpm2key->parent); + if ((tmp_handle >> TPM2_HR_SHIFT) == TPM2_HT_PERSISTENT) { + rc = Esys_TR_FromTPMPublic(esys_context, tmp_handle, + ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, + &primary_handle); + if (!tss_check_error(rc, "Esys_TR_FromTPMPublic failed")) + goto cleanup; + } else if (!esys_create_primary(esys_context, &primary_handle)) goto cleanup; rc = Esys_Load(esys_context, primary_handle, @@ -1543,6 +1632,7 @@ */ static bool oldgrub_write_sealed_secret(const char *pathname, + const TPM2_HANDLE persistent_addr, const TPML_PCR_SELECTION *pcr_sel, const TPM2B_PRIVATE *sealed_private, const TPM2B_PUBLIC *sealed_public) @@ -1583,14 +1673,21 @@ */ static bool tpm2key_write_sealed_secret(const char *pathname, + const TPM2_HANDLE persistent_addr, const TPML_PCR_SELECTION *pcr_sel, const TPM2B_PRIVATE *sealed_private, const TPM2B_PUBLIC *sealed_public) { TSSPRIVKEY *tpm2key = NULL; + TPM2_HANDLE parent; bool ok = false; - if (!tpm2key_basekey(&tpm2key, TPM2_RH_OWNER, sealed_public, sealed_private)) + if (persistent_addr == 0) + parent = TPM2_RH_OWNER; + else + parent = persistent_addr; + + if (!tpm2key_basekey(&tpm2key, parent, sealed_public, sealed_private)) goto cleanup; if (SRK_template->publicArea.type == TPM2_ALG_RSA) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcr-oracle-0.5.8/src/pcr.h new/pcr-oracle-0.5.9/src/pcr.h --- old/pcr-oracle-0.5.8/src/pcr.h 2025-10-07 04:39:23.000000000 +0200 +++ new/pcr-oracle-0.5.9/src/pcr.h 2026-02-02 08:35:19.000000000 +0100 @@ -67,10 +67,11 @@ const char *input_path, const char *output_path, const char *policy_name); extern bool pcr_authorized_policy_seal_secret(const target_platform_t *platform, - const char *authorized_policy, const char *input_path, - const char *output_path); -extern bool pcr_seal_secret(const target_platform_t *, const tpm_pcr_bank_t *bank, + const char *opt_persistent_srk, const char *authorized_policy, const char *input_path, const char *output_path); +extern bool pcr_seal_secret(const target_platform_t *, const tpm_pcr_bank_t *bank, + const char *opt_persistent_srk, const char *input_path, + const char *output_path); extern bool pcr_unseal_secret(const target_platform_t *, const tpm_pcr_selection_t *pcr_selection, const char *signed_policy_path, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcr-oracle-0.5.8/src/tpm2key.c new/pcr-oracle-0.5.9/src/tpm2key.c --- old/pcr-oracle-0.5.8/src/tpm2key.c 2025-10-07 04:39:23.000000000 +0200 +++ new/pcr-oracle-0.5.9/src/tpm2key.c 2026-02-02 08:35:19.000000000 +0100 @@ -53,7 +53,8 @@ key->type = OBJ_txt2obj(OID_sealedData, 1); key->emptyAuth = 1; key->parent = ASN1_INTEGER_new(); - ASN1_INTEGER_set(key->parent, parent); + /* Convert 'parent' to 'int32_t' to make sure 'parent' only occupies at most 4 bytes */ + ASN1_INTEGER_set(key->parent, (int32_t)parent); key->pubkey = ASN1_OCTET_STRING_new(); ASN1_STRING_set(key->pubkey, bp_pub->data, buffer_available(bp_pub));
