commit pcr-oracle for openSUSE:Factory
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 2024-08-08 10:57:03 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pcr-oracle (Old) and /work/SRC/openSUSE:Factory/.pcr-oracle.new.7232 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "pcr-oracle" Thu Aug 8 10:57:03 2024 rev:14 rq:1192055 version:0.5.4 Changes: -------- --- /work/SRC/openSUSE:Factory/pcr-oracle/pcr-oracle.changes 2024-03-26 19:27:48.490143709 +0100 +++ /work/SRC/openSUSE:Factory/.pcr-oracle.new.7232/pcr-oracle.changes 2024-08-08 10:57:20.717022562 +0200 @@ -1,0 +2,7 @@ +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 + +------------------------------------------------------------------- New: ---- fix-testcase-empty-efi-variables.patch support-ecc-srk.patch BETA DEBUG BEGIN: New:- 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 New: - Add support-ecc-srk.patch to support ECC SRK - Add fix-testcase-empty-efi-variables.patch to fix the testcase BETA DEBUG END: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pcr-oracle.spec ++++++ --- /var/tmp/diff_new_pack.d2s5o3/_old 2024-08-08 10:57:21.225043446 +0200 +++ /var/tmp/diff_new_pack.d2s5o3/_new 2024-08-08 10:57:21.225043446 +0200 @@ -34,6 +34,10 @@ 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 BuildRequires: libopenssl-devel >= 0.9.8 BuildRequires: tpm2-0-tss-devel >= 2.4.0 Requires: libtss2-tcti-device0 ++++++ fix-testcase-empty-efi-variables.patch ++++++ 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 ++++++ support-ecc-srk.patch ++++++ 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
participants (1)
-
Source-Sync