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 2023-02-01 16:39:34
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openssl_tpm2_engine (Old)
and /work/SRC/openSUSE:Factory/.openssl_tpm2_engine.new.32243 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "openssl_tpm2_engine"
Wed Feb 1 16:39:34 2023 rev:10 rq:1062393 version:3.3.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/openssl_tpm2_engine/openssl_tpm2_engine.changes
2023-01-14 00:03:44.197892246 +0100
+++
/work/SRC/openSUSE:Factory/.openssl_tpm2_engine.new.32243/openssl_tpm2_engine.changes
2023-02-01 16:49:00.417187926 +0100
@@ -1,0 +2,9 @@
+Tue Jan 31 21:17:40 UTC 2023 - [email protected]
+
+- Update to version 3.3.1
+ * fix intermittent EC TPM_RC_KEY return
+ * add import section to man pages
+ * Add importable sealed data
+ * Fix name hash for importable keys and data
+
+-------------------------------------------------------------------
Old:
----
openssl_tpm2_engine-3.2.1.tar.gz
New:
----
openssl_tpm2_engine-3.3.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ openssl_tpm2_engine.spec ++++++
--- /var/tmp/diff_new_pack.D3Iddi/_old 2023-02-01 16:49:00.773190075 +0100
+++ /var/tmp/diff_new_pack.D3Iddi/_new 2023-02-01 16:49:00.781190124 +0100
@@ -18,7 +18,7 @@
Name: openssl_tpm2_engine
-Version: 3.2.1
+Version: 3.3.1
Release: 0
Summary: OpenSSL TPM 2.0 interface engine plugin
License: LGPL-2.1-only
++++++ openssl_tpm2_engine-3.2.1.tar.gz -> openssl_tpm2_engine-3.3.1.tar.gz
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-3.2.1/configure.ac
new/openssl_tpm2_engine-3.3.1/configure.ac
--- old/openssl_tpm2_engine-3.2.1/configure.ac 2023-01-12 21:56:04.000000000
+0100
+++ new/openssl_tpm2_engine-3.3.1/configure.ac 2023-01-31 17:21:01.000000000
+0100
@@ -2,7 +2,7 @@
# configure.in for the OpenSSL TPM engine project
#
-AC_INIT(openssl-tpm2-engine, 3.2.1, <[email protected]>)
+AC_INIT(openssl-tpm2-engine, 3.3.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-3.2.1/create_tpm2_key.1.in
new/openssl_tpm2_engine-3.3.1/create_tpm2_key.1.in
--- old/openssl_tpm2_engine-3.2.1/create_tpm2_key.1.in 2023-01-12
21:56:04.000000000 +0100
+++ new/openssl_tpm2_engine-3.3.1/create_tpm2_key.1.in 2023-01-31
17:21:01.000000000 +0100
@@ -45,6 +45,25 @@
sha512:1,3-5 means PCRs 1,3,4 and 5 in the sha512 bank
+[Import]
+
+In some cases, there may be a need to wrap a key without access to the
+TPM it will be use on. For these cases an importable key may be
+specified with the --import option. For this to work, you must use a
+public key corresponding exactly to the one the importing TPM will use
+(Note: only Elliptic Curve parents are currently supported). For
+instance the owner seed elliptic curve storage key may be produced as
+
+tsscreateprimary -hi o -st -ecc nistp256 -opem parent.pub
+
+Then an importable key may be wrapped to the TPM via:
+
+create_tpm2_key --import parent.pub --wrap key.priv key.tpm
+
+Note that certain parameters must be assumed about a parent when it is
+wrapped, like the template (must be standard restricted decryption
+key) and the name hash (must be sha256).
+
[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-3.2.1/create_tpm2_key.c
new/openssl_tpm2_engine-3.3.1/create_tpm2_key.c
--- old/openssl_tpm2_engine-3.2.1/create_tpm2_key.c 2023-01-12
21:56:04.000000000 +0100
+++ new/openssl_tpm2_engine-3.3.1/create_tpm2_key.c 2023-01-31
17:21:01.000000000 +0100
@@ -204,141 +204,6 @@
return TPM_RC_SUCCESS;
}
-TPM_RC tpm2_outerwrap(EVP_PKEY *parent,
- TPMT_SENSITIVE *s,
- TPMT_PUBLIC *pub,
- PRIVATE_2B *p,
- ENCRYPTED_SECRET_2B *enc_secret)
-{
- PRIVATE_2B secret, seed;
- /* amount of room in the buffer for the integrity TPM2B */
- const int name_alg_size = TSS_GetDigestSize(pub->nameAlg);
- const int integrity_skip = name_alg_size + 2;
- // BYTE *integrity = p->buffer;
- BYTE *sensitive = p->buffer + integrity_skip;
- BYTE *buf;
- TPM2B *t2b;
- INT32 size;
- size_t ssize;
- UINT16 bsize, written = 0;
- EVP_PKEY *ephemeral = NULL;
- EVP_PKEY_CTX *ctx;
- TPM2B_ECC_POINT pub_pt, ephemeral_pt;
- EC_KEY *e_parent, *e_ephemeral;
- const EC_GROUP *group;
- unsigned char aeskey[T2_AES_KEY_BYTES];
- /* hmac follows namealg, so set to max size */
- KEY_2B hmackey;
- TPMT_HA hmac;
- NAME_2B name;
- DIGEST_2B digest;
- unsigned char null_iv[AES_128_BLOCK_SIZE_BYTES];
- TPM2B null_2b;
-
- null_2b.size = 0;
-
- if (EVP_PKEY_type(EVP_PKEY_id(parent)) != EVP_PKEY_EC) {
- printf("Can only currently wrap to EC parent\n");
- return TPM_RC_ASYMMETRIC;
- }
-
- e_parent = EVP_PKEY_get1_EC_KEY(parent);
- group = EC_KEY_get0_group(e_parent);
-
- /* marshal the sensitive into a TPM2B */
- t2b = (TPM2B *)sensitive;
- buf = t2b->buffer;
- size = sizeof(p->buffer) - integrity_skip;
- bsize = 0;
- TSS_TPMT_SENSITIVE_Marshal(s, &bsize, &buf, &size);
- buf = (BYTE *)&t2b->size;
- size = 2;
- TSS_UINT16_Marshal(&bsize, &written, &buf, &size);
- /* set the total size of the private entity */
- p->size = bsize + sizeof(UINT16) + integrity_skip;
-
- /* compute the elliptic curve shared (and encrypted) secret */
- ctx = EVP_PKEY_CTX_new(parent, NULL);
- if (!ctx)
- goto openssl_err;
- if (EVP_PKEY_keygen_init(ctx) != 1)
- goto openssl_err;
- EVP_PKEY_keygen(ctx, &ephemeral);
- if (!ephemeral)
- goto openssl_err;
- /* otherwise the ctx free will free the key */
-#if OPENSSL_VERSION_NUMBER < 0x10100000
- CRYPTO_add(&ephemeral->references, 1, CRYPTO_LOCK_EVP_PKEY);
-#else
- EVP_PKEY_up_ref(ephemeral);
-#endif
- EVP_PKEY_CTX_free(ctx);
-
- e_ephemeral = EVP_PKEY_get1_EC_KEY(ephemeral);
-
- /* now begin again with the ephemeral private key because the
- * context must be initialised with the private key */
- ctx = EVP_PKEY_CTX_new(ephemeral, NULL);
- if (!ctx)
- goto openssl_err;
- if (EVP_PKEY_derive_init(ctx) != 1)
- goto openssl_err;
- if (EVP_PKEY_derive_set_peer(ctx, parent) != 1)
- goto openssl_err;
- ssize = sizeof(secret.buffer);
- if (EVP_PKEY_derive(ctx, secret.buffer, &ssize) != 1)
- goto openssl_err;
- secret.size = ssize;
- EVP_PKEY_CTX_free(ctx);
-
- tpm2_get_public_point(&pub_pt, group, EC_KEY_get0_public_key(e_parent));
- tpm2_get_public_point(&ephemeral_pt, group,
- EC_KEY_get0_public_key(e_ephemeral));
- EC_KEY_free(e_parent);
- EC_KEY_free(e_ephemeral);
-
- /* now pass the secret through KDFe to get the shared secret
- * The size is the size of the parent name algorithm which we
- * assume to be sha256 */
- TSS_KDFE(seed.buffer, pub->nameAlg, (TPM2B *)&secret, "DUPLICATE",
- (TPM2B *)&ephemeral_pt.point.x, (TPM2B *)&pub_pt.point.x,
- SHA256_DIGEST_LENGTH*8);
- seed.size = SHA256_DIGEST_LENGTH;
-
- /* and finally through KDFa to get the aes symmetric encryption key */
- tpm2_ObjectPublic_GetName(&name, pub);
- TSS_KDFA(aeskey, pub->nameAlg, (TPM2B *)&seed, "STORAGE",
- (TPM2B *)&name, &null_2b, T2_AES_KEY_BITS);
- /* and then the outer HMAC key */
- hmackey.size = name_alg_size;
- TSS_KDFA(hmackey.buffer, pub->nameAlg, (TPM2B *)&seed, "INTEGRITY",
- &null_2b, &null_2b, name_alg_size * 8);
- /* OK the ephermeral public point is now the encrypted secret */
- size = sizeof(ephemeral_pt);
- buf = enc_secret->secret;
- TSS_TPM2B_ECC_POINT_Marshal(&ephemeral_pt, &written,
- &buf, &size);
- enc_secret->size = written;
- memset(null_iv, 0, sizeof(null_iv));
- TSS_AES_EncryptCFB(sensitive, T2_AES_KEY_BITS, aeskey, null_iv,
- p->size - integrity_skip, sensitive);
- hmac.hashAlg = pub->nameAlg;
- TSS_HMAC_Generate(&hmac, (TPM2B_KEY *)&hmackey,
- p->size - integrity_skip, sensitive,
- name.size, name.name,
- 0, NULL);
- digest.size = name_alg_size;
- memcpy(digest.buffer, &hmac.digest, digest.size);
- size = integrity_skip;
- buf = p->buffer;
- TSS_TPM2B_DIGEST_Marshal((TPM2B_DIGEST *)&digest, &written, &buf,
&size);
- return TPM_RC_SUCCESS;
-
- openssl_err:
- ERR_print_errors_fp(stderr);
- return TPM_RC_ASYMMETRIC;
-}
-
EVP_PKEY *
openssl_read_key(char *filename)
{
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-3.2.1/seal_tpm2_data.1.in
new/openssl_tpm2_engine-3.3.1/seal_tpm2_data.1.in
--- old/openssl_tpm2_engine-3.2.1/seal_tpm2_data.1.in 2023-01-12
21:56:04.000000000 +0100
+++ new/openssl_tpm2_engine-3.3.1/seal_tpm2_data.1.in 2023-01-31
17:21:01.000000000 +0100
@@ -21,6 +21,25 @@
sha512:1,3-5 means PCRs 1,3,4 and 5 in the sha512 bank
+[Import]
+
+In some cases, there may be a need to wrap a key without access to the
+TPM it will be use on. For these cases an importable key may be
+specified with the --import option. For this to work, you must use a
+public key corresponding exactly to the one the importing TPM will use
+(Note: only Elliptic Curve parents are currently supported). For
+instance the owner seed elliptic curve storage key may be produced as
+
+tsscreateprimary -hi o -st -ecc nistp256 -opem parent.pub
+
+Then a sealed data file may be wrapped to the TPM via:
+
+echo "data" | seal_tpm2_data --import parent.pub seal.tpm
+
+Note that certain parameters must be assumed about a parent when it is
+wrapped, like the template (must be standard restricted decryption
+key) and the name hash (must be sha256).
+
[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-3.2.1/seal_tpm2_data.c
new/openssl_tpm2_engine-3.3.1/seal_tpm2_data.c
--- old/openssl_tpm2_engine-3.2.1/seal_tpm2_data.c 2023-01-12
21:56:04.000000000 +0100
+++ new/openssl_tpm2_engine-3.3.1/seal_tpm2_data.c 2023-01-31
17:21:01.000000000 +0100
@@ -14,6 +14,7 @@
#include <openssl/evp.h>
#include <openssl/pem.h>
+#include <openssl/rand.h>
#include <openssl/ui.h>
#include "tpm2-tss.h"
@@ -35,6 +36,7 @@
{"policy", 1, 0, 'c'},
{"nomigrate", 0, 0, 'm'},
{"name-scheme", 1, 0, 'n'},
+ {"import", 1, 0, 'i'},
{0, 0, 0, 0}
};
@@ -78,7 +80,10 @@
" details about formatting\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 to authorize unsealing\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"
"\n"
"\n"
"Report bugs to " PACKAGE_BUGREPORT "\n",
@@ -86,6 +91,24 @@
exit(-1);
}
+void wrap_data(TPMT_SENSITIVE *s, const char *password, void *data,
+ int data_len)
+{
+ memset(s, 0, sizeof(*s));
+
+ s->sensitiveType = TPM_ALG_KEYEDHASH;
+ if (password) {
+ int len = strlen(password);
+
+ memcpy(VAL_2B(s->authValue, buffer), password, len);
+ VAL_2B(s->authValue, size) = len;
+ } else {
+ VAL_2B(s->authValue, size) = 0;
+ }
+ VAL_2B(s->sensitive.bits, size) = data_len;
+ memcpy(VAL_2B(s->sensitive.bits, buffer), data, data_len);
+}
+
int main(int argc, char **argv)
{
int option_index, c;
@@ -95,8 +118,8 @@
char *filename;
uint32_t noda = TPMA_OBJECT_NODA, phandle;
TPM_RC rc;
- TSS_CONTEXT *tssContext;
- const char *dir;
+ TSS_CONTEXT *tssContext = NULL;
+ const char *dir = NULL;
const char *reason = ""; /* gcc 4.8.5 gives spurious uninitialized
warning without this */
TPMT_HA digest;
uint32_t sizeInBytes;
@@ -115,15 +138,17 @@
int32_t size;
uint16_t pubkey_len, privkey_len;
char *parent_str = NULL;
+ char *import = NULL;
TPML_PCR_SELECTION pcr_lock;
int has_policy = 0;
char *signed_policy = NULL;
+ ENCRYPTED_SECRET_2B secret, *enc_secret = NULL;
pcr_lock.count = 0;
while (1) {
option_index = 0;
- c = getopt_long(argc, argv, "ak:b:hp:vdsun",
+ c = getopt_long(argc, argv, "ak:b:hp:vdsun:i:",
long_options, &option_index);
if (c == -1)
break;
@@ -182,6 +207,9 @@
case 'x':
tpm2_get_pcr_lock(&pcr_lock, optarg);
break;
+ case 'i':
+ import = optarg;
+ break;
case OPT_SIGNED_POLICY:
signed_policy = optarg;
break;
@@ -208,6 +236,11 @@
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 || signed_policy)
has_policy = 1;
@@ -254,39 +287,39 @@
tpm2_add_auth_policy(sk, &digest);
}
- dir = tpm2_set_unique_tssdir();
- rc = tpm2_create(&tssContext, dir);
- if (rc) {
- reason = "TSS_Create";
- goto out_rmdir;
- }
-
- if (pcr_lock.count != 0) {
- rc = tpm2_pcr_lock_policy(tssContext, &pcr_lock,
- sk, &digest);
+ if (!import) {
+ dir = tpm2_set_unique_tssdir();
+ rc = tpm2_create(&tssContext, dir);
if (rc) {
- reason = "create pcr policy";
- goto out_free_auth;
+ reason = "TSS_Create";
+ goto out_rmdir;
}
- }
-
- if (parent_str) {
- parent = tpm2_get_parent(tssContext, parent_str);
- if (parent == 0) {
- reason = "Invalid parent";
- goto out_delete;
+ 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) {
+ reason = "Invalid parent";
+ goto out_delete;
+ }
}
- }
- if (tpm2_handle_mso(tssContext, parent, TPM_HT_PERMANENT)) {
- rc = tpm2_load_srk(tssContext, &phandle, parent_auth,
- NULL, parent, 1);
- if (rc) {
+ if (tpm2_handle_mso(tssContext, parent, TPM_HT_PERMANENT)) {
+ rc = tpm2_load_srk(tssContext, &phandle, parent_auth,
+ NULL, parent, 1);
+ if (rc) {
reason = "tpm2_load_srk";
goto out_delete;
+ }
+ } else {
+ phandle = parent;
}
- } else {
- phandle = parent;
}
tpm2_public_template_seal(p);
@@ -321,6 +354,37 @@
TPMA_OBJECT_FIXEDPARENT |
TPMA_OBJECT_FIXEDTPM;
+ if (import) {
+ TPMT_SENSITIVE ts;
+ EVP_PKEY *p_pkey = openssl_read_public_key(import);
+
+ wrap_data(&ts, data_auth, VAL_2B(s->data, buffer),
+ VAL_2B(s->data, size));
+
+ /* random nonce for seed to add entropy to wrapping */
+ VAL_2B(ts.seedValue, size) = TSS_GetDigestSize(name_alg);
+ RAND_bytes(VAL_2B(ts.seedValue, buffer),
+ VAL_2B(ts.seedValue, size));
+
+ /* fill in the unique area as Hash(seed||key) */
+ digest.hashAlg = name_alg;
+ TSS_Hash_Generate(&digest,
+ VAL_2B(ts.seedValue, size),
+ VAL_2B(ts.seedValue, buffer),
+ VAL_2B(ts.sensitive.bits, size),
+ VAL_2B(ts.sensitive.bits, buffer),
+ 0, NULL);
+ VAL_2B(p->unique.keyedHash, size) = TSS_GetDigestSize(name_alg);
+ memcpy(VAL_2B(p->unique.keyedHash, buffer),
+ &digest.digest, VAL_2B(p->unique.keyedHash, size));
+
+ outPublic = inPublic;
+ rc = tpm2_outerwrap(p_pkey, &ts, &outPublic.publicArea,
&outPrivate, &secret);
+ if (rc)
+ goto out_flush;
+ enc_secret = &secret;
+ goto write_file;
+ }
/* use salted parameter encryption to hide the key */
rc = tpm2_get_session_handle(tssContext, &authHandle, phandle,
TPM_SE_HMAC, name_alg);
@@ -339,6 +403,9 @@
goto out_flush;
}
+ parent = tpm2_handle_ext(tssContext, parent);
+
+ write_file:
buffer = pubkey;
pubkey_len = 0;
size = sizeof(pubkey);
@@ -349,18 +416,19 @@
size = sizeof(privkey);
TSS_TPM2B_PRIVATE_Marshal((TPM2B_PRIVATE *)&outPrivate, &privkey_len,
&buffer, &size);
- parent = tpm2_handle_ext(tssContext, parent);
tpm2_write_tpmfile(filename, pubkey, pubkey_len,
privkey, privkey_len, data_auth == NULL,
- parent, sk, 2, NULL);
-
+ parent, sk, 2, enc_secret);
out_flush:
- tpm2_flush_srk(tssContext, phandle);
+ if (tssContext)
+ tpm2_flush_srk(tssContext, phandle);
out_delete:
- TSS_Delete(tssContext);
+ if (tssContext)
+ TSS_Delete(tssContext);
out_rmdir:
- rmdir(dir);
+ if (dir)
+ rmdir(dir);
out_free_auth:
free(data_auth);
out_free_policy:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-3.2.1/tests/check_importable.sh
new/openssl_tpm2_engine-3.3.1/tests/check_importable.sh
--- old/openssl_tpm2_engine-3.2.1/tests/check_importable.sh 2023-01-12
21:56:04.000000000 +0100
+++ new/openssl_tpm2_engine-3.3.1/tests/check_importable.sh 2023-01-31
17:21:01.000000000 +0100
@@ -6,21 +6,32 @@
prim=$(tsscreateprimary -ecc nistp256 -hi o -opem srk.pub | sed 's/Handle //')
|| exit 1
tssflushcontext -ha ${prim} || exit 1
-# check an EC key with a cert and password
-openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:prime256v1 -out
key.priv || exit 1
-${bindir}/create_tpm2_key --import srk.pub --wrap key.priv -a -k passw0rd
key.tpm || exit 1
-openssl req -new -x509 -subj '/CN=test/' -key key.tpm -passin pass:passw0rd
-engine tpm2 -keyform engine -out tmp.crt || exit 1
-openssl verify -CAfile tmp.crt -check_ss_sig tmp.crt || exit 1
+for n in sha1 sha256 sha384; do
+ echo "Checking Name Hash $n"
+ if [ "$n" = "sha256" ]; then
+ POLICYFILE=policies/policy_pcr.txt
+ else
+ POLICYFILE=policies/policy_pcr${n}.txt
+ fi
+ # check an EC key with a cert and password
+ openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:prime256v1 -out
key.priv || exit 1
+ ${bindir}/create_tpm2_key --import srk.pub --wrap key.priv -n ${n} -a -k
passw0rd key.tpm || exit 1
+ openssl req -new -x509 -subj '/CN=test/' -key key.tpm -passin
pass:passw0rd -engine tpm2 -keyform engine -out tmp.crt || exit 1
+ openssl verify -CAfile tmp.crt -check_ss_sig tmp.crt || exit 1
-# Check the loadability of an importable key
-NV=81000201
-${bindir}/load_tpm2_key key.tpm ${NV} || exit 1
-openssl req -new -x509 -subj '/CN=test/' -key //nvkey:${NV} -passin
pass:passw0rd -engine tpm2 -keyform engine -out tmp.crt || exit 1
-openssl verify -CAfile tmp.crt -check_ss_sig tmp.crt || exit 1
-
-#check an RSA key with a cert and policy
-openssl genrsa 2048 > key.priv || exit 1
-${bindir}/create_tpm2_key --import srk.pub --wrap key.priv -a -k passw0rd -c
policies/policy_authvalue.txt key.tpm || exit 1
-openssl req -new -x509 -subj '/CN=test/' -key key.tpm -passin pass:passw0rd
-engine tpm2 -keyform engine -out tmp.crt || exit 1
-openssl verify -CAfile tmp.crt -check_ss_sig tmp.crt || exit 1
+ # Check the loadability of an importable key
+ NV=81000201
+ ${bindir}/load_tpm2_key key.tpm ${NV} || exit 1
+ openssl req -new -x509 -subj '/CN=test/' -key //nvkey:${NV} -passin
pass:passw0rd -engine tpm2 -keyform engine -out tmp.crt || exit 1
+ openssl verify -CAfile tmp.crt -check_ss_sig tmp.crt || exit 1
+ tssevictcontrol -hi o -ho ${NV} -hp ${NV}
+ #check an RSA key with a cert and policy
+ openssl genrsa 2048 > key.priv || exit 1
+ tsspcrreset -ha 16
+ ${bindir}/create_tpm2_key --import srk.pub -n ${n} --wrap key.priv -c
${POLICYFILE} key.tpm || exit 1
+ openssl req -new -x509 -subj '/CN=test/' -key key.tpm -engine tpm2
-keyform engine -out tmp.crt && exit 1
+ tsspcrextend -ha 16 -ic aaa
+ openssl req -new -x509 -subj '/CN=test/' -key key.tpm -engine tpm2
-keyform engine -out tmp.crt || exit 1
+ openssl verify -CAfile tmp.crt -check_ss_sig tmp.crt || exit 1
+done
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-3.2.1/tests/seal_unseal.sh
new/openssl_tpm2_engine-3.3.1/tests/seal_unseal.sh
--- old/openssl_tpm2_engine-3.2.1/tests/seal_unseal.sh 2023-01-12
21:56:04.000000000 +0100
+++ new/openssl_tpm2_engine-3.3.1/tests/seal_unseal.sh 2023-01-31
17:21:01.000000000 +0100
@@ -1,37 +1,65 @@
#!/bin/bash
-set -x
bindir=${srcdir}/..
-##
-# test is
-# 1. Verify that a standard key can't be unsealed
-# 2. seal a phrase
-# 3. recover the same phrase on unseal
-##
-DATA="This is some DATA"
-AUTH="Passw0rd"
-${bindir}/create_tpm2_key key.tpm || exit 1;
-${bindir}/unseal_tpm2_data key.tpm 2> /dev/null && exit 1;
-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
+for n in sha1 sha256 sha384; do
+ echo "Checking Name Hash $n"
+ ##
+ # test is
+ # 1. Verify that a standard key can't be unsealed
+ # 2. seal a phrase
+ # 3. recover the same phrase on unseal
+ ##
+ DATA="This is some DATA $n"
+ AUTH="Passw0rd"
+ ${bindir}/create_tpm2_key key.tpm || exit 1;
+ ${bindir}/unseal_tpm2_data key.tpm 2> /dev/null && exit 1;
+ echo $DATA | ${bindir}/seal_tpm2_data -n ${n} -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 -n ${n} --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
+
+ ##
+ # Check importable
+ # test is
+ # 1. create srk.pub as parent for import
+ # 2. seal with password
+ # 3. check unseal
+ # 4. seal with policy
+ # 5. check unseal
+ # 6. update PCR and check unseal failure
+ DATA="Some Different DATA $n"
+ if [ "$n" = "sha256" ]; then
+ POLICYFILE="policies/policy_pcr.txt"
+ else
+ POLICYFILE="policies/policy_pcr${n}.txt"
+ fi
+ prim=$(tsscreateprimary -hi o -st -ecc nistp256 -opem srk.pub | sed
's/Handle //') || exit 1
+ tssflushcontext -ha $prim
+ TPM_INTERFACE_TYPE= echo $DATA | ${bindir}/seal_tpm2_data -n ${n} -a -k
${AUTH} --import srk.pub seal.tpm || exit 1;
+ ${bindir}/unseal_tpm2_data -k ${AUTH} seal.tpm | grep -q "${DATA}" || exit
1;
+ rm seal.tpm
+
+ TPM_INTERFACE_TYPE= echo $DATA | ${bindir}/seal_tpm2_data -n ${n} --import
srk.pub --policy ${POLICYFILE} seal.tpm || exit 1;
+ tsspcrreset -ha 16
+ ${bindir}/unseal_tpm2_data -k ${AUTH} seal.tpm && exit 1
+ tsspcrextend -ha 16 -ic aaa
+ ${bindir}/unseal_tpm2_data -k ${AUTH} seal.tpm | grep -q "${DATA}" || exit
1;
+done
exit 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-3.2.1/tpm2-common.c
new/openssl_tpm2_engine-3.3.1/tpm2-common.c
--- old/openssl_tpm2_engine-3.2.1/tpm2-common.c 2023-01-12 21:56:04.000000000
+0100
+++ new/openssl_tpm2_engine-3.3.1/tpm2-common.c 2023-01-31 17:21:01.000000000
+0100
@@ -1171,6 +1171,17 @@
return 0;
}
+int tpm2_curve_to_order(TPMI_ECC_CURVE curve)
+{
+ int i;
+
+ for (i = 0; tpm2_supported_curves[i].name != NULL; i++)
+ if (tpm2_supported_curves[i].curve == curve)
+ return tpm2_supported_curves[i].C[5].s;
+
+ return 0;
+}
+
TPMI_ECC_CURVE tpm2_nid_to_curve_name(int nid)
{
int i;
@@ -1773,7 +1784,7 @@
}
}
- if (strcmp(OID_importableKey, oid) == 0) {
+ if (secret) {
TPM_HANDLE session;
TPM_HANDLE parentHandle;
DATA_2B encryptionKey;
@@ -2059,12 +2070,16 @@
k.tpk.type = OBJ_txt2obj(OID_sealedData, 1);
} else if (secret) {
k.tpk.type = OBJ_txt2obj(OID_importableKey, 1);
+ } else {
+ k.tpk.type = OBJ_txt2obj(OID_loadableKey, 1);
+ }
+
+ if (secret) {
k.tpk.secret = ASN1_OCTET_STRING_new();
ASN1_STRING_set(k.tpk.secret, secret->secret,
secret->size);
- } else {
- k.tpk.type = OBJ_txt2obj(OID_loadableKey, 1);
}
+
k.tpk.emptyAuth = empty_auth;
k.tpk.parent = ASN1_INTEGER_new();
ASN1_INTEGER_set(k.tpk.parent, parent);
@@ -2691,6 +2706,7 @@
TPM_RC rc = TPM_RC_CURVE;
BN_CTX *ctx = NULL;
BIGNUM *x, *y;
+ int order;
if (curve == TPM_ECC_NONE) {
fprintf(stderr, "TPM does not support the curve in this EC
key\n");
@@ -2722,10 +2738,11 @@
goto err;
}
+ order = tpm2_curve_to_order(curve);
VAL_2B(pub->unique.ecc.x, size) =
- BN_bn2bin(x, VAL_2B(pub->unique.ecc.x, buffer));
+ BN_bn2binpad(x, VAL_2B(pub->unique.ecc.x, buffer), order);
VAL_2B(pub->unique.ecc.y, size) =
- BN_bn2bin(y, VAL_2B(pub->unique.ecc.y, buffer));
+ BN_bn2binpad(y, VAL_2B(pub->unique.ecc.y, buffer), order);
rc = TPM_RC_SUCCESS;
@@ -2795,6 +2812,140 @@
return TPM_RC_ASYMMETRIC;
}
+TPM_RC tpm2_outerwrap(EVP_PKEY *parent,
+ TPMT_SENSITIVE *s,
+ TPMT_PUBLIC *pub,
+ PRIVATE_2B *p,
+ ENCRYPTED_SECRET_2B *enc_secret)
+{
+ PRIVATE_2B secret, seed;
+ /* amount of room in the buffer for the integrity TPM2B */
+ const int integrity_skip = SHA256_DIGEST_LENGTH + 2;
+ // BYTE *integrity = p->buffer;
+ BYTE *sensitive = p->buffer + integrity_skip;
+ BYTE *buf;
+ TPM2B *t2b;
+ INT32 size;
+ size_t ssize;
+ UINT16 bsize, written = 0;
+ EVP_PKEY *ephemeral = NULL;
+ EVP_PKEY_CTX *ctx;
+ TPM2B_ECC_POINT pub_pt, ephemeral_pt;
+ EC_KEY *e_parent, *e_ephemeral;
+ const EC_GROUP *group;
+ unsigned char aeskey[T2_AES_KEY_BYTES];
+ /* hmac follows namealg, so set to max size */
+ KEY_2B hmackey;
+ TPMT_HA hmac;
+ NAME_2B name;
+ DIGEST_2B digest;
+ unsigned char null_iv[AES_128_BLOCK_SIZE_BYTES];
+ TPM2B null_2b;
+
+ null_2b.size = 0;
+
+ if (EVP_PKEY_type(EVP_PKEY_id(parent)) != EVP_PKEY_EC) {
+ printf("Can only currently wrap to EC parent\n");
+ return TPM_RC_ASYMMETRIC;
+ }
+
+ e_parent = EVP_PKEY_get1_EC_KEY(parent);
+ group = EC_KEY_get0_group(e_parent);
+
+ /* marshal the sensitive into a TPM2B */
+ t2b = (TPM2B *)sensitive;
+ buf = t2b->buffer;
+ size = sizeof(p->buffer) - integrity_skip;
+ bsize = 0;
+ TSS_TPMT_SENSITIVE_Marshal(s, &bsize, &buf, &size);
+ buf = (BYTE *)&t2b->size;
+ size = 2;
+ TSS_UINT16_Marshal(&bsize, &written, &buf, &size);
+ /* set the total size of the private entity */
+ p->size = bsize + sizeof(UINT16) + integrity_skip;
+
+ /* compute the elliptic curve shared (and encrypted) secret */
+ ctx = EVP_PKEY_CTX_new(parent, NULL);
+ if (!ctx)
+ goto openssl_err;
+ if (EVP_PKEY_keygen_init(ctx) != 1)
+ goto openssl_err;
+ EVP_PKEY_keygen(ctx, &ephemeral);
+ if (!ephemeral)
+ goto openssl_err;
+ /* otherwise the ctx free will free the key */
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+ CRYPTO_add(&ephemeral->references, 1, CRYPTO_LOCK_EVP_PKEY);
+#else
+ EVP_PKEY_up_ref(ephemeral);
+#endif
+ EVP_PKEY_CTX_free(ctx);
+
+ e_ephemeral = EVP_PKEY_get1_EC_KEY(ephemeral);
+
+ /* now begin again with the ephemeral private key because the
+ * context must be initialised with the private key */
+ ctx = EVP_PKEY_CTX_new(ephemeral, NULL);
+ if (!ctx)
+ goto openssl_err;
+ if (EVP_PKEY_derive_init(ctx) != 1)
+ goto openssl_err;
+ if (EVP_PKEY_derive_set_peer(ctx, parent) != 1)
+ goto openssl_err;
+ ssize = sizeof(secret.buffer);
+ if (EVP_PKEY_derive(ctx, secret.buffer, &ssize) != 1)
+ goto openssl_err;
+ secret.size = ssize;
+ EVP_PKEY_CTX_free(ctx);
+
+ tpm2_get_public_point(&pub_pt, group, EC_KEY_get0_public_key(e_parent));
+ tpm2_get_public_point(&ephemeral_pt, group,
+ EC_KEY_get0_public_key(e_ephemeral));
+ EC_KEY_free(e_parent);
+ EC_KEY_free(e_ephemeral);
+
+ /* now pass the secret through KDFe to get the shared secret
+ * The size is the size of the parent name algorithm which we
+ * assume to be sha256 */
+ TSS_KDFE(seed.buffer, TPM_ALG_SHA256, (TPM2B *)&secret, "DUPLICATE",
+ (TPM2B *)&ephemeral_pt.point.x, (TPM2B *)&pub_pt.point.x,
+ SHA256_DIGEST_LENGTH*8);
+ seed.size = SHA256_DIGEST_LENGTH;
+
+ /* and finally through KDFa to get the aes symmetric encryption key */
+ tpm2_ObjectPublic_GetName(&name, pub);
+ TSS_KDFA(aeskey, TPM_ALG_SHA256, (TPM2B *)&seed, "STORAGE",
+ (TPM2B *)&name, &null_2b, T2_AES_KEY_BITS);
+ /* and then the outer HMAC key */
+ hmackey.size = SHA256_DIGEST_LENGTH;
+ TSS_KDFA(hmackey.buffer, TPM_ALG_SHA256, (TPM2B *)&seed, "INTEGRITY",
+ &null_2b, &null_2b, SHA256_DIGEST_LENGTH*8);
+ /* OK the ephermeral public point is now the encrypted secret */
+ size = sizeof(ephemeral_pt);
+ buf = enc_secret->secret;
+ TSS_TPM2B_ECC_POINT_Marshal(&ephemeral_pt, &written,
+ &buf, &size);
+ enc_secret->size = written;
+ memset(null_iv, 0, sizeof(null_iv));
+ TSS_AES_EncryptCFB(sensitive, T2_AES_KEY_BITS, aeskey, null_iv,
+ p->size - integrity_skip, sensitive);
+ hmac.hashAlg = TPM_ALG_SHA256;
+ TSS_HMAC_Generate(&hmac, (TPM2B_KEY *)&hmackey,
+ p->size - integrity_skip, sensitive,
+ name.size, name.name,
+ 0, NULL);
+ digest.size = SHA256_DIGEST_LENGTH;
+ memcpy(digest.buffer, &hmac.digest, digest.size);
+ size = integrity_skip;
+ buf = p->buffer;
+ TSS_TPM2B_DIGEST_Marshal((TPM2B_DIGEST *)&digest, &written, &buf,
&size);
+ return TPM_RC_SUCCESS;
+
+ openssl_err:
+ ERR_print_errors_fp(stderr);
+ return TPM_RC_ASYMMETRIC;
+}
+
void
openssl_print_errors()
{
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-3.2.1/tpm2-common.h
new/openssl_tpm2_engine-3.3.1/tpm2-common.h
--- old/openssl_tpm2_engine-3.2.1/tpm2-common.h 2023-01-12 21:56:04.000000000
+0100
+++ new/openssl_tpm2_engine-3.3.1/tpm2-common.h 2023-01-31 17:21:01.000000000
+0100
@@ -115,4 +115,9 @@
TPMT_HA *digest);
TPM_RC tpm2_new_signed_policy(char *tpmkey, char *policykey, char *engine,
TSSAUTHPOLICY *ap, TPMT_HA *digest);
+TPM_RC tpm2_outerwrap(EVP_PKEY *parent,
+ TPMT_SENSITIVE *s,
+ TPMT_PUBLIC *pub,
+ PRIVATE_2B *p,
+ ENCRYPTED_SECRET_2B *enc_secret);
#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openssl_tpm2_engine-3.2.1/unseal_tpm2_data.c
new/openssl_tpm2_engine-3.3.1/unseal_tpm2_data.c
--- old/openssl_tpm2_engine-3.2.1/unseal_tpm2_data.c 2023-01-12
21:56:04.000000000 +0100
+++ new/openssl_tpm2_engine-3.3.1/unseal_tpm2_data.c 2023-01-31
17:21:01.000000000 +0100
@@ -142,6 +142,8 @@
goto out_free_app_data;
}
+ name_alg = app_data->name_alg;
+
itemHandle = rc;
rc = tpm2_get_session_handle(tssContext, &session, parent,