Package sources for project devel:languages:perl are received through scmsync. This is not supported by the OBS frontend

File support-ecc-srk.patch of Package pcr-oracle

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

openSUSE Build Service is sponsored by