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 2022-02-19 00:07:22
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openssl_tpm2_engine (Old)
 and      /work/SRC/openSUSE:Factory/.openssl_tpm2_engine.new.1958 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "openssl_tpm2_engine"

Sat Feb 19 00:07:22 2022 rev:6 rq: version:3.1.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/openssl_tpm2_engine/openssl_tpm2_engine.changes  
2022-02-18 22:54:35.385455729 +0100
+++ 
/work/SRC/openSUSE:Factory/.openssl_tpm2_engine.new.1958/openssl_tpm2_engine.changes
        2022-02-19 00:07:29.181017502 +0100
@@ -1,0 +2,8 @@
+Thu Feb 17 14:09:11 UTC 2022 - james.bottom...@hansenpartnership.com
+
+- Update to version 3.1.0
+  * Bandaid openssl-3 support
+  * direct pcr policy creation options
+  * TPM key RFC
+
+-------------------------------------------------------------------

Old:
----
  openssl_tpm2_engine-3.0.1.tar.gz

New:
----
  openssl_tpm2_engine-3.1.0.tar.gz

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

Other differences:
------------------
++++++ openssl_tpm2_engine.spec ++++++
--- /var/tmp/diff_new_pack.lGBlID/_old  2022-02-19 00:07:29.789017427 +0100
+++ /var/tmp/diff_new_pack.lGBlID/_new  2022-02-19 00:07:29.793017427 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package openssl_tpm2_engine
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 # Copyright (c) 2017 james.bottom...@hansenpartnership.com
 #
 # All modifications and additions to the file contributed by third parties
@@ -18,7 +18,7 @@
 
 
 Name:           openssl_tpm2_engine
-Version:        3.0.1
+Version:        3.1.0
 Release:        0
 Summary:        OpenSSL TPM 2.0 interface engine plugin
 License:        LGPL-2.1-only

++++++ openssl_tpm2_engine-3.0.1.tar.gz -> openssl_tpm2_engine-3.1.0.tar.gz 
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/Makefile.am 
new/openssl_tpm2_engine-3.1.0/Makefile.am
--- old/openssl_tpm2_engine-3.0.1/Makefile.am   2021-04-04 22:47:14.000000000 
+0200
+++ new/openssl_tpm2_engine-3.1.0/Makefile.am   2022-02-17 00:15:34.000000000 
+0100
@@ -9,6 +9,10 @@
 CLEANFILES = $(man1_MANS)
 endif
 
+if HAVE_OPENSSL3
+CFLAGS+= -DOPENSSL_API_COMPAT=0x10100000L
+endif
+
 openssl_engine_LTLIBRARIES=libtpm2.la
 bin_PROGRAMS=create_tpm2_key load_tpm2_key seal_tpm2_data unseal_tpm2_data
 openssl_enginedir=@enginesdir@
@@ -41,4 +45,4 @@
 install-data-hook:
        cd $(DESTDIR)$(openssl_enginedir) && $(LN_S) -f libtpm2@SHREXT@ 
tpm2@SHREXT@
 
-SUBDIRS = tests
+SUBDIRS = tests doc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/configure.ac 
new/openssl_tpm2_engine-3.1.0/configure.ac
--- old/openssl_tpm2_engine-3.0.1/configure.ac  2021-04-04 22:47:14.000000000 
+0200
+++ new/openssl_tpm2_engine-3.1.0/configure.ac  2022-02-17 00:15:34.000000000 
+0100
@@ -2,7 +2,7 @@
 # configure.in for the OpenSSL TPM engine project
 #
 
-AC_INIT(openssl-tpm2-engine, 3.0.1, <openssl-tpm2-eng...@groups.io>)
+AC_INIT(openssl-tpm2-engine, 3.1.0, <openssl-tpm2-eng...@groups.io>)
 AM_INIT_AUTOMAKE([foreign 1.6.3])
 AC_CANONICAL_HOST
 AM_CONDITIONAL(NATIVE_BUILD, test "x$cross_compiling" = "xno")
@@ -50,6 +50,11 @@
         AC_SUBST(OPENSSL_INCLUDE_DIR)])
 
 AC_LANG(C)
+
+PKG_CHECK_MODULES([DEPS], [libcrypto >= 3.0.0],
+                  [ac_have_openssl3=1],
+                 [PKG_CHECK_MODULES([DEPS], [libcrypto])])
+
 AC_ARG_WITH(
        [enginesdir],
        [AC_HELP_STRING([--with-enginesdir], [OpenSSL engines directory])],
@@ -95,6 +100,8 @@
 ])
 AM_CONDITIONAL(HAVE_IBM_TSS, test "$tsslibs" = "IBM")
 
+AM_CONDITIONAL(HAVE_OPENSSL3, test "$ac_have_openssl3" = "1")
+
 AC_DISABLE_STATIC
 AC_PROG_CC_STDC
 AM_PROG_CC_C_O
@@ -128,6 +135,8 @@
 AC_PATH_PROG(TPMSERVER, 
tpm_server,,/bin:/usr/bin:/usr/lib/ibmtss:/usr/libexec/ibmtss)
 AC_PATH_PROG(SWTPM, swtpm,,/bin:/usr/bin:/usr/lib/ibmtss:/usr/libexec/ibmtss)
 AC_PATH_PROG(SWTPM_IOCTL, 
swtpm_ioctl,,/bin:/usr/bin:/usr/lib/ibmtss:/usr/libexec/ibmtss)
+AC_CHECK_PROG(XML2RFC, xml2rfc, xml2rfc)
+AM_CONDITIONAL(HAVE_XML2RFC, test -n "${XML2RFC}")
 CFLAGS="$CFLAGS -Wall"
 SHREXT=$shrext_cmds
 AC_SUBST(CFLAGS)
@@ -147,7 +156,7 @@
 
 AC_SUBST(testtpm)
 
-AC_OUTPUT([Makefile tests/Makefile])
+AC_OUTPUT([Makefile tests/Makefile doc/Makefile])
 
 cat <<EOF
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/create_tpm2_key.1.in 
new/openssl_tpm2_engine-3.1.0/create_tpm2_key.1.in
--- old/openssl_tpm2_engine-3.0.1/create_tpm2_key.1.in  2021-04-04 
22:47:14.000000000 +0200
+++ new/openssl_tpm2_engine-3.1.0/create_tpm2_key.1.in  2022-02-17 
00:15:34.000000000 +0100
@@ -31,6 +31,20 @@
 
 $ echo 0000016b >> policy.txt
 
+[PCR Values]
+
+The PCR values are specified as
+
+ <bank>:<list>
+
+Where <bank> is any supported PCR hash bank and list specifies the
+PCRs to lock the key to as both comma separated individual values as
+well as comma separated ranges.  So
+
+ sha256:1,3 means PCRs 1 and 3 in the sha256 bank
+
+ sha512:1,3-5 means PCRs 1,3,4 and 5 in the sha512 bank
+
 [examples]
 
 Create a self-signed cert using the TPM engine:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/create_tpm2_key.c 
new/openssl_tpm2_engine-3.1.0/create_tpm2_key.c
--- old/openssl_tpm2_engine-3.0.1/create_tpm2_key.c     2021-04-04 
22:47:14.000000000 +0200
+++ new/openssl_tpm2_engine-3.1.0/create_tpm2_key.c     2022-02-17 
00:15:34.000000000 +0100
@@ -36,6 +36,7 @@
        {"key-size", 1, 0, 's'},
        {"name-scheme", 1, 0, 'n'},
        {"parent-handle", 1, 0, 'p'},
+       {"pcr-lock", 1, 0, 'x'},
        {"wrap", 1, 0, 'w'},
        {"version", 0, 0, 'v'},
        {"password", 1, 0, 'k'},
@@ -94,6 +95,9 @@
                "                                may not be used for general 
signing or\n"
                "                                decryption but may be the 
parent of other\n"
                "                                keys (i.e. it is a storage 
key)\n"
+               "\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"
                "Report bugs to " PACKAGE_BUGREPORT "\n",
                argv0);
@@ -817,6 +821,10 @@
        ENCRYPTED_SECRET_2B secret, *enc_secret = NULL;
        int restricted = 0;
        char *parent_str = NULL;
+       TPML_PCR_SELECTION pcr_lock;
+       int has_policy = 0;
+
+       pcr_lock.count = 0;
 
        OpenSSL_add_all_digests();
        /* may be needed to decrypt the key */
@@ -824,7 +832,7 @@
 
        while (1) {
                option_index = 0;
-               c = getopt_long(argc, argv, "n:s:ab:p:hw:vk:re:ldc:i:",
+               c = getopt_long(argc, argv, "n:s:ab:p:hw:vk:re:ldc:i:x:",
                                long_options, &option_index);
                if (c == -1)
                        break;
@@ -899,6 +907,9 @@
                        case 'i':
                                import = optarg;
                                break;
+                       case 'x':
+                               tpm2_get_pcr_lock(&pcr_lock, optarg);
+                               break;
                        case OPT_DEPRECATED:
                                version = 0;
                                break;
@@ -944,11 +955,24 @@
                exit(1);
        }
 
+       if (pcr_lock.count !=0 && policyFilename) {
+               fprintf(stderr, "cannot specify both policy file and pcr 
lock\n");
+               exit(1);
+       }
+
+       if (pcr_lock.count != 0 && import) {
+               fprintf(stderr, "cannot specify pcr lock and import because 
pcrs may not be correct\n");
+               exit(1);
+       }
+
+       if (pcr_lock.count != 0 || policyFilename)
+               has_policy = 1;
+
        digest.hashAlg = name_alg;
        sizeInBytes = TSS_GetDigestSize(digest.hashAlg);
        memset((uint8_t *)&digest.digest, 0, sizeInBytes);
 
-       if (policyFilename) {
+       if (has_policy) {
                sk = sk_TSSOPTPOLICY_new_null();
                if (!sk) {
                        rc = NOT_TPM_ERROR;
@@ -956,10 +980,11 @@
                        goto out_err;
                }
 
-               rc = tpm2_parse_policy_file(policyFilename, sk, auth, &digest);
-               if (rc) {
+               if (policyFilename) {
+                       rc = tpm2_parse_policy_file(policyFilename, sk, auth, 
&digest);
                        reason = "parse_policy_file";
-                       goto out_free_policy;
+                       if (rc)
+                               goto out_free_policy;
                }
        }
 
@@ -975,6 +1000,8 @@
                                goto out_free_auth;
                        }
                }
+               if (has_policy && !policyFilename)
+                       tpm2_add_auth_policy(sk, &digest);
        }
 
        if (import) {
@@ -982,6 +1009,8 @@
                EVP_PKEY *pkey = openssl_read_key(wrap);
                TPMT_SENSITIVE s;
 
+               rc = NOT_TPM_ERROR;
+
                if (parent_str) {
                        parent = tpm2_get_parent_ext(parent_str);
                        if (parent == 0) {
@@ -996,8 +1025,6 @@
                pub = &objectPublic;
                priv = &outPrivate;
 
-               rc = NOT_TPM_ERROR;
-
                if (!p_pkey || !pkey) {
                        reason = "read openssl key";
                        goto out_err;
@@ -1014,7 +1041,7 @@
                        reason = "openssl_to_tpm_public";
                        goto out_err;
                }
-               if (policyFilename) {
+               if (has_policy) {
                        VAL(pub->publicArea.objectAttributes) &=
                                ~TPMA_OBJECT_USERWITHAUTH;
                        rc = TSS_TPM2B_Create(
@@ -1059,6 +1086,15 @@
                goto out_free_auth;
        }
 
+       if (pcr_lock.count != 0) {
+               rc = tpm2_pcr_lock_policy(tssContext, &pcr_lock,
+                                         sk, &digest);
+               if (rc) {
+                       reason = "create pcr policy";
+                       goto out_free_auth;
+               }
+       }
+
        if (parent_str) {
                parent = tpm2_get_parent(tssContext, parent_str);
                if (parent == 0) {
@@ -1111,7 +1147,7 @@
                        goto out_flush;
                }
 
-               if (policyFilename) {
+               if (has_policy) {
                        VAL(objectPublic.publicArea.objectAttributes) &=
                                ~TPMA_OBJECT_USERWITHAUTH;
                        rc = TSS_TPM2B_Create(
@@ -1171,7 +1207,7 @@
                        tpm2_public_template_ecc(&objectPublic.publicArea, ecc);
                }
 
-               if (policyFilename) {
+               if (has_policy) {
                        VAL(objectPublic.publicArea.objectAttributes) &=
                                ~TPMA_OBJECT_USERWITHAUTH;
                        rc = TSS_TPM2B_Create(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/doc/Makefile.am 
new/openssl_tpm2_engine-3.1.0/doc/Makefile.am
--- old/openssl_tpm2_engine-3.0.1/doc/Makefile.am       1970-01-01 
01:00:00.000000000 +0100
+++ new/openssl_tpm2_engine-3.1.0/doc/Makefile.am       2022-02-17 
00:15:34.000000000 +0100
@@ -0,0 +1,15 @@
+XML2RFC_TARGETS = draft-bottomley-tpm2-keys.txt \
+               draft-bottomley-tpm2-keys.html
+
+if HAVE_XML2RFC
+all: $(XML2RFC_TARGETS)
+
+clean-local:
+       rm -fr $(XML2RFC_TARGETS)
+endif
+
+$(builddir)/%.txt: $(srcdir)/%.xml
+       $(XML2RFC) --text -o $@ $<
+
+$(builddir)/%.html: $(srcdir)/%.xml
+       $(XML2RFC) --html -o $@ $<
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openssl_tpm2_engine-3.0.1/doc/draft-bottomley-tpm2-keys.xml 
new/openssl_tpm2_engine-3.1.0/doc/draft-bottomley-tpm2-keys.xml
--- old/openssl_tpm2_engine-3.0.1/doc/draft-bottomley-tpm2-keys.xml     
1970-01-01 01:00:00.000000000 +0100
+++ new/openssl_tpm2_engine-3.1.0/doc/draft-bottomley-tpm2-keys.xml     
2022-02-17 00:15:34.000000000 +0100
@@ -0,0 +1,465 @@
+<?xml version="1.0"?>
+<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
+<!-- One method to get references from the online citation libraries.
+There has to be one entity for each item to be referenced.
+An alternate method (rfc include) is described in the references.
+-->
+<!ENTITY RFC2119 SYSTEM 
"http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml";>
+<!ENTITY RFC8017 SYSTEM 
"http://xml.resource.org/public/rfc/bibxml/reference.RFC.8017.xml";>
+]>
+<?rfc toc="yes" ?>
+<rfc ipr="trust200902" category="info" docName="draft-bottomley-tpm-keys-00">
+  <front>
+    <title abbrev="TPM 2 Key Format">ASN.1 Specification for TPM 2.0 Key 
Files</title>
+    <author initials="J." surname="Bottomley" fullname="James E.J. Bottomley">
+      <organization>Linux Kernel</organization>
+      <address>
+        <postal>
+          <street/>
+          <city/>
+          <region/>
+          <country>USA</country>
+        </postal>
+        <email>james.bottom...@hansenpartnership.com</email>
+      </address>
+    </author>
+    <date month="May" year="2021"/>
+    <area>Security</area>
+    <keyword>I-D</keyword>
+    <keyword>Internet-Draft</keyword>
+    <keyword>X.509</keyword>
+    <abstract>
+      <t>
+       This specification is designed to be an extension to the ASN.1
+       (defined in <xref target="X.680"/>) specification of PKCS #1
+       <xref target="RFC8017"/> to define the file format of private
+       keys that need to be loaded into a TPM 2 device to operate.
+      </t>
+    </abstract>
+  </front>
+  <middle>
+    <section anchor="intro" title="Introduction">
+      <t>
+       The Security of private keys has long been a concern and the
+       ability of ubiquitous devices like TPMs has made it useful to
+       use them for secure private key storage.  With the advent of
+       TPM 2.0, private key storage inside the TPM (acting as a token
+       which could be referred to by PKCS #11) has been discouraged,
+       and instead key files which are loaded and evicted as
+       necessary is the encouraged format.  This standard defines an
+       interoperable ASN.1 representation for such key files, so that
+       a key created by one tool should be loadable by a different
+       one.
+      </t>
+    </section>
+    <section anchor="terms" title="Terminology">
+      <t>
+        The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
+        NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED",  "MAY", and
+        "OPTIONAL" in this document are to be interpreted as described in
+        <xref target="RFC2119"/>.
+      </t>
+      <section title="Notation">
+       <dl>
+         <dt>ASN.1</dt>
+         <dd>Abstract Syntax Notation defined in
+         <xref target="X.680"/></dd>
+         <dt>DER</dt>
+         <dd>Distinguished Encoding Rules. Basically a defined binary
+         representation for ASN.1</dd>
+         <dt>MSO</dt>
+         <dd>Most Significant Octet (the highest order
+         byte of an integer)</dd>
+         <dt>PEM</dt>
+         <dd>Privacy enhanced Electronic Mail.  An ASCII compatible
+         representation of DER</dd>
+         <dt>TCG</dt>
+         <dd>Trusted Computing Group</dd>
+         <dt>TPM</dt>
+         <dd>Trusted Platform Module</dd>
+       </dl>
+      </section>
+    </section>
+    <section anchor="keyrep" title="Key Representation">
+      <t>
+       All TPM 2.0 keys consist of two binary pieces, a public part,
+       which can be parsed according to the TPM specification for
+       TPM2B_PUBLIC <xref target="TPM2.0"/> and a private part, which
+       is cryptographically sealed in such a way as to be only
+       readable on the TPM that created it.  The purpose of this
+       specification is to specify a format by which the public and
+       private pieces of a TPM key can be loaded.
+      </t>
+      <t>
+       The design of the TPMkey ASN.1 format is that it should have a
+       distinguishing OID at the beginning so the DER form of the
+       key can be easily recognized.  In PEM form, the key MUST have
+       "-----BEGIN TSS2 PRIVATE KEY-----" and "-----END TSS2 PRIVATE
+       KEY-----" as the PEM guards. All additional information that
+       may be needed to load the key is specified as optional
+       explicit elements, which can be extended by later
+       specifications, which is why the TPMkey is not versioned.
+      </t>
+      <section anchor="tpmkey" title="TPMkey Syntax">
+       <figure><artwork>
+ TPMKey ::= SEQUENCE {
+    type        OBJECT IDENTIFIER
+    emptyAuth   [0] EXPLICIT BOOLEAN OPTIONAL
+    policy      [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL
+    secret      [2] EXPLICIT OCTET STRING OPTIONAL
+    parent      INTEGER
+    pubkey      OCTET STRING
+    privkey     OCTET STRING
+  }
+       </artwork></figure>
+       <t>
+         The fields of type TPMKey have the following meanings:
+       </t>
+       <section title="type">
+         <t>
+           A unique OID specifying the key type.  This standard
+           currently defines three types of keys: a loadable key,
+           specified by id-loadablekey, (to be loaded with
+           TPM2_Load), an importable key, specified by
+           id-importablekey, (to be loaded with TPM2_Import) and a
+           sealed data key, specified by id-sealedkey, (to be
+           extracted with TPM2_Unseal).  The TCG has reserved the
+           following OID prefix for this:
+         </t>
+         <figure><artwork>
+  id-tpmkey OBJECT IDENTIFIER ::=
+    {joint-iso-itu-t(2) international-organizations(23) 133 10}
+         </artwork></figure>
+         <t>
+           And the three key types are:
+         </t>
+         <figure><artwork>
+  id-loadablekey OBJECT IDENTIFIER ::=
+    {id-tpmkey 3}
+         </artwork></figure>
+         <figure><artwork>
+  id-importablekey OBJECT IDENTIFIER ::=
+    {id-tpmkey 4}
+         </artwork></figure>
+         <figure><artwork>
+  id-sealedkey OBJECT IDENTIFIER ::=
+    {id-tpmkey 5}
+         </artwork></figure>
+       </section>
+       <section title="emptyAuth">
+         <t>
+           An implementation needs to know as it formulates the
+           TPM2_Load/Import/Unseal command whether it must also send
+           down an authorization, so this parameter gives that
+           indication.  emptyAuth MUST be true if authorization is
+           NOT required and MUST BE either false or absent if
+           authorization is required.  Since this element has
+           three states (one representing true and two representing
+           false) it is RECOMMENDED that implementations emitting
+           TPMkey representations use absence of the tag to represent
+           false.  However, implementations reading TPMKey MUST
+           be able to process all three possible states.
+         </t>
+       </section>
+       <section title="policy">
+         <t>
+           This MUST be present if the TPM key has a policy hash
+           because it describes to the implementation how to
+           construct the policy.  The forms of the policy statement
+           are described in section <xref target="policy"/>.
+         </t>
+       </section>
+       <section title="secret">
+         <t>
+           This section describes the additional cryptographic
+           secret used to specify the outer wrapping of an
+           importable key.  It MUST be present for key type
+           id-importablekey and MUST NOT be present for any other
+           key type.
+         </t>
+         <t>
+           Importable keys (designed to be processed by TPM2_Import)
+           MUST have an unencrypted inner wrapper (symmetricAlg MUST
+           be TPM_ALG_NULL and encryptionKey MUST be empty) and an
+           outer wrapper encrypted to the parent key using
+           inSymSeed. The secret parameter is the fully marshalled
+           TPM2B_ENCRYPTED_SECRET form of inSymSeed.
+         </t>
+       </section>
+       <section title="parent">
+         <t>
+           This MUST be present for all keys and specifies the handle
+           of the parent key.  The parent key SHOULD be either a
+           persistent handle (MSO 0x81) or a permanent handle (MSO
+           0x40).  Since volatile handle numbering can change
+           unexpectedly depending on key load order, the parent
+           SHOULD NOT be a volatile handle (MSO 0x80). The parent MUST
+           NOT have any other MSO.
+         </t>
+         <t>
+            If a permanent handle (MSO 0x40) is specified then the
+            implementation MUST run TPM2_CreatePrimary on the handle
+            using the TCG specified Elliptic Curve template for the
+            NIST P-256 curve and use the primary key so generated as
+            the parent.
+         </t>
+       </section>
+       <section title="pubkey">
+         <t>
+           This MUST be present and MUST correspond to the fully
+           marshalled TPM2B_PUBLIC structure of the TPM Key.
+         </t>
+       </section>
+       <section title="privkey">
+         <t>
+           This MUST be present and MUST correspond to the fully
+           marshalled TPM2B_PRIVATE structure of the TPM Key.  For
+           importable keys, this must be the duplicate parameter that
+           would be input to TPM2_Import.
+         </t>
+       </section>
+      </section>
+    </section>
+    <section anchor="policy" title="Key Policy Specification">
+      <t>
+       Policy is constructed on a TPM by executing a sequence of
+       policy statements.  This specification currently only defines
+       a limited subset of the allowed policy statements.  The policy
+       is specified by a hash, which the execution of the policy
+       statements must reach in order for the policy to be validated
+       (See <xref target="TPM2.0"/> Part 1 for a detailed description.
+      </t>
+      <t>
+       The TPMPolicy ASN.1 MUST be a sequence of policy statements
+       which correspond exactly to TPM policy instructions in the
+       order they should be executed and additionally from which the
+       ultimate policy hash can be constructed.
+      </t>
+      <t>
+       The current policy specification is strictly for AND based
+       policy only and may be extended at a later date with OR
+       policy.  However, the ASN.1 for policy is formulated as CONS
+       elements, leaving the possibility of adding additional but
+       optional elements for policy statements which are not
+       supported by this standard (such as TPM2_PolicyAuthorize).
+      </t>
+      <section title="TPMPolicy Syntax">
+       <figure><artwork>
+ TPMPolicy ::= SEQUENCE {
+    CommandCode   [0] EXPLICIT INTEGER
+    CommandPolicy [1] EXPLICIT OCTET STRING
+  }
+       </artwork></figure>
+       <t>
+         The Fields of type TPMPolicy have the following meanings:
+       </t>
+       <section title="CommandCode">
+         <t>
+           This is the integer representation of the TPM command code
+           for the policy statement.
+         </t>
+       </section>
+       <section title="CommandPolicy">
+         <t>
+           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
+           as the body.
+         </t>
+         <t>
+           Commands which have no body, such as TPM2_AuthVal, MUST be
+           specified as a zero length OCTET STRING
+         </t>
+       </section>
+      </section>
+      <section title="Policy Implementation Considerations">
+       <t>
+         The policy hash for AND based policies is constructed by extension of 
the prior policy hash
+       </t>
+       <figure><artwork>
+  newHash = HASH ( oldHash || policyHash )
+       </artwork></figure>
+       <t>
+         where policyHash is usually simply the hash of the fully
+         marshalled policy command (including the CommandCode).
+         However, this isn't true for TPM2_PolicyCounterTimer() so
+         always consult the <xref target="TPM2.0"/> specifications
+         for how to construct the policyHash.
+       </t>
+       <t>
+         The implementation should fail fast for policy problems, so
+         if an individual policy command returns a failure (which
+         usually indicates a particular policy requirement cannot be
+         met), that failure should be reported in as much detail as
+         possible and processing of the key should fail at that
+         point.
+       </t>
+       <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.
+         </t>
+       </section>
+      </section>
+    </section>
+    <section anchor="implementation" title="Implementation Considerations">
+      <t>
+       Implementations SHOULD support all TCG mandated algorithms,
+       but MAY omit those deemed insecure, such as the SHA1 hash.
+      </t>
+      <t>
+       TPM2_Import transforms the privKey into a TPM2B_PRIVATE which
+       can then be used as a source to TPM2_Load, making the loading
+       of importable keys is necessarily a two stage process, which
+       can be time consuming on some TPMs.  Since the TPM2B_PRIVATE
+       structure emitted by TPM2_Import is fully secure,
+       Implementations SHOULD minimize the number of TPM2_Import
+       operations by caching the emitted TPM2B_PRIVATE.
+      </t>
+    </section>
+    <section anchor="security" title="Security Considerations">
+      <t>
+       The TPM 2.0 supports a variety of algorithms, the most common
+       being SHA1 and SHA256 for hashing and RSA2048 and NIST P-256
+       for asymmetric keys.  Implementors SHOULD NOT use deprecated
+       algorithms, such as SHA1, for any TPM operation.  In
+       particular, the algorithm used for the policy hash SHOULD NOT
+       be SHA1 and this means that SHA1 SHOULD NOT be used as the
+       name algorithm hash for any TPM key.
+      </t>
+      <t>
+       TPM 2.0 supports a session mode (TPM_RS_PW) where
+       authorizations are passed to the TPM in clear text over the
+       TPM connection.  Implementations SHOULD consider the
+       possibility of snooping on the wire between the implementation
+       and the TPM, such as <xref target="TPM GENIE"/>, and SHOULD
+       use HMAC session authorizations as best practice for all TPM
+       keys.
+      </t>
+      <t>
+       In addition to snooping authorizations, snooping may also
+       occur when key material is being exchanged between the TPM and
+       the implementation, such as wrapping of private keys and the
+       sealing and unsealing operations for sealed keys.
+       Implementations SHOULD always use HMAC sessions with
+       TPMA_SESSION_DECRYPT when sensitive information is passed in
+       to the TPM and HMAC sessions with TPMA_SESSION_ENCRYPT when
+       sensitive information is received from the TPM.
+      </t>
+      <t>
+       The easiest way to get the TPM to wrap an external private key
+       is to use TPM2_Import.  However, since TPMA_SESSION_DECRYPT
+       only protects the first parameter (which is encryptionKey),
+       the duplicate should use inner symmetric encryption with a
+       randomly generated ephemeral key, which is then presented to
+       the TPM via the protected encryptionKey parameter.
+      </t>
+      <t>
+       The TPM has a mode where it can generate private key material
+       internally (using TPM2_Create) such that the private part of
+       the key can never leave the TPM.  Implementations SHOULD
+       support this mode but should be aware that while keys created
+       like this may be more secure than wrapped keys, they can also
+       be used only while access to the TPM that created them is
+       available, so implementations SHOULD also support wrapping for
+       keys that are expected to outlive the TPM that's using them.
+       Clients can then develop best practices around TPM wrapped
+       identity keys, possibly with TPM created sub keys, which can
+       only be used on the device they were wrapped for.
+      </t>
+      <t>
+       Since TPM keys can only be used by the specific TPM that
+       created them, which is usually embedded in a piece of
+       hardware, they are secure against exfiltration attacks.
+       However, consideration should be given to an attacker gaining
+       access to the system containing the TPM.  TPM keys are most
+       secure when used as part of an operating system that has
+       guaranteed trust properties, such as secure and measured boot.
+       Implementations SHOULD assist users in constructing key
+       policies that ensure the key can be used only when the
+       operating system is within its trusted parameters to minimize
+       threats from co-located attackers.
+      </t>
+    </section>
+    <section anchor="IANA" title="IANA Considerations">
+      <t>
+       None.
+      </t>
+    </section>
+    <section anchor="comments" title="Comments on and Enhancements to this 
Document">
+      <t>
+       Comments on this document should be addressed to the author
+       (james.bottom...@hansenpartnership.com) but should also CC the
+       email lists of the two projects implementing this
+       specification:
+      </t>
+      <t>
+       The OpenSSL engine: openssl_tpm2_eng...@groups.io
+      </t>
+      <t>
+       The Linux Kernel: linux-integr...@vger.kernel.org
+      </t>
+      <t>
+       The OpenSSL TPM2 engine <xref target="OPENSSL TPM2 ENGINE"/>
+       is currently the only implementation of this full
+       specification, so enhancements should be proposed after
+       patches implementing the enhancement have been accepted by
+       openssl_tpm2_engine or another full specification
+       implementation.
+      </t>
+    </section>
+
+  </middle>
+  <back>
+    <references title="Normative References">
+      &RFC2119;
+      &RFC8017;
+      <reference anchor="TPM2.0" 
target="https://trustedcomputinggroup.org/resource/tpm-library-specification/";>
+       <front>
+          <title>TPM 2.0 Library Specification</title>
+          <author>
+            <organization>Trusted Computing Group</organization>
+          </author>
+          <date year="2013" month="March" day="15"/>
+       </front>
+      </reference>
+      <reference anchor="X.680" 
target="https://itu.int/rec/T-REC-X.680-201508-I/en";>
+       <front>
+         <title>ITU-T Recommendation X.680,
+              Information technology - Abstract Syntax Notation One
+          (ASN.1):  Specification of basic notation.</title>
+         <author><organization>International Telecommunication 
Union</organization></author>
+         <date year="2015" month="August"/>
+       </front>
+      </reference>
+    </references>
+    <references title="Informative References">
+      <reference anchor="TPM GENIE" 
target="https://www.nccgroup.com/globalassets/about-us/us/documents/tpm-genie.pdf";>
+       <front>
+         <title>TPM Genie: Interposer Attacks Against the Trusted
+         Platform Module Serial Bus</title>
+         <author initials="J." surname="Boone" fullname="J. Boone">
+           <organization>NCC Group</organization>
+         </author>
+         <date year="2018" month="March" day="9"/>
+       </front>
+      </reference>
+      <reference anchor="OPENSSL TPM2 ENGINE" 
target="https://git.kernel.org/pub/scm/linux/kernel/git/jejb/openssl_tpm2_engine.git/";>
+       <front>
+         <title>OpenSSL TPM2 Engine</title>
+         <author><organization>Open Source Project</organization></author>
+       </front>
+      </reference>
+    </references>
+  </back>
+</rfc>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/e_tpm2-ecc.c 
new/openssl_tpm2_engine-3.1.0/e_tpm2-ecc.c
--- old/openssl_tpm2_engine-3.0.1/e_tpm2-ecc.c  2021-04-04 22:47:14.000000000 
+0200
+++ new/openssl_tpm2_engine-3.1.0/e_tpm2-ecc.c  2022-02-17 00:15:34.000000000 
+0100
@@ -103,7 +103,11 @@
 #endif
        }
 
+#if OPENSSL_VERSION_NUMBER >= 0x30000000
+       EVP_PKEY_set1_EC_KEY(pkey, eck);
+#else
        EC_KEY_free(eck);
+#endif
 }
 
 static void tpm2_ecc_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/e_tpm2-rsa.c 
new/openssl_tpm2_engine-3.1.0/e_tpm2-rsa.c
--- old/openssl_tpm2_engine-3.0.1/e_tpm2-rsa.c  2021-04-04 22:47:14.000000000 
+0200
+++ new/openssl_tpm2_engine-3.1.0/e_tpm2-rsa.c  2022-02-17 00:15:34.000000000 
+0100
@@ -130,8 +130,12 @@
 
        RSA_set_ex_data(rsa, ex_app_data, data);
 
+#if OPENSSL_VERSION_NUMBER >= 0x30000000
+       EVP_PKEY_set1_RSA(pkey, rsa);
+#else
        /* release the reference EVP_PKEY_get1_RSA obtained */
        RSA_free(rsa);
+#endif
 }
 
 static void tpm2_rsa_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/ibm-tss.h 
new/openssl_tpm2_engine-3.1.0/ibm-tss.h
--- old/openssl_tpm2_engine-3.0.1/ibm-tss.h     2021-04-04 22:47:14.000000000 
+0200
+++ new/openssl_tpm2_engine-3.1.0/ibm-tss.h     2022-02-17 00:15:34.000000000 
+0100
@@ -487,6 +487,32 @@
        return rc;
 }
 
+static inline TPM_RC
+tpm2_PCR_Read(TSS_CONTEXT *tssContext, TPML_PCR_SELECTION *pcrSelectionIn,
+             TPML_PCR_SELECTION *pcrSelectionOut, TPML_DIGEST *pcrValues)
+{
+       PCR_Read_In in;
+       PCR_Read_Out out;
+       TPM_RC rc;
+
+       in.pcrSelectionIn = *pcrSelectionIn;
+
+       rc = TSS_Execute(tssContext,
+                        (RESPONSE_PARAMETERS *)&out,
+                        (COMMAND_PARAMETERS *)&in,
+                        NULL,
+                        TPM_CC_PCR_Read,
+                        TPM_RH_NULL, NULL, 0);
+
+       if (rc)
+               return rc;
+
+       *pcrSelectionOut = out.pcrSelectionOut;
+       *pcrValues = out.pcrValues;
+
+       return rc;
+}
+
 static inline TPM_HANDLE
 tpm2_handle_int(TSS_CONTEXT *tssContext, TPM_HANDLE h)
 {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/intel-tss.h 
new/openssl_tpm2_engine-3.1.0/intel-tss.h
--- old/openssl_tpm2_engine-3.0.1/intel-tss.h   2021-04-04 22:47:14.000000000 
+0200
+++ new/openssl_tpm2_engine-3.1.0/intel-tss.h   2022-02-17 00:15:34.000000000 
+0100
@@ -151,7 +151,7 @@
                                                                \
        *buffer += offset;                                      \
        *size -= offset;                                        \
-       *written = offset;                                      \
+       *written += offset;                                     \
                                                                \
        return rc;                                              \
 }
@@ -179,6 +179,9 @@
 TSS_CONVERT_MARSHAL(TPM2B_DIGEST, )
 TSS_CONVERT_MARSHAL(TPM2B_PUBLIC, )
 TSS_CONVERT_MARSHAL(TPM2B_PRIVATE, )
+TSS_CONVERT_MARSHAL(TPML_PCR_SELECTION, )
+TSS_CONVERT_MARSHAL(UINT32, *)
+#define TSS_TPM_CC_Marshal TSS_UINT32_Marshal
 
 TSS_CONVERT_UNMARSHAL(TPML_PCR_SELECTION, )
 TSS_CONVERT_UNMARSHAL(TPM2B_PRIVATE, )
@@ -935,6 +938,25 @@
                                       operandB, offset, operation);
 }
 
+static inline TPM_RC
+tpm2_PCR_Read(TSS_CONTEXT *tssContext, TPML_PCR_SELECTION *pcrSelectionIn,
+             TPML_PCR_SELECTION *pcrSelectionOut, TPML_DIGEST *pcrValues)
+{
+       TPML_PCR_SELECTION *out;
+       TPML_DIGEST *val;
+       TPM_RC rc;
+
+       rc = Esys_PCR_Read(tssContext, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                          pcrSelectionIn, NULL, &out, &val);
+       if (rc)
+               return rc;
+
+       *pcrSelectionOut = *out;
+       *pcrValues = *val;
+
+       return rc;
+}
+
 static inline TPM_HANDLE
 tpm2_handle_ext(TSS_CONTEXT *tssContext, TPM_HANDLE esysh)
 {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/seal_tpm2_data.1.in 
new/openssl_tpm2_engine-3.1.0/seal_tpm2_data.1.in
--- old/openssl_tpm2_engine-3.0.1/seal_tpm2_data.1.in   2021-04-04 
22:47:14.000000000 +0200
+++ new/openssl_tpm2_engine-3.1.0/seal_tpm2_data.1.in   2022-02-17 
00:15:34.000000000 +0100
@@ -7,6 +7,20 @@
 TPM.  Possible uses for this blob of data include as a symmetric key,
 which is the use in the linux kernel trusted key infrastructure.
 
+[PCR Values]
+
+The PCR values are specified as
+
+ <bank>:<list>
+
+Where <bank> is any supported PCR hash bank and list specifies the
+PCRs to lock the key to as both comma separated individual values as
+well as comma separated ranges.  So
+
+ sha256:1,3 means PCRs 1 and 3 in the sha256 bank
+
+ sha512:1,3-5 means PCRs 1,3,4 and 5 in the sha512 bank
+
 [examples]
 
 Create a sealed data blob to the storage parent (owner hierarchy)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/seal_tpm2_data.c 
new/openssl_tpm2_engine-3.1.0/seal_tpm2_data.c
--- old/openssl_tpm2_engine-3.0.1/seal_tpm2_data.c      2021-04-04 
22:47:14.000000000 +0200
+++ new/openssl_tpm2_engine-3.1.0/seal_tpm2_data.c      2022-02-17 
00:15:34.000000000 +0100
@@ -27,6 +27,7 @@
        {"auth-parent", 1, 0, 'b'},
        {"help", 0, 0, 'h'},
        {"parent-handle", 1, 0, 'p'},
+       {"pcr-lock", 1, 0, 'x'},
        {"version", 0, 0, 'v'},
        {"password", 1, 0, 'k'},
        {"da", 0, 0, 'd'},
@@ -71,6 +72,10 @@
                "\t-m,--nomigrate                Create a sealed data bundle 
that can be\n"
                "                                migrated to other systems.\n"
                "\t-n, --name-scheme <scheme>    name algorithm to use sha1 
[sha256] sha384 sha512\n"
+               "\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"
                "\n"
                "Report bugs to " PACKAGE_BUGREPORT "\n",
                argv0);
@@ -106,6 +111,10 @@
        int32_t size;
        uint16_t pubkey_len, privkey_len;
        char *parent_str = NULL;
+       TPML_PCR_SELECTION pcr_lock;
+       int has_policy = 0;
+
+       pcr_lock.count = 0;
 
        while (1) {
                option_index = 0;
@@ -165,6 +174,9 @@
                case 'm':
                        nomigrate = 1;
                        break;
+               case 'x':
+                       tpm2_get_pcr_lock(&pcr_lock, optarg);
+                       break;
                default:
                        printf("Unknown option '%c'\n", c);
                        usage(argv[0]);
@@ -183,22 +195,32 @@
                usage(argv[0]);
        }
 
+       if (pcr_lock.count !=0 && policyFilename) {
+               fprintf(stderr, "cannot specify both policy file and pcr 
lock\n");
+               exit(1);
+       }
+
+       if (pcr_lock.count != 0 || policyFilename)
+               has_policy = 1;
+
        digest.hashAlg = name_alg;
        sizeInBytes = TSS_GetDigestSize(digest.hashAlg);
        memset((uint8_t *)&digest.digest, 0, sizeInBytes);
 
-       if (policyFilename) {
+       if (has_policy) {
                sk = sk_TSSOPTPOLICY_new_null();
                if (!sk) {
                        fprintf(stderr, "Failed to allocate policy stack\n");
                        exit(1);
                }
 
-               rc = tpm2_parse_policy_file(policyFilename, sk,
-                                           data_auth, &digest);
-               if (rc) {
-                       reason = "parse_policy_file";
-                       goto out_free_policy;
+               if (policyFilename) {
+                       rc = tpm2_parse_policy_file(policyFilename, sk,
+                                                   data_auth, &digest);
+                       if (rc) {
+                               reason = "parse_policy_file";
+                               goto out_free_policy;
+                       }
                }
        }
 
@@ -215,6 +237,8 @@
                                goto out_free_auth;
                        }
                }
+               if (has_policy && !policyFilename)
+                       tpm2_add_auth_policy(sk, &digest);
        }
 
        dir = tpm2_set_unique_tssdir();
@@ -224,6 +248,15 @@
                goto out_rmdir;
        }
 
+       if (pcr_lock.count != 0) {
+               rc = tpm2_pcr_lock_policy(tssContext, &pcr_lock,
+                                         sk, &digest);
+               if (rc) {
+                       reason = "create pcr policy";
+                       goto out_free_auth;
+               }
+       }
+
        if (parent_str) {
                parent = tpm2_get_parent(tssContext, parent_str);
                if (parent == 0) {
@@ -245,7 +278,7 @@
 
        tpm2_public_template_seal(p);
 
-       if (policyFilename) {
+       if (has_policy) {
                VAL(p->objectAttributes) &=
                        ~TPMA_OBJECT_USERWITHAUTH;
                rc = TSS_TPM2B_Create(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openssl_tpm2_engine-3.0.1/tests/check_counter_timer.sh 
new/openssl_tpm2_engine-3.1.0/tests/check_counter_timer.sh
--- old/openssl_tpm2_engine-3.0.1/tests/check_counter_timer.sh  2021-04-04 
22:47:14.000000000 +0200
+++ new/openssl_tpm2_engine-3.1.0/tests/check_counter_timer.sh  2022-02-17 
00:15:34.000000000 +0100
@@ -27,10 +27,11 @@
 # 3. encode a message using the TPM key
 # 4. verify the message through the public key
 ##
+echo "policy counter timer" > plain.txt
 ${bindir}/create_tpm2_key key.tpm -a -k paSSW0RD -c policy.txt && \
 openssl rsa -engine tpm2 -inform engine -pubin -in key.tpm -pubout -out 
key.pub && \
-echo "policy counter timer" | openssl rsautl -sign -passin pass:paSSW0RD 
-engine tpm2 -engine tpm2 -keyform engine -inkey key.tpm -out tmp.msg && \
-openssl rsautl -verify -in tmp.msg -inkey key.pub -pubin || exit 1
+openssl pkeyutl -sign -in plain.txt -passin pass:paSSW0RD -engine tpm2 -engine 
tpm2 -keyform engine -inkey key.tpm -out tmp.msg && \
+openssl pkeyutl -verify -in plain.txt -sigfile tmp.msg -inkey key.pub -pubin 
|| exit 1
 
 ##
 # advance the TPM clock by ten minutes and a second which should make
@@ -44,7 +45,7 @@
 # now the signing operation should fail
 ##
 echo "Check key failure due to counter timer policy"
-echo "policy fail counter timer" | openssl rsautl -sign -passin pass:paSSW0RD 
-engine tpm2 -engine tpm2 -keyform engine -inkey key.tpm -out tmp.msg 2> 
tmp.txt && exit 1
+openssl pkeyutl -sign -in plain.txt -passin pass:paSSW0RD -engine tpm2 -engine 
tpm2 -keyform engine -inkey key.tpm -out tmp.msg 2> tmp.txt && exit 1
 # check we got the right failure message
 grep "Policy Failure: Counter Timer at offset 8 is not <=" tmp.txt
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openssl_tpm2_engine-3.0.1/tests/check_enhanced_auth.sh 
new/openssl_tpm2_engine-3.1.0/tests/check_enhanced_auth.sh
--- old/openssl_tpm2_engine-3.0.1/tests/check_enhanced_auth.sh  2021-04-04 
22:47:14.000000000 +0200
+++ new/openssl_tpm2_engine-3.1.0/tests/check_enhanced_auth.sh  2022-02-17 
00:15:34.000000000 +0100
@@ -19,7 +19,22 @@
 ${bindir}/create_tpm2_key key.tpm -c policies/policy_bogus.txt
 a=0; while [ $a -lt 5 ]; do
     a=$[$a+1]
-    echo "This is a message" | openssl rsautl -sign -engine tpm2 -engine tpm2 
-keyform engine -inkey key.tpm -out tmp.msg && exit 1
+    echo "This is a message" | openssl pkeyutl -sign -engine tpm2 -engine tpm2 
-keyform engine -inkey key.tpm -out tmp.msg && exit 1
+done
+
+##
+# Randomize the PCR banks
+##
+for h in "sha1" "sha256" "sha384"; do
+    pcr=0;
+    while [ $pcr -lt 24 ]; do
+       tsspcrextend -ha $pcr -halg $h -ic $RANDOM
+       pcr=$[$pcr + 1]
+    done
+    ##
+    # reset PCR 16 for the fixed policy tests
+    ##
+    ${tss_pcrreset_cmd} -ha 16
 done
 
 for h in "sha1" "" "sha384"; do
@@ -35,10 +50,11 @@
     # 2. get the corresponding public key from the engine
     # 3. encode a message using the TPM key
     # 4. verify the message through the public key
+    echo "This is a Message" > plain.txt
     ${bindir}/create_tpm2_key ${n} -a -k passw0rd key2.tpm -c 
policies/policy_authvalue.txt && \
     openssl rsa -engine tpm2 -inform engine -passin pass:passw0rd -in key2.tpm 
-pubout -out key2.pub && \
-    echo "This is a message" | openssl rsautl -sign -engine tpm2 -engine tpm2 
-keyform engine -inkey key2.tpm -passin pass:passw0rd -out tmp.msg && \
-    openssl rsautl -verify -in tmp.msg -inkey key2.pub -pubin || exit 1
+    openssl pkeyutl -sign -engine tpm2 -engine tpm2 -keyform engine -inkey 
key2.tpm -passin pass:passw0rd -in plain.txt -out tmp.msg && \
+    openssl pkeyutl -verify -in plain.txt -sigfile tmp.msg -inkey key2.pub 
-pubin || exit 1
 
     ##
     # test is
@@ -52,8 +68,8 @@
     ${tss_pcrextend_cmd} -ha 16 -ic aaa
     ${bindir}/create_tpm2_key ${n} key2.tpm -c policies/policy_pcr${h}.txt && \
        openssl rsa -engine tpm2 -inform engine -in key2.tpm -pubout -out 
key2.pub && \
-       echo "This is a message" | openssl rsautl -sign -engine tpm2 -engine 
tpm2 -keyform engine -inkey key2.tpm -out tmp.msg && \
-       openssl rsautl -verify -in tmp.msg -inkey key2.pub -pubin || exit 1
+       openssl pkeyutl -sign -in plain.txt -engine tpm2 -engine tpm2 -keyform 
engine -inkey key2.tpm -out tmp.msg && \
+       openssl pkeyutl -verify -in plain.txt -sigfile tmp.msg -inkey key2.pub 
-pubin || exit 1
 
     ##
     # test is
@@ -65,8 +81,8 @@
     ${tss_pcrreset_cmd} -ha 16
     ${bindir}/create_tpm2_key ${n} key2.tpm -c policies/policy_pcr${h}.txt
     openssl rsa -engine tpm2 -inform engine -in key2.tpm -pubout -out key2.pub 
&& \
-       echo "This is a message" | openssl rsautl -sign -engine tpm2 -engine 
tpm2 -keyform engine -inkey key2.tpm -out tmp.msg && \
-       openssl rsautl -verify -in tmp.msg -inkey key2.pub -pubin
+       openssl pkeyutl -sign -in plain.txt -engine tpm2 -engine tpm2 -keyform 
engine -inkey key2.tpm -out tmp.msg && \
+       openssl pkeyutl -verify -in plain.txt -sigfile tmp.msg -inkey key2.pub 
-pubin
     if [ $? -ne 1 ]; then
        echo "TPM key should not be accessible"
        exit 1
@@ -85,8 +101,8 @@
     ${tss_pcrextend_cmd} -ha 16 -ic aaa
     ${bindir}/create_tpm2_key ${n} -a -k passw0rd key2.tpm -c 
policy_authvalue_pcr.txt && \
        openssl rsa -engine tpm2 -inform engine -passin pass:passw0rd -in 
key2.tpm -pubout -out key2.pub && \
-       echo "This is a message" | openssl rsautl -sign -engine tpm2 -engine 
tpm2 -keyform engine -inkey key2.tpm -passin pass:passw0rd -out tmp.msg && \
-       openssl rsautl -verify -in tmp.msg -inkey key2.pub -pubin || exit 1
+       openssl pkeyutl -sign -in plain.txt -engine tpm2 -engine tpm2 -keyform 
engine -inkey key2.tpm -passin pass:passw0rd -out tmp.msg && \
+       openssl pkeyutl -verify -in plain.txt -sigfile tmp.msg -inkey key2.pub 
-pubin || exit 1
 
     ##
     # test is
@@ -101,6 +117,36 @@
     ${tss_pcrextend_cmd} -ha 16 -ic aaa
     ${bindir}/create_tpm2_key ${n} -a -k passw0rd key2.tpm -c 
policy_pcr_authvalue.txt && \
        openssl rsa -engine tpm2 -inform engine -passin pass:passw0rd -in 
key2.tpm -pubout -out key2.pub && \
-       echo "This is a message" | openssl rsautl -sign -engine tpm2 -engine 
tpm2 -keyform engine -inkey key2.tpm -passin pass:passw0rd -out tmp.msg && \
-       openssl rsautl -verify -in tmp.msg -inkey key2.pub -pubin || exit 1
+       openssl pkeyutl -sign -in plain.txt -engine tpm2 -engine tpm2 -keyform 
engine -inkey key2.tpm -passin pass:passw0rd -out tmp.msg && \
+       openssl pkeyutl -verify -in plain.txt -sigfile tmp.msg -inkey key2.pub 
-pubin || exit 1
+
+    ##
+    # test is
+    # 1. Create a key on a huge range of PCRs (testing multiple reads)
+    # 2. verify key works with undisturbed PCRs
+    # 3. extend non-mentioned pcr and verify key works
+    # 4. extend mentioned PCR and verify key fails
+    ##
+    ${bindir}/create_tpm2_key ${n} -a -k passw0rd key.tpm --pcr-lock 
1,2,3-15,17-23 --pcr-lock sha1:1-4 --pcr-lock sha384:10-20 || exit 1
+    openssl rsa -engine tpm2 -inform engine -passin pass:passw0rd -in key.tpm 
-pubout -out key.pub || exit 1
+    openssl pkeyutl -sign -in plain.txt -engine tpm2 -engine tpm2 -keyform 
engine -inkey key.tpm -passin pass:passw0rd -out tmp.msg || exit 1
+    openssl pkeyutl -verify -in plain.txt -sigfile tmp.msg -inkey key.pub 
-pubin || exit 1
+    ${tss_pcrextend_cmd} -ha 16 -ic $RANDOM
+    ${tss_pcrextend_cmd} -ha 5 -halg sha1 -ic $RANDOM
+    ${tss_pcrextend_cmd} -ha 9 -halg sha384 -ic $RANDOM
+    openssl pkeyutl -sign -in plain.txt -engine tpm2 -engine tpm2 -keyform 
engine -inkey key.tpm -passin pass:passw0rd -out tmp.msg || exit 1
+    openssl pkeyutl -verify -in plain.txt -sigfile tmp.msg -inkey key.pub 
-pubin || exit 1
+    ${tss_pcrextend_cmd} -ha 1 -halg sha1 -ic $RANDOM
+    openssl pkeyutl -sign -in plain.txt -engine tpm2 -engine tpm2 -keyform 
engine -inkey key.tpm -passin pass:passw0rd -out tmp.msg && exit 1
+    ##
+    # Check a smaller PCR lock with no auth
+    ##
+    ${bindir}/create_tpm2_key ${n} --pcr-lock 2,4,7,10 --pcr-lock sha1:1,3 
key.tpm || exit 1
+    openssl rsa -engine tpm2 -inform engine -in key.tpm -pubout -out key.pub 
|| exit 1
+    openssl pkeyutl -sign -in plain.txt -engine tpm2 -engine tpm2 -keyform 
engine -inkey key.tpm -out tmp.msg || exit 1
+    openssl pkeyutl -verify -in plain.txt -sigfile tmp.msg -inkey key.pub 
-pubin || exit 1
+    ${tss_pcrextend_cmd} -ha 4 -halg sha256 -ic $RANDOM
+    echo "This is a message" | openssl pkeyutl -sign -engine tpm2 -engine tpm2 
-keyform engine -inkey key.tpm -out tmp.msg && exit 1
 done
+
+exit 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/tests/create_ecc.sh 
new/openssl_tpm2_engine-3.1.0/tests/create_ecc.sh
--- old/openssl_tpm2_engine-3.0.1/tests/create_ecc.sh   2021-04-04 
22:47:14.000000000 +0200
+++ new/openssl_tpm2_engine-3.1.0/tests/create_ecc.sh   2022-02-17 
00:15:34.000000000 +0100
@@ -8,7 +8,7 @@
 # 2. Create a self signed x509 certificate
 # 3. verify the certificate
 for curve in $(${bindir}/create_tpm2_key --list-curves); do
-    if openssl ecparam -name ${curve} 2>&1 | grep 'unknown curve'; then
+    if openssl ecparam -name ${curve} 2>&1 | egrep '(invalid|unknown) curve'; 
then
        continue
     fi
     echo "Checking curve ${curve}"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openssl_tpm2_engine-3.0.1/tests/create_nonopenssl_ecc.sh 
new/openssl_tpm2_engine-3.1.0/tests/create_nonopenssl_ecc.sh
--- old/openssl_tpm2_engine-3.0.1/tests/create_nonopenssl_ecc.sh        
2021-04-04 22:47:14.000000000 +0200
+++ new/openssl_tpm2_engine-3.1.0/tests/create_nonopenssl_ecc.sh        
2022-02-17 00:15:34.000000000 +0100
@@ -14,7 +14,7 @@
 
 
 for curve in $(${bindir}/create_tpm2_key --list-curves); do
-    if openssl ecparam -name ${curve} 2>&1 | grep -v 'unknown curve'; then
+    if openssl ecparam -name ${curve} 2>&1 | egrep -v '(invalid|unknown) 
curve'; then
        continue
     fi
     echo "Checking curve ${curve}"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/tests/da_check.sh 
new/openssl_tpm2_engine-3.1.0/tests/da_check.sh
--- old/openssl_tpm2_engine-3.0.1/tests/da_check.sh     2021-04-04 
22:47:14.000000000 +0200
+++ new/openssl_tpm2_engine-3.1.0/tests/da_check.sh     2022-02-17 
00:15:34.000000000 +0100
@@ -13,7 +13,7 @@
 count=1;
 while true; do
     echo "This is a message" | 
-    openssl rsautl -sign -engine tpm2 -keyform engine -inkey key.tpm -passin 
pass:passwrd -out tmp.msg 2>tmp.txt
+    openssl pkeyutl -sign -engine tpm2 -keyform engine -inkey key.tpm -passin 
pass:passwrd -out tmp.msg 2>tmp.txt
     val=$?
     cat tmp.txt
     if [ $val -ne 1 ]; then
@@ -39,7 +39,7 @@
 echo "Locked out after $count tries"
 # try with correct password, should still be locked out
 echo "This is a message" | 
-openssl rsautl -sign -engine tpm2 -keyform engine -inkey key.tpm -passin 
pass:passw0rd -out tmp.msg 2>tmp.txt
+openssl pkeyutl -sign -engine tpm2 -keyform engine -inkey key.tpm -passin 
pass:passw0rd -out tmp.msg 2>tmp.txt
 val=$?
 cat tmp.txt
 if [ $val -ne 1 ]; then
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/tests/derive_ecc.sh 
new/openssl_tpm2_engine-3.1.0/tests/derive_ecc.sh
--- old/openssl_tpm2_engine-3.0.1/tests/derive_ecc.sh   2021-04-04 
22:47:14.000000000 +0200
+++ new/openssl_tpm2_engine-3.1.0/tests/derive_ecc.sh   2022-02-17 
00:15:34.000000000 +0100
@@ -24,7 +24,7 @@
 ##
 
 for curve in $(${bindir}/create_tpm2_key --list-curves); do
-    if openssl ecparam -name ${curve} 2>&1 | grep 'unknown curve'; then
+    if openssl ecparam -name ${curve} 2>&1 | egrep '(invalid|unknown) curve'; 
then
        continue
     fi
     echo "Checking curve ${curve} explicitly named"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/tests/fail_connect.sh 
new/openssl_tpm2_engine-3.1.0/tests/fail_connect.sh
--- old/openssl_tpm2_engine-3.0.1/tests/fail_connect.sh 2021-04-04 
22:47:14.000000000 +0200
+++ new/openssl_tpm2_engine-3.1.0/tests/fail_connect.sh 2022-02-17 
00:15:34.000000000 +0100
@@ -41,7 +41,7 @@
 # conversion to public key doesn't actually contact the TPM
 # so this should succeed
 ##
-openssl rsa -engine tpm2 -inform engine -in tmp.tpm -pubout -out tmp.pub 2> 
tmp.txt
+openssl pkey -engine tpm2 -inform engine -in tmp.tpm -pubout -out tmp.pub 2> 
tmp.txt
 if [ $? -ne 0 ]; then
     echo "TPM key import failed with $?"
     cat tmp.txt
@@ -51,7 +51,7 @@
 # key operation does contact the TPM and should fail
 ##
 echo "This is a message" |\
-openssl rsautl -sign -engine tpm2 -keyform engine -inkey tmp.tpm -out tmp.msg 
2> tmp.txt
+openssl pkeyutl -sign -engine tpm2 -keyform engine -inkey tmp.tpm -out tmp.msg 
2> tmp.txt
 if [ $? -ne 1 ]; then
     echo "TPM key signing failed with $?"
     cat tmp.txt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/tests/seal_unseal.sh 
new/openssl_tpm2_engine-3.1.0/tests/seal_unseal.sh
--- old/openssl_tpm2_engine-3.0.1/tests/seal_unseal.sh  2021-04-04 
22:47:14.000000000 +0200
+++ new/openssl_tpm2_engine-3.1.0/tests/seal_unseal.sh  2022-02-17 
00:15:34.000000000 +0100
@@ -16,4 +16,22 @@
 echo $DATA | ${bindir}/seal_tpm2_data -a -k ${AUTH} seal.tpm || exit 1;
 ${bindir}/unseal_tpm2_data -k ${AUTH} seal.tpm | grep -q "${DATA}" || exit 1;
 
+##
+# Check with policy
+# test is
+# 1. seal with a pcr lock and no auth
+# 2. verify unseal
+# 3. move PCR on and verify no unseal
+# 4. 1-3 with auth and pcr lock
+##
+echo $DATA | ${bindir}/seal_tpm2_data --pcr-lock 2,16 seal.tpm || exit 1;
+${bindir}/unseal_tpm2_data seal.tpm | grep -q "${DATA}" || exit 1;
+tsspcrextend -ha 16 -ic $RANDOM
+${bindir}/unseal_tpm2_data seal.tpm && exit 1
+echo $DATA | ${bindir}/seal_tpm2_data -a -k ${AUTH} --pcr-lock 2,16 seal.tpm 
|| exit 1;
+${bindir}/unseal_tpm2_data -k ${AUTH} seal.tpm | grep -q "${DATA}" || exit 1;
+tsspcrextend -ha 16 -ic $RANDOM
+${bindir}/unseal_tpm2_data -k ${AUTH} seal.tpm && exit 1
+
+
 exit 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/tests/wrap_ecc.sh 
new/openssl_tpm2_engine-3.1.0/tests/wrap_ecc.sh
--- old/openssl_tpm2_engine-3.0.1/tests/wrap_ecc.sh     2021-04-04 
22:47:14.000000000 +0200
+++ new/openssl_tpm2_engine-3.1.0/tests/wrap_ecc.sh     2022-02-17 
00:15:34.000000000 +0100
@@ -9,7 +9,7 @@
 # 3. Create a self signed x509 certificate
 # 4. verify the certificate
 for curve in $(${bindir}/create_tpm2_key --list-curves); do
-    if openssl ecparam -name ${curve} 2>&1 | grep 'unknown curve'; then
+    if openssl ecparam -name ${curve} 2>&1 | egrep '(unknown|invalid) curve'; 
then
        continue
     fi
     echo "Checking curve ${curve}"
@@ -21,7 +21,7 @@
     exit 1
 done
 for curve in $(${bindir}/create_tpm2_key --list-curves); do
-    if openssl ecparam -name ${curve} 2>&1 | grep 'unknown curve'; then
+    if openssl ecparam -name ${curve} 2>&1 | egrep '(invalid|unknown) curve'; 
then
        continue
     fi
     echo "Checking curve ${curve}"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/tests/wrap_generic_ecc.sh 
new/openssl_tpm2_engine-3.1.0/tests/wrap_generic_ecc.sh
--- old/openssl_tpm2_engine-3.0.1/tests/wrap_generic_ecc.sh     2021-04-04 
22:47:14.000000000 +0200
+++ new/openssl_tpm2_engine-3.1.0/tests/wrap_generic_ecc.sh     2022-02-17 
00:15:34.000000000 +0100
@@ -9,7 +9,7 @@
 # 3. Create a self signed x509 certificate
 # 4. verify the certificate
 for curve in $(${bindir}/create_tpm2_key --list-curves); do
-    if openssl ecparam -name ${curve} 2>&1 | grep 'unknown curve'; then
+    if openssl ecparam -name ${curve} 2>&1 | egrep '(invalid|unknown) curve'; 
then
        continue
     fi
     openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:${curve} -out 
key.priv && \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/tpm2-common.c 
new/openssl_tpm2_engine-3.1.0/tpm2-common.c
--- old/openssl_tpm2_engine-3.0.1/tpm2-common.c 2021-04-04 22:47:14.000000000 
+0200
+++ new/openssl_tpm2_engine-3.1.0/tpm2-common.c 2022-02-17 00:15:34.000000000 
+0100
@@ -29,6 +29,25 @@
 #include "tpm2-asn.h"
 #include "tpm2-common.h"
 
+static struct {
+       const char *hash;
+       TPM_ALG_ID alg;
+} tpm2_hashes[] = {
+       { "sha1", TPM_ALG_SHA1 },
+       { "sha256", TPM_ALG_SHA256 },
+       { "sha384", TPM_ALG_SHA384 },
+#ifdef TPM_ALG_SHA512
+       { "sha512", TPM_ALG_SHA512 },
+#endif
+#ifdef TPM_ALG_SM3_256
+       { "sm3", TPM_ALG_SM3_256 },
+#endif
+       { NULL, 0 }
+};
+
+#define                MAX_TPM_PCRS    24
+const int      MAX_TPM_PCRS_ARRAY = (MAX_TPM_PCRS + 7)/8;
+
 struct myTPM2B {
        UINT16 s;
        BYTE *const b;
@@ -1470,7 +1489,7 @@
                rc = tpm2_create(&tssContext, ad->dir);
                if (rc) {
                        reason="tpm2_create";
-                       goto import_err;
+                       goto import_no_flush_err;
                }
 
                parentHandle = tpm2_handle_int(tssContext, ad->parent);
@@ -1512,6 +1531,7 @@
 
        import_err:
                tpm2_flush_srk(tssContext, parentHandle);
+       import_no_flush_err:
                TSS_Delete(tssContext);
                if (rc) {
                        tpm2_error(rc, reason);
@@ -1891,6 +1911,240 @@
        sk_TSSOPTPOLICY_free(sk);
 }
 
+static const char *get_hash_by_alg(TPM_ALG_ID alg)
+{
+       int i;
+
+       for (i = 0; tpm2_hashes[i].hash; i++)
+               if (tpm2_hashes[i].alg == alg)
+                       break;
+
+       return tpm2_hashes[i].hash;
+}
+
+static int add_pcrs_hash(TPML_PCR_SELECTION *pcrs, char *bank)
+{
+       int i;
+       TPM_ALG_ID alg;
+
+       for (i = 0; tpm2_hashes[i].hash; i++)
+               if (strcmp(tpm2_hashes[i].hash, bank) == 0)
+                       break;
+
+       if (!tpm2_hashes[i].hash) {
+               fprintf(stderr, "unknown bank in pcrs list %s\n", bank);
+               exit(1);
+       }
+       alg = tpm2_hashes[i].alg;
+
+       for (i = 0; i < pcrs->count; i++)
+               if (pcrs->pcrSelections[i].hash == alg) {
+                       fprintf(stderr, "hash bank %s was already specified\n", 
bank);
+                       exit(1);
+               }
+
+       pcrs->pcrSelections[i].hash = alg;
+       pcrs->pcrSelections[i].sizeofSelect = MAX_TPM_PCRS_ARRAY;
+       pcrs->count++;
+
+       return i;
+}
+
+static void update_pcrs(TPML_PCR_SELECTION *pcrs, int bank, char *str)
+{
+       char *sep = strchr(str, '-');
+       char *endptr;
+       long from, to;
+       int i;
+
+       if (sep)
+               *sep = '\0';
+       from = to = strtol(str, &endptr, 10);
+       if (*endptr != '\0' || from < 0 || from >= MAX_TPM_PCRS)
+               goto err;
+
+       if (sep) {
+               str = sep + 1;
+               to = strtol(str, &endptr, 10);
+
+               if (*endptr != '\0' || to < 0 || to >= MAX_TPM_PCRS)
+                       goto err;
+       }
+       if (to < from) {
+               fprintf(stderr, "Incorrect PCR range specified %ld-%ld\n",
+                       from, to);
+               exit(1);
+       }
+
+       for (i = from; i <= to; i++)
+               pcrs->pcrSelections[bank].pcrSelect[i/8] |= (1 << (i%8));
+
+       return;
+ err:
+       fprintf(stderr, "incorrect PCR specification %s\n", str);
+       exit(1);
+}
+
+void tpm2_get_pcr_lock(TPML_PCR_SELECTION *pcrs, char *arg)
+{
+       char *sep = strchr(arg, ':');
+       char *bankstr = arg;
+       int bank;
+
+       if (sep) {
+               *sep = '\0';
+               arg = sep + 1;
+       } else {
+               bankstr = "sha256";
+       }
+       bank = add_pcrs_hash(pcrs, bankstr);
+       for (sep = strchr(arg, ','); sep; arg = sep + 1, sep = strchr(arg, 
',')) {
+               *sep = '\0';
+               update_pcrs(pcrs, bank, arg);
+       }
+       update_pcrs(pcrs, bank, arg);
+}
+
+static int hash_print(const char *hash, int start, BYTE val, int k,
+                     TPML_DIGEST *dl, EVP_MD_CTX *ctx)
+{
+       int i, j;
+
+       for (i = 0; i < 8; i++) {
+               TPM2B_DIGEST *d;
+               BYTE *db;
+
+               if ((val & (1 << i)) == 0)
+                       continue;
+
+               d = &dl->digests[k++];
+               db = VAL_2B_P(d, buffer);
+               EVP_DigestUpdate(ctx, VAL_2B_P(d, buffer), VAL_2B_P(d, size));
+               printf("%s: %02d: ", hash, start + i);
+               for (j = 0; j < VAL_2B_P(d, size); j++) {
+                       printf("%02x", db[j]);
+               }
+               printf("\n");
+       }
+       return k;
+}
+
+static void pcr_digests_process(TPML_PCR_SELECTION *in, TPML_PCR_SELECTION 
*out,
+                               TPML_DIGEST *d, EVP_MD_CTX *ctx)
+{
+       int i, j, k = 0;
+
+       for (i = 0; i < in->count; i++) {
+               const char *hash = get_hash_by_alg(out->pcrSelections[i].hash);
+
+               for (j = 0; j < MAX_TPM_PCRS_ARRAY; j++) {
+                       in->pcrSelections[i].pcrSelect[j] &=
+                               ~out->pcrSelections[i].pcrSelect[j];
+
+                       k = hash_print(hash, j * 8,
+                                      out->pcrSelections[i].pcrSelect[j],
+                                      k, d, ctx);
+               }
+       }
+}
+
+TPM_RC tpm2_pcr_lock_policy(TSS_CONTEXT *tssContext,
+                           TPML_PCR_SELECTION *pcrs,
+                           STACK_OF(TSSOPTPOLICY) *sk,
+                           TPMT_HA *digest)
+{
+       TSSOPTPOLICY *policy = TSSOPTPOLICY_new();
+       TPM_RC rc;
+       BYTE buf[1024];
+       UINT16 written = 0;
+       INT32 size = sizeof(buf);
+       const TPM_CC cc = TPM_CC_PolicyPCR;
+       DIGEST_2B pcrDigest;
+       BYTE *buffer = buf;
+       TPML_PCR_SELECTION pcrread, pcrreturn;
+       TPML_DIGEST pcr_digests;
+       EVP_MD_CTX *ctx = EVP_MD_CTX_create();
+
+       switch (digest->hashAlg) {
+       case TPM_ALG_SHA1:
+               EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
+               break;
+       case TPM_ALG_SHA256:
+               EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
+               break;
+       case TPM_ALG_SHA384:
+               EVP_DigestInit_ex(ctx, EVP_sha384(), NULL);
+               break;
+#ifdef TPM_ALG_SHA512
+       case TPM_ALG_SHA512:
+               EVP_DigestInit_ex(ctx, EVP_sha512(), NULL);
+               break;
+#endif
+#ifdef TPM_ALG_SM3_256
+       case TPM_ALG_SM3_256:
+               EVP_DigestInit_ex(ctx, EVP_sm3(), NULL);
+               break;
+#endif
+       default:
+               fprintf(stderr, "Unknown TPM hash algorithm 0x%x\n",
+                       digest->hashAlg);
+               exit(1);
+       }
+
+       pcrread = *pcrs;
+
+       for (;;) {
+               rc = tpm2_PCR_Read(tssContext, &pcrread, &pcrreturn, 
&pcr_digests);
+               if (pcr_digests.count == 0 || rc != TPM_RC_SUCCESS)
+                       break;
+
+               pcr_digests_process(&pcrread, &pcrreturn, &pcr_digests, ctx);
+       }
+
+       EVP_DigestFinal_ex(ctx, pcrDigest.buffer, NULL);
+       pcrDigest.size = TSS_GetDigestSize(digest->hashAlg);
+       EVP_MD_CTX_destroy(ctx);
+
+       if (rc)
+               return rc;
+
+       ASN1_INTEGER_set(policy->CommandCode, cc);
+       TSS_TPM_CC_Marshal(&cc, &written, &buffer, &size);
+       TSS_TPML_PCR_SELECTION_Marshal(pcrs, &written, &buffer, &size);
+       memcpy(buffer, pcrDigest.buffer, pcrDigest.size);
+       written += pcrDigest.size;
+       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);
+
+       return TPM_RC_SUCCESS;
+}
+
+void tpm2_add_auth_policy(STACK_OF(TSSOPTPOLICY) *sk, TPMT_HA *digest)
+{
+       TSSOPTPOLICY *policy = TSSOPTPOLICY_new();
+       BYTE buf[4];
+       BYTE *buffer = buf;
+       UINT16 written = 0;
+       INT32 size = sizeof(buf);
+       const TPM_CC cc = TPM_CC_PolicyAuthValue;
+
+       TSS_TPM_CC_Marshal(&cc, &written, &buffer, &size);
+
+       ASN1_INTEGER_set(policy->CommandCode, cc);
+       ASN1_STRING_set(policy->CommandPolicy, "", 0);
+       sk_TSSOPTPOLICY_push(sk, policy);
+
+       TSS_Hash_Generate(digest,
+                         TSS_GetDigestSize(digest->hashAlg),
+                         (uint8_t *)&digest->digest,
+                         written, buf, 0, NULL);
+}
+
 IMPLEMENT_ASN1_FUNCTIONS(TSSOPTPOLICY)
 IMPLEMENT_ASN1_FUNCTIONS(TSSLOADABLE)
 IMPLEMENT_ASN1_FUNCTIONS(TSSPRIVKEY)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openssl_tpm2_engine-3.0.1/tpm2-common.h 
new/openssl_tpm2_engine-3.1.0/tpm2-common.h
--- old/openssl_tpm2_engine-3.0.1/tpm2-common.h 2021-04-04 22:47:14.000000000 
+0200
+++ new/openssl_tpm2_engine-3.1.0/tpm2-common.h 2022-02-17 00:15:34.000000000 
+0100
@@ -88,4 +88,10 @@
                              STACK_OF(TSSOPTPOLICY) *sk,
                              char *auth, TPMT_HA *digest);
 void tpm2_free_policy(STACK_OF(TSSOPTPOLICY) *sk);
+void tpm2_get_pcr_lock(TPML_PCR_SELECTION *pcrs, char *arg);
+TPM_RC tpm2_pcr_lock_policy(TSS_CONTEXT *tssContext,
+                           TPML_PCR_SELECTION *pcrs,
+                           STACK_OF(TSSOPTPOLICY) *sk,
+                           TPMT_HA *digest);
+void tpm2_add_auth_policy(STACK_OF(TSSOPTPOLICY) *sk, TPMT_HA *digest);
 #endif

Reply via email to