Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package openssl_tpm2_engine for
openSUSE:Factory checked in at 2024-01-03 12:30:40
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openssl_tpm2_engine (Old)
and /work/SRC/openSUSE:Factory/.openssl_tpm2_engine.new.28375 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "openssl_tpm2_engine"
Wed Jan 3 12:30:40 2024 rev:15 rq:1136249 version:4.1.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/openssl_tpm2_engine/openssl_tpm2_engine.changes
2023-12-05 17:03:26.945662632 +0100
+++
/work/SRC/openSUSE:Factory/.openssl_tpm2_engine.new.28375/openssl_tpm2_engine.changes
2024-01-03 12:31:20.057387821 +0100
@@ -1,0 +2,12 @@
+Tue Jan 1 16:07:25 UTC 2024 - [email protected]
+
+- Update to version 4.1.1
+ * fix 32 bit build
+
+-------------------------------------------------------------------
+Mon Dec 31 03:55:34 UTC 2023 - [email protected]
+
+- Update to version 4.1.0
+ * implement tpm2_PolicySecret
+
+-------------------------------------------------------------------
Old:
----
openssl_tpm2_engine-4.0.2.tar.gz
New:
----
openssl_tpm2_engine-4.1.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ openssl_tpm2_engine.spec ++++++
--- /var/tmp/diff_new_pack.P6UOqr/_old 2024-01-03 12:31:20.621408449 +0100
+++ /var/tmp/diff_new_pack.P6UOqr/_new 2024-01-03 12:31:20.621408449 +0100
@@ -1,7 +1,7 @@
#
# spec file for package openssl_tpm2_engine
#
-# Copyright (c) 2023 SUSE LLC
+# Copyright (c) 2024 SUSE LLC
# Copyright (c) 2017 [email protected]
#
# All modifications and additions to the file contributed by third parties
@@ -18,7 +18,7 @@
Name: openssl_tpm2_engine
-Version: 4.0.2
+Version: 4.1.1
Release: 0
Summary: OpenSSL TPM 2.0 interface engine plugin
License: LGPL-2.1-only
++++++ openssl_tpm2_engine-4.0.2.tar.gz -> openssl_tpm2_engine-4.1.1.tar.gz
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-4.0.2/configure.ac
new/openssl_tpm2_engine-4.1.1/configure.ac
--- old/openssl_tpm2_engine-4.0.2/configure.ac 2023-12-05 04:47:13.000000000
+0100
+++ new/openssl_tpm2_engine-4.1.1/configure.ac 2024-01-02 16:52:46.000000000
+0100
@@ -2,7 +2,7 @@
# configure.in for the OpenSSL TPM engine project
#
-AC_INIT(openssl-tpm2-engine, 4.0.2, <[email protected]>)
+AC_INIT(openssl-tpm2-engine, 4.1.1, <[email protected]>)
AM_INIT_AUTOMAKE([foreign 1.6.3])
AC_CANONICAL_HOST
AM_CONDITIONAL(NATIVE_BUILD, test "x$cross_compiling" = "xno")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openssl_tpm2_engine-4.0.2/doc/draft-bottomley-tpm2-keys.xml
new/openssl_tpm2_engine-4.1.1/doc/draft-bottomley-tpm2-keys.xml
--- old/openssl_tpm2_engine-4.0.2/doc/draft-bottomley-tpm2-keys.xml
2023-12-05 04:47:13.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/doc/draft-bottomley-tpm2-keys.xml
2024-01-02 16:52:46.000000000 +0100
@@ -23,7 +23,7 @@
<email>[email protected]</email>
</address>
</author>
- <date month="June" year="2023"/>
+ <date month="December" year="2023"/>
<area>Security</area>
<keyword>I-D</keyword>
<keyword>Internet-Draft</keyword>
@@ -277,7 +277,7 @@
This is a binary string representing a fully marshalled,
TPM ordered, command body for the TPM policy command.
Therefore to send the command, the implementation simply
- marshalls the command code and appends this octet string
+ marshals the command code and appends this octet string
as the body.
</t>
<t>
@@ -330,6 +330,25 @@
policySignature.
</t>
</section>
+ <section title="TPM2_PolicySecret">
+ <t>
+ According to <xref target="TPM2.0"/> the body of this
+ command consists of the handle of the authorizing object,
+ TPM2B_NONCE nonceTPM, TPM2B_DIGEST cpHashA, TPM2B_NONCE
+ policyRef and INT32 expiration. However, the policyHash
+ only uses policyRef and the name of the authorizing
+ object. Since the usual authorizing object for
+ TPM2_PolicySecret is a permanent handle or NV Index, and
+ those are hard to find by name, the handle is also given
+ as an optional hint in addition to the name.
+ </t>
+ <t>
+ The format of CommandPolicy for TPM2_PolicySecret MUST be
+ TPM_HANDLE objectHandleHint, TPM2B_NAME objectName,
+ TPM2B_DIGEST policyRef. Where objectHandleHint MAY be
+ zero to indicate no hint.
+ </t>
+ </section>
</section>
<section title="Policy Implementation Considerations">
<t>
@@ -364,16 +383,25 @@
<section title="Authorization Policy">
<t>
When Authorization (Passing in a password) is required,
- the emptyAuth parameter MUST be absent or set to false
- and additionally the TPM_CC_PolicyAuthValue MUST be
- specified as the command code for one entry in the
- TPMPolicy sequence. However, the implementation MAY
- choose to execute either TPM2_PolicyPassword for TPM_RS_PW
- or TPM2_PolicyAuthValue for HMAC based authorization
- depending on whether the command being authorized is using
- sessions or not. If the policy does not require an
- authorization then the emptyAuth parameter MUST be set to
- true.
+ the emptyAuth parameter MUST be absent or set to false and
+ additionally TPM_CC_PolicyAuthValue or TPM_CC_PolicySecret
+ MUST be specified as the command code for one entry in the
+ TPMPolicy sequence. However, when TPM2_PolicyAuthValue is
+ specified, the implementation MAY choose to execute either
+ TPM2_PolicyPassword for TPM_RS_PW or TPM2_PolicyAuthValue
+ for HMAC based authorization depending on whether the
+ command being authorized is using sessions or not. If the
+ policy does not require an authorization then the
+ emptyAuth parameter MUST be set to true.
+ </t>
+ <t>
+ Implementations should bear in mind that most crypto
+ systems with key management expect to consume only one
+ password per key, so implementations SHOULD avoid policy
+ chains which would require more than one password as would
+ happen when TPM2_PolicySecret and TPM2_PolicyAuthValue
+ both appear in the same policy chain. Implementations MAY
+ detect and emit an error in this case.
</t>
</section>
</section>
@@ -520,6 +548,25 @@
the TPM clock.
</t>
</section>
+ <section title="Policy Signing Keys and policyRef values">
+ <t>
+ There is a high likelihood that a consumer would use the
+ same policy signing key for multiple TPM objects with
+ signed policy. This gives rise to the risk that a
+ malicious user could extract signed policy meant for key1
+ and use it instead with key2 (policy swapping). To
+ mitigate this risk, the implementation SHOULD place a high
+ entropy nonce in policyRef to ensure that each key has a
+ different policyRef which prevents this policy swapping.
+ </t>
+ <t>
+ The TCG specifies that policyRef could have an
+ implementation defined meaning in which case
+ implementations MAY use implementation meaningful values
+ instead of nonces for policyRef but SHOULD take other
+ measures to prevent policy swapping.
+ </t>
+ </section>
</section>
</section>
<section anchor="implementation" title="Implementation Considerations">
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-4.0.2/src/engine/e_tpm2.c
new/openssl_tpm2_engine-4.1.1/src/engine/e_tpm2.c
--- old/openssl_tpm2_engine-4.0.2/src/engine/e_tpm2.c 2023-12-05
04:47:13.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/src/engine/e_tpm2.c 2024-01-02
16:52:46.000000000 +0100
@@ -177,7 +177,8 @@
rc = tpm2_get_bound_handle(tssContext, &session, key, NULL);
if (rc == TPM_RC_SUCCESS) {
- rc = tpm2_ReadPublic(tssContext, key, NULL, session);
+ rc = tpm2_ReadPublic(tssContext, key, NULL, session,
+ NULL);
if (rc)
tpm2_flush_handle(tssContext, session);
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-4.0.2/src/include/ibm-tss.h
new/openssl_tpm2_engine-4.1.1/src/include/ibm-tss.h
--- old/openssl_tpm2_engine-4.0.2/src/include/ibm-tss.h 2023-12-05
04:47:13.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/src/include/ibm-tss.h 2024-01-02
16:52:46.000000000 +0100
@@ -163,7 +163,7 @@
static inline TPM_RC
tpm2_ReadPublic(TSS_CONTEXT *tssContext, TPM_HANDLE objectHandle,
- TPMT_PUBLIC *pub, TPM_HANDLE auth)
+ TPMT_PUBLIC *pub, TPM_HANDLE auth, NAME_2B *name)
{
ReadPublic_In rin;
ReadPublic_Out rout;
@@ -190,6 +190,35 @@
if (pub)
*pub = rout.outPublic.publicArea;
+ if (name)
+ *name = rout.name.t;
+
+ return rc;
+}
+
+static inline TPM_RC
+tpm2_NV_ReadPublic(TSS_CONTEXT *tssContext, TPM_HANDLE nvIndex,
+ NAME_2B *nvName)
+{
+ TPM_RC rc;
+ NV_ReadPublic_In in;
+ NV_ReadPublic_Out out;
+
+ in.nvIndex = nvIndex;
+ rc = TSS_Execute (tssContext,
+ (RESPONSE_PARAMETERS *)&out,
+ (COMMAND_PARAMETERS *)&in,
+ NULL,
+ TPM_CC_NV_ReadPublic,
+ TPM_RH_NULL, NULL, 0);
+
+ if (rc) {
+ tpm2_error(rc, "TPM2_NV_ReadPublic");
+ return rc;
+ }
+
+ if (nvName)
+ *nvName = out.nvName.t;
return rc;
}
@@ -379,7 +408,7 @@
* access to the public part. It does this by keeping
* key files, but request the public part just to make
* sure*/
- tpm2_ReadPublic(tssContext, tpmKey, NULL, TPM_RH_NULL);
+ tpm2_ReadPublic(tssContext, tpmKey, NULL, TPM_RH_NULL, NULL);
/* don't care what rout returns, the purpose of the
* operation was to get the public key parameters into
* the tss so it can construct the salt */
@@ -584,6 +613,87 @@
return rc;
}
+
+static inline TPM_RC
+tpm2_PolicyLocality(TSS_CONTEXT *tssContext, TPM_HANDLE policySession,
+ UINT8 locality)
+{
+ PolicyLocality_In in;
+ TPM_RC rc;
+
+ in.policySession = policySession;
+ in.locality.val = locality;
+
+ rc = TSS_Execute(tssContext,
+ NULL,
+ (COMMAND_PARAMETERS *)&in,
+ NULL,
+ TPM_CC_PolicyLocality,
+ TPM_RH_NULL, NULL, 0);
+
+ return rc;
+}
+
+static inline TPM_RC
+tpm2_PolicySecret(TSS_CONTEXT *tssContext, TPM_HANDLE authHandle,
+ TPM_HANDLE policySession, DIGEST_2B *policyRef,
+ const char *authVal)
+{
+ PolicySecret_In in;
+ PolicySecret_Out out;
+ TPM_RC rc;
+ TPMT_SYM_DEF symmetric;
+ TPM_HANDLE authSession;
+
+ /*
+ * Simple use case: we take a bound session inside this
+ * function because we know the auth and we have an object
+ * handle. In theory the caller should pass in the session,
+ * but all current callers would flush the handle immediately
+ * after so it simplifies the API to do the session setup and
+ * teardown inside this call.
+ */
+
+ symmetric.algorithm = TPM_ALG_AES;
+ symmetric.keyBits.aes = 128;
+ symmetric.mode.aes = TPM_ALG_CFB;
+
+ /* need public area pulled in for nonce computation */
+ if ((authHandle >> 24) == TPM_HT_NV_INDEX)
+ tpm2_NV_ReadPublic(tssContext, authHandle, NULL);
+ else
+ tpm2_ReadPublic(tssContext, authHandle, NULL, TPM_RH_NULL,
NULL);
+
+ rc = tpm2_StartAuthSession(tssContext, TPM_RH_NULL, authHandle,
+ TPM_SE_HMAC, &symmetric, TPM_ALG_SHA256,
+ &authSession, authVal);
+ if (rc)
+ return rc;
+
+ in.authHandle = authHandle;
+ in.policySession = policySession;
+ in.nonceTPM.b.size = 0;
+ in.cpHashA.b.size = 0;
+
+ in.policyRef.t = *policyRef;
+ in.expiration = 0;
+
+ rc = TSS_Execute(tssContext,
+ (RESPONSE_PARAMETERS *)&out,
+ (COMMAND_PARAMETERS *)&in,
+ NULL,
+ TPM_CC_PolicySecret,
+ authSession, authVal, 0,
+ TPM_RH_NULL, NULL, 0);
+
+ if (rc) {
+ tpm2_FlushContext(tssContext, authSession);
+ tpm2_error(rc, "TPM2_PolicySecret");
+ return rc;
+ }
+
+ return rc;
+}
static inline TPM_RC
tpm2_PolicyGetDigest(TSS_CONTEXT *tssContext, TPM_HANDLE policySession,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-4.0.2/src/include/intel-tss.h
new/openssl_tpm2_engine-4.1.1/src/include/intel-tss.h
--- old/openssl_tpm2_engine-4.0.2/src/include/intel-tss.h 2023-12-05
04:47:13.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/src/include/intel-tss.h 2024-01-02
16:52:46.000000000 +0100
@@ -70,6 +70,8 @@
#define TPM_CC_PolicyAuthValue TPM2_CC_PolicyAuthValue
#define TPM_CC_PolicyCounterTimer TPM2_CC_PolicyCounterTimer
#define TPM_CC_PolicyAuthorize TPM2_CC_PolicyAuthorize
+#define TPM_CC_PolicyLocality TPM2_CC_PolicyLocality
+#define TPM_CC_PolicySecret TPM2_CC_PolicySecret
#define TPM_ST_HASHCHECK TPM2_ST_HASHCHECK
@@ -78,6 +80,8 @@
#define TPM_RH_ENDORSEMENT ESYS_TR_RH_ENDORSEMENT
#define TPM_RH_NULL ESYS_TR_NONE
+#define TPM_HT_NV_INDEX TPM2_HT_NV_INDEX
+#define TPM_HT_POLICY_SESSION TPM2_HT_POLICY_SESSION
#define TPM_HT_PERMANENT TPM2_HT_PERMANENT
#define TPM_HT_TRANSIENT TPM2_HT_TRANSIENT
#define TPM_HT_PERSISTENT TPM2_HT_PERSISTENT
@@ -178,10 +182,12 @@
}
TSS_CONVERT_MARSHAL(TPMT_PUBLIC, )
+TSS_CONVERT_MARSHAL(UINT8, *)
TSS_CONVERT_MARSHAL(UINT16, *)
TSS_CONVERT_MARSHAL(TPMT_SENSITIVE, )
TSS_CONVERT_MARSHAL(TPM2B_ECC_POINT, )
TSS_CONVERT_MARSHAL(TPM2B_DIGEST, )
+TSS_CONVERT_MARSHAL(TPM2B_NAME, )
TSS_CONVERT_MARSHAL(TPM2B_PUBLIC, )
TSS_CONVERT_MARSHAL(TPM2B_PRIVATE, )
TSS_CONVERT_MARSHAL(TPML_PCR_SELECTION, )
@@ -196,6 +202,7 @@
TSS_CONVERT_UNMARSHAL(UINT16, )
TSS_CONVERT_UNMARSHAL(UINT32, )
TSS_CONVERT_UNMARSHAL(TPM2B_DIGEST, )
+TSS_CONVERT_UNMARSHAL(TPM2B_NAME, )
TSS_CONVERT_UNMARSHAL(TPMT_SIGNATURE, X)
#define ARRAY_SIZE(A) (sizeof(A)/sizeof(A[0]))
@@ -796,27 +803,50 @@
static inline TPM_RC
tpm2_ReadPublic(TSS_CONTEXT *tssContext, TPM_HANDLE objectHandle,
- TPMT_PUBLIC *pub, TPM_HANDLE auth)
+ TPMT_PUBLIC *pub, TPM_HANDLE auth, NAME_2B *name)
{
TPM2B_PUBLIC *out;
+ NAME_2B *out_name;
TPM_RC rc;
if (auth != TPM_RH_NULL)
intel_sess_helper(tssContext, auth, TPMA_SESSION_ENCRYPT);
rc = Esys_ReadPublic(tssContext, objectHandle, auth, ESYS_TR_NONE,
- ESYS_TR_NONE, &out, NULL, NULL);
+ ESYS_TR_NONE, &out, &out_name, NULL);
if (rc)
return rc;
if (pub)
*pub = out->publicArea;
+ if (name)
+ *name = *out_name;
free(out);
return rc;
}
static inline TPM_RC
+tpm2_NV_ReadPublic(TSS_CONTEXT *tssContext, TPM_HANDLE nvIndex,
+ NAME_2B *nvName)
+{
+ TPM_RC rc;
+ NAME_2B *name;
+
+ rc = Esys_NV_ReadPublic(tssContext, nvIndex, ESYS_TR_NONE, ESYS_TR_NONE,
+ ESYS_TR_NONE, NULL, &name);
+
+ if (rc)
+ return rc;
+
+ if (nvName)
+ *nvName = *name;
+ free(name);
+
+ return rc;
+}
+
+static inline TPM_RC
tpm2_RSA_Decrypt(TSS_CONTEXT *tssContext, TPM_HANDLE keyHandle,
PUBLIC_KEY_RSA_2B *cipherText, TPMT_RSA_DECRYPT *inScheme,
PUBLIC_KEY_RSA_2B *message,
@@ -1045,6 +1075,58 @@
}
static inline TPM_RC
+tpm2_PolicyLocality(TSS_CONTEXT *tssContext, TPM_HANDLE policySession,
+ UINT8 locality)
+{
+ return Esys_PolicyLocality(tssContext, policySession,
+ ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+ locality);
+}
+
+static inline TPM_RC
+tpm2_PolicySecret(TSS_CONTEXT *tssContext, TPM_HANDLE authHandle,
+ TPM_HANDLE policySession, DIGEST_2B *policyRef,
+ const char *authVal)
+{
+ TPM_RC rc;
+ TPM_HANDLE authSession;
+ TPMT_SYM_DEF symmetric;
+
+ /*
+ * Simple use case: we take a bound session inside this
+ * function because we know the auth and we have an object
+ * handle. In theory the caller should pass in the session,
+ * but all current callers would flush the handle immediately
+ * after so it simplifies the API to do the session setup and
+ * teardown inside this call.
+ */
+
+ symmetric.algorithm = TPM_ALG_AES;
+ symmetric.keyBits.aes = 128;
+ symmetric.mode.aes = TPM_ALG_CFB;
+
+
+ rc = tpm2_StartAuthSession(tssContext, TPM_RH_NULL, authHandle,
+ TPM_SE_HMAC, &symmetric, TPM_ALG_SHA256,
+ &authSession, authVal);
+ if (rc)
+ return rc;
+
+ intel_auth_helper(tssContext, authHandle, authVal);
+ intel_sess_helper(tssContext, authSession, 0);
+
+ rc = Esys_PolicySecret(tssContext, authHandle, policySession,
+ authSession, ESYS_TR_NONE, ESYS_TR_NONE,
+ NULL /* nonceTPM */, NULL /* cpHashA */,
+ policyRef, 0, NULL, NULL);
+
+ if (rc)
+ tpm2_FlushContext(tssContext, authSession);
+
+ return rc;
+}
+
+static inline TPM_RC
tpm2_PolicyGetDigest(TSS_CONTEXT *tssContext, TPM_HANDLE policySession,
DIGEST_2B *digest)
{
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-4.0.2/src/include/tpm2-common.h
new/openssl_tpm2_engine-4.1.1/src/include/tpm2-common.h
--- old/openssl_tpm2_engine-4.0.2/src/include/tpm2-common.h 2023-12-05
04:47:13.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/src/include/tpm2-common.h 2024-01-02
16:52:46.000000000 +0100
@@ -62,7 +62,7 @@
TPM_HANDLE salt_key, TPM_SE sessionType,
TPM_ALG_ID name_alg);
TPM_RC tpm2_init_session(TSS_CONTEXT *tssContext, TPM_HANDLE handle,
- const struct app_data *app_data, TPM_ALG_ID name_alg);
+ const struct app_data *app_data, const char **auth);
TPM_RC tpm2_get_bound_handle(TSS_CONTEXT *tssContext, TPM_HANDLE *handle,
TPM_HANDLE bind, const char *auth);
TPMI_ECC_CURVE tpm2_curve_name_to_TPMI(const char *name);
@@ -104,6 +104,8 @@
STACK_OF(TSSOPTPOLICY) *sk,
TPMT_HA *digest);
void tpm2_add_auth_policy(STACK_OF(TSSOPTPOLICY) *sk, TPMT_HA *digest);
+void tpm2_add_locality(STACK_OF(TSSOPTPOLICY) *sk, UINT8 locality,
+ TPMT_HA *digest);
EVP_PKEY *openssl_read_public_key(char *filename);
void tpm2_public_template_rsa(TPMT_PUBLIC *pub);
void tpm2_public_template_ecc(TPMT_PUBLIC *pub, TPMI_ECC_CURVE curve);
@@ -115,7 +117,9 @@
TPM_RC tpm2_add_signed_policy(STACK_OF(TSSOPTPOLICY) *sk, char *key_file,
TPMT_HA *digest);
TPM_RC tpm2_new_signed_policy(char *tpmkey, char *policykey, char *engine,
- TSSAUTHPOLICY *ap, TPMT_HA *digest);
+ TSSAUTHPOLICY *ap, TPMT_HA *digest, int
need_auth);
+TPM_RC tpm2_add_policy_secret(TSS_CONTEXT *tssContext, STACK_OF(TSSOPTPOLICY)
*sk,
+ TPM_HANDLE handle, TPMT_HA *digest);
TPM_RC tpm2_outerwrap(EVP_PKEY *parent,
TPMT_SENSITIVE *s,
TPMT_PUBLIC *pub,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openssl_tpm2_engine-4.0.2/src/libcommon/tpm2-common.c
new/openssl_tpm2_engine-4.1.1/src/libcommon/tpm2-common.c
--- old/openssl_tpm2_engine-4.0.2/src/libcommon/tpm2-common.c 2023-12-05
04:47:13.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/src/libcommon/tpm2-common.c 2024-01-02
16:52:46.000000000 +0100
@@ -475,6 +475,7 @@
PUBLIC_KEY_RSA_2B message;
TPM_HANDLE authHandle;
TPM_SE sessionType;
+ const char *auth;
keyHandle = tpm2_load_key(&tssContext, ad, srk_auth, NULL);
@@ -505,15 +506,12 @@
if (rc)
goto out;
- if (sessionType == TPM_SE_POLICY) {
- rc = tpm2_init_session(tssContext, authHandle,
- ad, ad->Public.publicArea.nameAlg);
- if (rc)
- goto out;
- }
+ rc = tpm2_init_session(tssContext, authHandle, ad, &auth);
+ if (rc)
+ goto out;
rc = tpm2_RSA_Decrypt(tssContext, keyHandle, cipherText, &inScheme,
- &message, authHandle, ad->auth, protection);
+ &message, authHandle, auth, protection);
if (rc) {
tpm2_error(rc, "TPM2_RSA_Decrypt");
@@ -543,6 +541,7 @@
TPM_SE sessionType;
ECDSA_SIG *sig;
BIGNUM *r, *s;
+ const char *auth;
int len =
tpm2_curve_to_order(ad->Public.publicArea.parameters.eccDetail.curveID);
/* so we give it a digest equal to the key length, except if that
@@ -590,15 +589,12 @@
if (rc)
goto out;
- if (sessionType == TPM_SE_POLICY) {
- rc = tpm2_init_session(tssContext, authHandle,
- ad, ad->Public.publicArea.nameAlg);
- if (rc)
- goto out;
- }
+ rc = tpm2_init_session(tssContext, authHandle, ad, &auth);
+ if (rc)
+ goto out;
rc = tpm2_Sign(tssContext, keyHandle, &digest, &inScheme, &signature,
- authHandle, ad->auth);
+ authHandle, auth);
if (rc) {
tpm2_error(rc, "TPM2_Sign");
tpm2_flush_handle(tssContext, authHandle);
@@ -638,6 +634,7 @@
TPM_SE sessionType;
size_t len;
int ret;
+ const char *auth;
keyHandle = tpm2_load_key(&tssContext, ad, srk_auth, NULL);
if (keyHandle == 0) {
@@ -654,12 +651,9 @@
if (rc)
goto out;
- if (sessionType == TPM_SE_POLICY) {
- rc = tpm2_init_session(tssContext, authHandle,
- ad, ad->Public.publicArea.nameAlg);
- if (rc)
- goto out;
- }
+ rc = tpm2_init_session(tssContext, authHandle, ad, &auth);
+ if (rc)
+ goto out;
rc = tpm2_ECDH_ZGen(tssContext, keyHandle, inPoint, &outPoint,
authHandle, ad->auth);
@@ -984,7 +978,16 @@
TPM_RC tpm2_readpublic(TSS_CONTEXT *tssContext, TPM_HANDLE handle,
TPMT_PUBLIC *pub)
{
- return tpm2_ReadPublic(tssContext, handle, pub, TPM_RH_NULL);
+ return tpm2_ReadPublic(tssContext, handle, pub, TPM_RH_NULL, NULL);
+}
+
+static TPM_RC tpm2_readname(TSS_CONTEXT *tssContext, TPM_HANDLE handle,
+ NAME_2B *name)
+{
+ if (tpm2_handle_mso(tssContext, handle, TPM_HT_NV_INDEX))
+ return tpm2_NV_ReadPublic(tssContext, handle, name);
+ else
+ return tpm2_ReadPublic(tssContext, handle, NULL, TPM_RH_NULL,
name);
}
TPM_RC tpm2_get_bound_handle(TSS_CONTEXT *tssContext, TPM_HANDLE *handle,
@@ -1034,7 +1037,8 @@
static TPM_RC tpm2_try_policy(TSS_CONTEXT *tssContext, TPM_HANDLE handle,
int num_commands, struct policy_command *commands,
- TPM_ALG_ID name_alg, const char *prefix)
+ TPM_ALG_ID name_alg, const char *prefix,
+ const struct app_data *ad, const char **auth)
{
INT32 size;
BYTE *policy;
@@ -1173,6 +1177,41 @@
break;
}
+ case TPM_CC_PolicyLocality:
+ rc = tpm2_PolicyLocality(tssContext, handle, policy[0]);
+ if (rc)
+ sprintf(reason, "Locality Check 0x%x failed",
+ policy[0]);
+ break;
+
+ case TPM_CC_PolicySecret: {
+ NAME_2B name;
+ DIGEST_2B policyRef;
+ TPM_HANDLE authHandle;
+
+ rc = UINT32_Unmarshal(&authHandle, &policy, &size);
+ if (rc)
+ goto unmarshal_failure;
+ rc = TPM2B_NAME_Unmarshal((TPM2B_NAME *)&name, &policy,
&size);
+ if (rc)
+ goto unmarshal_failure;
+ rc = TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST *)&policyRef,
&policy, &size);
+ if (rc)
+ goto unmarshal_failure;
+
+ authHandle = tpm2_handle_int(tssContext, authHandle);
+ rc = tpm2_PolicySecret(tssContext, authHandle,
+ handle, &policyRef, *auth);
+
+ /*
+ * we consumed auth above, so make sure it
+ * doesn't get reused in the actual command
+ */
+ *auth = NULL;
+ tpm2_rm_keyfile(ad->dir, authHandle);
+ break;
+ }
+
default:
fprintf(stderr, "%sUnsupported policy command %d\n",
prefix, commands[i].code);
@@ -1210,12 +1249,18 @@
}
TPM_RC tpm2_init_session(TSS_CONTEXT *tssContext, TPM_HANDLE handle,
- const struct app_data *app_data, TPM_ALG_ID name_alg)
+ const struct app_data *app_data, const char **auth)
{
int num_commands;
struct policy_command *commands;
char prefix[128];
TPM_RC rc;
+ TPM_ALG_ID name_alg = app_data->Public.publicArea.nameAlg;
+
+ *auth = app_data->auth;
+
+ if (!tpm2_handle_mso(tssContext, handle, TPM_HT_POLICY_SESSION))
+ return TPM_RC_SUCCESS;
if (app_data->pols == NULL)
return TPM_RC_SUCCESS;
@@ -1244,7 +1289,8 @@
rc = tpm2_try_policy(tssContext, handle,
pols->num_commands,
pols->commands,
- name_alg, prefix);
+ name_alg, prefix,
+ app_data, auth);
if (rc == TPM_RC_SUCCESS)
break;
}
@@ -1255,7 +1301,7 @@
}
rc = tpm2_try_policy(tssContext, handle, num_commands, commands,
- name_alg, "");
+ name_alg, "", app_data, auth);
out:
if (rc != TPM_RC_SUCCESS)
tpm2_flush_handle(tssContext, handle);
@@ -1436,6 +1482,10 @@
unlink(keyfile);
snprintf(keyfile, sizeof(keyfile), "%s/hp%08x.bin", dir, key);
unlink(keyfile);
+ if ((key >> 24) == TPM_HT_NV_INDEX) {
+ snprintf(keyfile, sizeof(keyfile), "%s/nvp%08x.bin", dir, key);
+ unlink(keyfile);
+ }
}
void tpm2_rm_tssdir(const char *dir)
@@ -2433,7 +2483,7 @@
}
TPM_RC tpm2_new_signed_policy(char *tpmkey, char *policykey, char *engine,
- TSSAUTHPOLICY *ap, TPMT_HA *digest)
+ TSSAUTHPOLICY *ap, TPMT_HA *digest, int need_auth)
{
BIO *bf;
TSSPRIVKEY *tpk;
@@ -2460,6 +2510,10 @@
goto err_free_tpmkey;
}
+ /* remove the emptyAuth attribut if set and we need authorization */
+ if (tpk->emptyAuth != -1 && need_auth)
+ tpk->emptyAuth = -1;
+
policy = sk_TSSOPTPOLICY_value(tpk->policy, 0);
if (ASN1_INTEGER_get(policy->CommandCode) != TPM_CC_PolicyAuthorize) {
fprintf(stderr, "TPM Key has no signed policy\n");
@@ -2598,13 +2652,13 @@
if (sep)
*sep = '\0';
- from = to = strtol(str, &endptr, 10);
+ from = to = strtoul(str, &endptr, 10);
if (*endptr != '\0' || from < 0 || from >= MAX_TPM_PCRS)
goto err;
if (sep) {
str = sep + 1;
- to = strtol(str, &endptr, 10);
+ to = strtoul(str, &endptr, 10);
if (*endptr != '\0' || to < 0 || to >= MAX_TPM_PCRS)
goto err;
@@ -2760,6 +2814,30 @@
written, buf, 0, NULL);
}
+void tpm2_add_locality(STACK_OF(TSSOPTPOLICY) *sk, UINT8 locality,
+ TPMT_HA *digest)
+{
+ TSSOPTPOLICY *policy = TSSOPTPOLICY_new();
+ BYTE buf[5];
+ BYTE *buffer = buf;
+ UINT16 written = 0;
+ INT32 size = sizeof(buf);
+ const TPM_CC cc = TPM_CC_PolicyLocality;
+
+ TSS_TPM_CC_Marshal(&cc, &written, &buffer, &size);
+ TSS_UINT8_Marshal(&locality, &written, &buffer, &size);
+
+ ASN1_INTEGER_set(policy->CommandCode, cc);
+ ASN1_STRING_set(policy->CommandPolicy, buf + 4, written - 4);
+
+ sk_TSSOPTPOLICY_push(sk, policy);
+
+ TSS_Hash_Generate(digest,
+ TSS_GetDigestSize(digest->hashAlg),
+ (uint8_t *)&digest->digest,
+ written, buf, 0, NULL);
+}
+
TPM_RC tpm2_add_signed_policy(STACK_OF(TSSOPTPOLICY) *sk, char *key_file,
TPMT_HA *digest)
{
@@ -2825,6 +2903,50 @@
return TPM_RC_SUCCESS;
}
+
+TPM_RC
+tpm2_add_policy_secret(TSS_CONTEXT *tssContext, STACK_OF(TSSOPTPOLICY) *sk,
+ TPM_HANDLE handle, TPMT_HA *digest)
+{
+ TSSOPTPOLICY *policy;
+ BYTE buf[1024];
+ BYTE *buffer = buf;
+ UINT16 written = 0;
+ INT32 size = sizeof(buf);
+ const TPM_CC cc = TPM_CC_PolicySecret;
+ NAME_2B name;
+ DIGEST_2B policyRef = {0};
+ TPM_RC rc;
+ TPM_HANDLE intHandle = tpm2_handle_int(tssContext, handle);
+
+ rc = tpm2_readname(tssContext, intHandle, &name);
+ if (rc)
+ return rc;
+ policy = TSSOPTPOLICY_new();
+ TSS_TPM_CC_Marshal(&cc, &written, &buffer, &size);
+ TSS_UINT32_Marshal(&handle, &written, &buffer, &size);
+ TSS_TPM2B_NAME_Marshal((TPM2B_NAME *)&name, &written, &buffer, &size);
+ TSS_TPM2B_DIGEST_Marshal((TPM2B_DIGEST *)&policyRef, &written, &buffer,
&size);
+
+ ASN1_INTEGER_set(policy->CommandCode, cc);
+ ASN1_STRING_set(policy->CommandPolicy, buf + 4, written - 4);
+ sk_TSSOPTPOLICY_push(sk, policy);
+
+ TSS_Hash_Generate(digest,
+ TSS_GetDigestSize(digest->hashAlg),
+ (uint8_t *)&digest->digest,
+ 4, buf, /* CC */
+ name.size, name.name, /* name */
+ 0, NULL);
+ TSS_Hash_Generate(digest,
+ TSS_GetDigestSize(digest->hashAlg),
+ (uint8_t *)&digest->digest, /* intermediate digest */
+ policyRef.size, policyRef.buffer,
+ 0, NULL);
+
+
+ return TPM_RC_SUCCESS;
+}
EVP_PKEY *
openssl_read_public_key(char *filename)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-4.0.2/src/provider/store.c
new/openssl_tpm2_engine-4.1.1/src/provider/store.c
--- old/openssl_tpm2_engine-4.0.2/src/provider/store.c 2023-12-05
04:47:13.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/src/provider/store.c 2024-01-02
16:52:46.000000000 +0100
@@ -85,7 +85,8 @@
rc = tpm2_get_bound_handle(tssContext, &session, key,
NULL);
if (rc == TPM_RC_SUCCESS) {
- rc = tpm2_ReadPublic(tssContext, key, NULL,
session);
+ rc = tpm2_ReadPublic(tssContext, key, NULL,
+ session, NULL);
if (rc)
tpm2_flush_handle(tssContext, session);
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openssl_tpm2_engine-4.0.2/src/tools/create_tpm2_key.1.in
new/openssl_tpm2_engine-4.1.1/src/tools/create_tpm2_key.1.in
--- old/openssl_tpm2_engine-4.0.2/src/tools/create_tpm2_key.1.in
2023-12-05 04:47:13.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/src/tools/create_tpm2_key.1.in
2024-01-02 16:52:46.000000000 +0100
@@ -64,6 +64,18 @@
wrapped, like the template (must be standard restricted decryption
key) and the name hash (must be sha256).
+[Secrets in Other Objects]
+
+When the option --secrets <handle> is used, it creates a key whose
+authorization password is conditioned on the password of a different
+object identified by <handle>. Usually this is a permanent NV index,
+but could be any object. The design of this policy is to allow the
+password to be changed without updating the key (simply by changing
+the authorization of the other object). Because OpenSSL can only
+request a single password, keys with a --secret policy may not
+additionally have an --auth option to also require passing in the
+password embedded in the key.
+
[Signed Policies]
When the option --signed-policy <key> is used, it creates a key whose
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openssl_tpm2_engine-4.0.2/src/tools/create_tpm2_key.c
new/openssl_tpm2_engine-4.1.1/src/tools/create_tpm2_key.c
--- old/openssl_tpm2_engine-4.0.2/src/tools/create_tpm2_key.c 2023-12-05
04:47:13.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/src/tools/create_tpm2_key.c 2024-01-02
16:52:46.000000000 +0100
@@ -29,6 +29,8 @@
#define OPT_DEPRECATED 0x1ff
#define OPT_RESTRICTED 0x1fe
#define OPT_SIGNED_POLICY 0x1fd
+#define OPT_LOCALITY 0x1fc
+#define OPT_SECRET 0x1fb
static struct option long_options[] = {
{"auth", 0, 0, 'a'},
@@ -39,6 +41,7 @@
{"parent-handle", 1, 0, 'p'},
{"pcr-lock", 1, 0, 'x'},
{"signed-policy", 1, 0, OPT_SIGNED_POLICY },
+ {"locality", 1, 0, OPT_LOCALITY },
{"wrap", 1, 0, 'w'},
{"version", 0, 0, 'v'},
{"password", 1, 0, 'k'},
@@ -49,6 +52,7 @@
{"key-policy", 1, 0, 'c'},
{"import", 1, 0, 'i'},
{"restricted", 0, 0, OPT_RESTRICTED },
+ {"secret", 1, 0, OPT_SECRET },
/*
* The option --deprecated allows us to create old format keys
* for the purposes of testing. It should never be used in
@@ -98,9 +102,14 @@
"\t-x, --pcr-lock <pcrs> Lock the created key to the
specified PCRs\n"
" By current value. See PCR
VALUES for\n"
" details about formatting\n"
+ "\t--locality <loc> Can only be used in a set of
localities\n"
+ " described by the <loc>
bitmap\n"
"\t--signed-policy <key> Add a signed policy directive
that allows\n"
"\t policies signed by the
specified public <key>\n"
"\t to authorize use of the key\n"
+ "\t--secret <handle> Tie authorization of the key
to the\n"
+ "\t Authorization of a different
object\n"
+ "\t Identified by <handle>.\n"
"\n"
"Report bugs to " PACKAGE_BUGREPORT "\n",
argv0);
@@ -448,7 +457,7 @@
int option_index, c;
const char *reason;
TSS_CONTEXT *tssContext = NULL;
- TPM_HANDLE parent = TPM_RH_OWNER, phandle;
+ TPM_HANDLE parent = TPM_RH_OWNER, phandle, secret_handle = 0;
TPM_RC rc;
BYTE pubkey[sizeof(TPM2B_PUBLIC)],privkey[sizeof(TPM2B_PRIVATE)],
*buffer;
uint16_t pubkey_len, privkey_len;
@@ -478,7 +487,8 @@
int restricted = 0;
char *parent_str = NULL;
TPML_PCR_SELECTION pcr_lock = { 0 };
- int has_policy = 0;
+ int has_policy = 0, has_locality = 0;
+ UINT8 locality = 0;
OpenSSL_add_all_digests();
/* may be needed to decrypt the key */
@@ -573,6 +583,14 @@
case OPT_SIGNED_POLICY:
signed_policy = optarg;
break;
+ case OPT_LOCALITY:
+ has_locality = 1;
+ locality = strtoul(optarg, NULL, 0);
+ break;
+ case OPT_SECRET:
+ secret_handle = strtoul(optarg, NULL, 0);
+ has_policy = 1;
+ break;
default:
printf("Unknown option '%c'\n", c);
usage(argv[0]);
@@ -627,7 +645,13 @@
exit(1);
}
- if (pcr_lock.count != 0 || policyFilename || signed_policy)
+ if (has_locality && locality == 0) {
+ fprintf(stderr, "zero is an illegal locality bitmap\n");
+ exit(1);
+ }
+
+ if (pcr_lock.count != 0 || policyFilename || signed_policy ||
+ has_locality)
has_policy = 1;
digest.hashAlg = name_alg;
@@ -671,6 +695,9 @@
tpm2_add_auth_policy(sk, &digest);
}
+ if (has_locality)
+ tpm2_add_locality(sk, locality, &digest);
+
if (import) {
EVP_PKEY *p_pkey = openssl_read_public_key(import);
EVP_PKEY *pkey = openssl_read_key(wrap);
@@ -762,6 +789,9 @@
}
}
+ if (secret_handle)
+ tpm2_add_policy_secret(tssContext, sk, secret_handle, &digest);
+
if (parent_str) {
parent = tpm2_get_parent(tssContext, parent_str);
if (parent == 0) {
@@ -947,7 +977,8 @@
size = sizeof(privkey);
TSS_TPM2B_PRIVATE_Marshal((TPM2B_PRIVATE *)priv, &privkey_len, &buffer,
&size);
tpm2_write_tpmfile(filename, pubkey, pubkey_len,
- privkey, privkey_len, auth == NULL, parent, sk,
+ privkey, privkey_len,
+ auth == NULL && secret_handle == 0, parent, sk,
version, enc_secret);
tpm2_free_policy(sk);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openssl_tpm2_engine-4.0.2/src/tools/seal_tpm2_data.1.in
new/openssl_tpm2_engine-4.1.1/src/tools/seal_tpm2_data.1.in
--- old/openssl_tpm2_engine-4.0.2/src/tools/seal_tpm2_data.1.in 2023-12-05
04:47:13.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/src/tools/seal_tpm2_data.1.in 2024-01-02
16:52:46.000000000 +0100
@@ -40,6 +40,18 @@
wrapped, like the template (must be standard restricted decryption
key) and the name hash (must be sha256).
+[Secrets in Other Objects]
+
+When the option --secrets <handle> is used, it creates a sealed blob
+whose authorization password is conditioned on the password of a
+different object identified by <handle>. Usually this is a permanent
+NV index, but could be any object. The design of this policy is to
+allow the password to be changed without updating the sealed blob
+(simply by changing the authorization of the other object). Because
+most unseal applications can only request a single password, blobs
+with a --secret policy may not additionally have an --auth option to
+also require passing in the password embedded in the blob.
+
[Signed Policies]
When the option --signed-policy <key> is used, it creates a sealed
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-4.0.2/src/tools/seal_tpm2_data.c
new/openssl_tpm2_engine-4.1.1/src/tools/seal_tpm2_data.c
--- old/openssl_tpm2_engine-4.0.2/src/tools/seal_tpm2_data.c 2023-12-05
04:47:13.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/src/tools/seal_tpm2_data.c 2024-01-02
16:52:46.000000000 +0100
@@ -22,6 +22,8 @@
#include "tpm2-common.h"
#define OPT_SIGNED_POLICY 0x1fd
+#define OPT_LOCALITY 0x1fc
+#define OPT_SECRET 0x1fb
static struct option long_options[] = {
{"auth", 0, 0, 'a'},
@@ -29,7 +31,9 @@
{"help", 0, 0, 'h'},
{"parent-handle", 1, 0, 'p'},
{"pcr-lock", 1, 0, 'x'},
+ {"locality", 1, 0, OPT_LOCALITY },
{"signed-policy", 1, 0, OPT_SIGNED_POLICY },
+ {"secret", 1, 0, OPT_SECRET },
{"version", 0, 0, 'v'},
{"password", 1, 0, 'k'},
{"da", 0, 0, 'd'},
@@ -78,9 +82,14 @@
"\t-x, --pcr-lock <pcrs> Lock the created key to the
specified PCRs\n"
" By current value. See PCR
VALUES for\n"
" details about formatting\n"
+ "\t--locality <loc> Can only be unsealed in a set
of localities\n"
+ " described by the <loc>
bitmap\n"
"\t--signed-policy <key> Add a signed policy directive
that allows\n"
"\t policies signed by the
specified public <key>\n"
"\t to authorize unsealing\n"
+ "\t--secret <handle> Tie authorization of the key
to the\n"
+ "\t Authorization of a different
object\n"
+ "\t Identified by <handle>.\n"
"\t-i, --import <pubkey> Create an importable key with
the outer\n"
" wrapper encrypted to
<pubkey>\n"
"\t-c, --policy Specify a policy for unsealing
the data\n"
@@ -123,7 +132,7 @@
const char *reason = ""; /* gcc 4.8.5 gives spurious uninitialized
warning without this */
TPMT_HA digest;
uint32_t sizeInBytes;
- TPM_HANDLE authHandle;
+ TPM_HANDLE authHandle, secret_handle = 0;
STACK_OF(TSSOPTPOLICY) *sk = NULL;
TPM2B_SENSITIVE_CREATE inSensitive;
TPM2B_PUBLIC inPublic;
@@ -143,6 +152,7 @@
int has_policy = 0;
char *signed_policy = NULL;
ENCRYPTED_SECRET_2B secret, *enc_secret = NULL;
+ int has_locality = 0, locality = 0;
pcr_lock.count = 0;
@@ -213,6 +223,14 @@
case OPT_SIGNED_POLICY:
signed_policy = optarg;
break;
+ case OPT_LOCALITY:
+ has_locality = 1;
+ locality = strtoul(optarg, NULL, 0);
+ break;
+ case OPT_SECRET:
+ has_policy = 1;
+ secret_handle = strtoul(optarg, NULL, 0);
+ break;
default:
printf("Unknown option '%c'\n", c);
usage(argv[0]);
@@ -241,7 +259,13 @@
exit(1);
}
- if (pcr_lock.count != 0 || policyFilename || signed_policy)
+ if (has_locality && locality == 0) {
+ fprintf(stderr, "zero is an illegal locality bitmap\n");
+ exit(1);
+ }
+
+ if (pcr_lock.count != 0 || policyFilename || signed_policy ||
+ has_locality)
has_policy = 1;
digest.hashAlg = name_alg;
@@ -322,6 +346,12 @@
}
}
+ if (has_locality)
+ tpm2_add_locality(sk, locality, &digest);
+
+ if (secret_handle)
+ tpm2_add_policy_secret(tssContext, sk, secret_handle, &digest);
+
tpm2_public_template_seal(p);
if (has_policy) {
@@ -427,7 +457,8 @@
TSS_TPM2B_PRIVATE_Marshal((TPM2B_PRIVATE *)&outPrivate, &privkey_len,
&buffer, &size);
tpm2_write_tpmfile(filename, pubkey, pubkey_len,
- privkey, privkey_len, data_auth == NULL,
+ privkey, privkey_len,
+ data_auth == NULL && secret_handle == 0,
parent, sk, 2, enc_secret);
out_flush:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openssl_tpm2_engine-4.0.2/src/tools/signed_tpm2_policy.1.in
new/openssl_tpm2_engine-4.1.1/src/tools/signed_tpm2_policy.1.in
--- old/openssl_tpm2_engine-4.0.2/src/tools/signed_tpm2_policy.1.in
2023-12-05 04:47:13.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/src/tools/signed_tpm2_policy.1.in
2024-01-02 16:52:46.000000000 +0100
@@ -22,6 +22,18 @@
sha512:1,3-5 means PCRs 1,3,4 and 5 in the sha512 bank
+[Secrets in Other Objects]
+
+When the option --secrets <handle> is used, it creates a key whose
+authorization password is conditioned on the password of a different
+object identified by <handle>. Usually this is a permanent NV index,
+but could be any object. The design of this policy is to allow the
+password to be changed without updating the key (simply by changing
+the authorization of the other object). Because OpenSSL can only
+request a single password, keys with a --secret policy may not
+additionally have an --auth option to also require passing in the
+password embedded in the key.
+
[examples]
list all signed policies:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openssl_tpm2_engine-4.0.2/src/tools/signed_tpm2_policy.c
new/openssl_tpm2_engine-4.1.1/src/tools/signed_tpm2_policy.c
--- old/openssl_tpm2_engine-4.0.2/src/tools/signed_tpm2_policy.c
2023-12-05 04:47:13.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/src/tools/signed_tpm2_policy.c
2024-01-02 16:52:46.000000000 +0100
@@ -27,12 +27,16 @@
#include "tpm2-common.h"
#define OPT_SIGNED_POLICY 0x1fd
+#define OPT_LOCALITY 0x1fc
+#define OPT_SECRET 0x1fb
static struct option long_options[] = {
{"auth", 0, 0, 'a'},
{"help", 0, 0, 'h'},
{"pcr-lock", 1, 0, 'x'},
+ {"locality", 1, 0, OPT_LOCALITY },
{"signed-policy", 1, 0, OPT_SIGNED_POLICY },
+ {"secret", 1, 0, OPT_SECRET},
{"version", 0, 0, 'v'},
{"key-policy", 1, 0, 'c'},
{"engine", 1, 0, 'e'},
@@ -53,10 +57,14 @@
"\t-x, --pcr-lock <pcrs> Lock the created key to the
specified PCRs\n"
" By current value. See PCR
VALUES for\n"
" details about formatting\n"
- "\n"
+ "\t--locality <loc> Can only be used in a set of
localities\n"
+ " described by the <loc>
bitmap\n"
"\t--signed-policy <key> Add a signed policy directive
that allows\n"
"\t policies signed by the
specified public <key>\n"
"\t to authorize use of the key\n"
+ "\t--secret <handle> Tie authorization of the key
to the\n"
+ "\t Authorization of a different
object\n"
+ "\t Identified by <handle>.\n"
"\t-n, --policy-name <name> Optional name to annotate the
policy with\n"
"\n"
"Report bugs to " PACKAGE_BUGREPORT "\n",
@@ -110,6 +118,9 @@
TPMT_HA digest;
int size;
TPML_PCR_SELECTION pcr_lock = { 0 };
+ int has_locality = 0;
+ int locality = 0;
+ int secret_handle = 0;
STACK_OF(TSSAUTHPOLICY) *sk;
enum cmd {
CMD_ADD = 0,
@@ -177,6 +188,13 @@
case OPT_SIGNED_POLICY:
signed_policy = optarg;
break;
+ case OPT_LOCALITY:
+ has_locality = 1;
+ locality = strtoul(optarg, NULL, 0);
+ break;
+ case OPT_SECRET:
+ secret_handle = strtoul(optarg, NULL, 0);
+ break;
default:
printf("Unknown option '%c'\n", c);
usage(argv0);
@@ -190,6 +208,11 @@
usage(argv0);
}
+ if (has_locality && locality == 0) {
+ fprintf(stderr, "zero is an illegal locality bitmap\n");
+ exit(1);
+ }
+
switch(cmd) {
case CMD_ADD:
filename = argv[argc - 2];
@@ -254,8 +277,34 @@
}
}
+ if (has_locality)
+ tpm2_add_locality(ap->policy, locality, &digest);
+
+ if (secret_handle) {
+ TSS_CONTEXT *tssContext = NULL;
+ const char *dir;
+
+ dir = tpm2_set_unique_tssdir();
+ rc = tpm2_create(&tssContext, dir);
+ if (rc) {
+ reason = "TSS_Create";
+ goto out_free_policy;
+ }
+
+ rc = tpm2_add_policy_secret(tssContext, ap->policy,
+ secret_handle, &digest);
+ TSS_Delete(tssContext);
+ tpm2_rm_tssdir(dir);
+ if (rc) {
+ reason = "create object authorization policy";
+ goto out_free_policy;
+ }
+ }
+
+
rc = tpm2_new_signed_policy(filename, policy_signing_key,
- engine, ap, &digest);
+ engine, ap, &digest,
+ auth || secret_handle);
if (rc == 0)
exit(0);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openssl_tpm2_engine-4.0.2/src/tools/unseal_tpm2_data.c
new/openssl_tpm2_engine-4.1.1/src/tools/unseal_tpm2_data.c
--- old/openssl_tpm2_engine-4.0.2/src/tools/unseal_tpm2_data.c 2023-12-05
04:47:13.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/src/tools/unseal_tpm2_data.c 2024-01-02
16:52:46.000000000 +0100
@@ -73,6 +73,7 @@
uint32_t parent, session;
UI_METHOD *ui = UI_create_method("unseal");
struct app_data *app_data;
+ const char *auth;
while (1) {
option_index = 0;
@@ -156,17 +157,13 @@
goto out_flush_data;
}
- if (app_data->req_policy_session) {
- rc = tpm2_init_session(tssContext, session,
- app_data, name_alg);
- if (rc) {
- reason = "tpm2_init_session";
- goto out_flush_session;
- }
+ rc = tpm2_init_session(tssContext, session, app_data, &auth);
+ if (rc) {
+ reason = "tpm2_init_session";
+ goto out_flush_session;
}
- rc = tpm2_Unseal(tssContext, itemHandle, &outData, session,
- app_data->auth);
+ rc = tpm2_Unseal(tssContext, itemHandle, &outData, session, auth);
if (rc) {
reason = "TPM2_Unseal";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-4.0.2/tests/check_locality.sh
new/openssl_tpm2_engine-4.1.1/tests/check_locality.sh
--- old/openssl_tpm2_engine-4.0.2/tests/check_locality.sh 1970-01-01
01:00:00.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/tests/check_locality.sh 2024-01-02
16:52:46.000000000 +0100
@@ -0,0 +1,23 @@
+#!/bin/bash
+set -x
+##
+# The TPM emulators always run in locality 0, so the only tests
+# we can do is create a key including and excluding locality zero
+# and check that one loads and the other doesn't
+##
+LOCALITY_01234=0x1f
+LOCALITY_1234=0x1e
+echo "This is a message" > plain.txt
+DATA="Test some data"
+
+${bindir}/create_tpm2_key --ecc prime256v1 --locality ${LOCALITY_01234}
key.tpm || exit 1
+openssl pkeyutl -sign $ENGINE $KEYFORM -inkey key.tpm -in plain.txt -out
tmp.msg|| exit 1
+echo "${DATA}"|${bindir}/seal_tpm2_data --locality ${LOCALITY_01234} key.tpm
+${bindir}/unseal_tpm2_data key.tpm|grep -q "${DATA}" || exit 1
+
+${bindir}/create_tpm2_key --ecc prime256v1 --locality ${LOCALITY_1234} key.tpm
|| exit 1
+openssl pkeyutl -sign $ENGINE $KEYFORM -inkey key.tpm -in plain.txt -out
tmp.msg&& exit 1
+echo "${DATA}"|${bindir}/seal_tpm2_data --locality ${LOCALITY_1234} key.tpm
+${bindir}/unseal_tpm2_data key.tpm && exit 1
+
+exit 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openssl_tpm2_engine-4.0.2/tests/check_secret_policies.sh
new/openssl_tpm2_engine-4.1.1/tests/check_secret_policies.sh
--- old/openssl_tpm2_engine-4.0.2/tests/check_secret_policies.sh
1970-01-01 01:00:00.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/tests/check_secret_policies.sh
2024-01-02 16:52:46.000000000 +0100
@@ -0,0 +1,49 @@
+#!/bin/bash
+set -x
+
+##
+# First create a NV object and a permanent key with a known authorization
+##
+PASSWORD="RNDPWD${RANDOM}"
+NVINDEX=0x01000002
+NVKEY=0x81005555
+DATA="Some Random Data ${RANDOM}"
+tssnvdefinespace -hi o -ha ${NVINDEX} -pwdn ${PASSWORD} || exit 1
+# note index is not initialized (but shouldn't need to be)
+key=$(tsscreateprimary -hi o -st -ecc nistp256 -pwdk ${PASSWORD}|sed 's/Handle
//') && \
+tssevictcontrol -hi o -ho ${key} -hp ${NVKEY} && \
+tssflushcontext -ha ${key}
+# create a policy key
+openssl genpkey -out policy.key -algorithm EC -pkeyopt
ec_paramgen_curve:prime256v1 || exit 1
+openssl pkey -in policy.key -pubout -out policy.pub
+
+##
+# Tests for each index, create an ordinary key a sealed object and a
+# signed policy key each with --secret and then verify they fail with
+# no password and accept the object password
+##
+for index in ${NVINDEX} ${NVKEY}; do
+
+ ${bindir}/create_tpm2_key --secret ${index} key.tpm || exit 1
+ echo ${DATA}|${bindir}/seal_tpm2_data --secret ${index} seal.tpm || exit 1
+ echo ${DATA} > plain.txt
+ openssl pkey $ENGINE $INFORM -in key.tpm -passin pass:" " -pubout -out
key.pub || exit 1
+ ${bindir}/create_tpm2_key --signed-policy policy.pub skey.tpm
+ ${bindir}/signed_tpm2_policy add --policy-name "secret" --secret ${index}
skey.tpm policy.key || exit 1
+ openssl pkey $ENGINE $INFORM -in skey.tpm -passin pass:" " -pubout -out
skey.pub || exit 1
+
+ # Verify use without password fails
+
+ openssl pkeyutl -sign -passin pass:" " -in plain.txt $ENGINE $KEYFORM
-inkey key.tpm -out tmp.msg && exit 1
+ ${bindir}/unseal_tpm2_data seal.tpm -k " " && exit 1
+ openssl pkeyutl -sign -passin pass:" " -in plain.txt $ENGINE $KEYFORM
-inkey skey.tpm -out tmp.msg && exit 1
+
+ # verify use with object password works
+ openssl pkeyutl -sign -passin pass:${PASSWORD} -in plain.txt $ENGINE
$KEYFORM -inkey key.tpm -out tmp.msg && \
+ openssl pkeyutl -verify -in plain.txt -sigfile tmp.msg -inkey key.pub
-pubin || exit 1
+ ${bindir}/unseal_tpm2_data seal.tpm -k ${PASSWORD}| grep -q "${DATA}" ||
exit 1
+ openssl pkeyutl -sign -passin pass:${PASSWORD} -in plain.txt $ENGINE
$KEYFORM -inkey skey.tpm -out tmp.msg && \
+ openssl pkeyutl -verify -in plain.txt -sigfile tmp.msg -inkey skey.pub
-pubin || exit 1
+done
+
+exit 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-4.0.2/tests/engine/Makefile.am
new/openssl_tpm2_engine-4.1.1/tests/engine/Makefile.am
--- old/openssl_tpm2_engine-4.0.2/tests/engine/Makefile.am 2023-12-05
04:47:13.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/tests/engine/Makefile.am 2024-01-02
16:52:46.000000000 +0100
@@ -27,6 +27,8 @@
../restricted_parent.sh \
../seal_unseal.sh \
../check_signed_policies.sh \
+ ../check_locality.sh \
+ ../check_secret_policies.sh \
../dynamic_engine.sh \
../stop_sw_tpm.sh
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-4.0.2/tests/provider/Makefile.am
new/openssl_tpm2_engine-4.1.1/tests/provider/Makefile.am
--- old/openssl_tpm2_engine-4.0.2/tests/provider/Makefile.am 2023-12-05
04:47:13.000000000 +0100
+++ new/openssl_tpm2_engine-4.1.1/tests/provider/Makefile.am 2024-01-02
16:52:46.000000000 +0100
@@ -29,6 +29,8 @@
../restricted_parent.sh \
../seal_unseal.sh \
../check_signed_policies.sh \
+ ../check_locality.sh \
+ ../check_secret_policies.sh \
../stop_sw_tpm.sh
fail_connect.sh: tpm_server_found