aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2020-03-03 12:35:54 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2020-03-04 07:53:44 -0800
commit686f8f78e5604d55018c7ef819a59c9ea819e890 (patch)
tree3448d170780e5f8fec4d9e744c1845629e62daf7
parent51f575dbf48a3bed907fca66f4db10beb81f9301 (diff)
downloadopenssl_tpm2_engine-686f8f78e5604d55018c7ef819a59c9ea819e890.tar.gz
Add ability to import PKCS12 keys
PKCS12 is a fairly common key wrapping protocol, particularly used by Microsoft, so add the ability to wrap PKCS12 keys. The wrap merely searches the PKCS12 bag for the private key, ignores all the certificates and produces a TPM wrapped version of the private key it finds. We can discriminate easily between PKCS12 and PEM private keys because the PKCS12 DER is a very specific ASN.1 format, so we don't need to know what type of keyfile we have, we just try both formats to see if it will import. Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--create_tpm2_key.c37
-rw-r--r--tests/Makefile.am1
-rwxr-xr-xtests/wrap_pkcs12.sh22
3 files changed, 59 insertions, 1 deletions
diff --git a/create_tpm2_key.c b/create_tpm2_key.c
index 11b2086..8e1a81f 100644
--- a/create_tpm2_key.c
+++ b/create_tpm2_key.c
@@ -19,6 +19,7 @@
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/err.h>
+#include <openssl/pkcs12.h>
#include <openssl/rand.h>
#define TSSINCLUDE(x) < TSS_INCLUDE/x >
@@ -85,7 +86,9 @@ usage(char *argv0)
"\t platform, storage, null or endorsement\n"
"\t respectively\n"
"\t-v, --version print package version\n"
- "\t-w, --wrap <file> wrap an existing openssl PEM key\n"
+ "\t-w, --wrap <file> wrap an existing openssl PEM key. <file> can\n"
+ " be in either PKCS12 or OpenSSL standard PEM\n"
+ " private key form (PKCS1 or PKCS8)\n"
"\t-k, --password <pwd> use this password instead of prompting\n"
"\t-r, --rsa create an RSA key (the default)\n"
"\t-e, --ecc <curve> Create an ECC key using the specified curve.\n"
@@ -385,6 +388,7 @@ openssl_read_key(char *filename)
{
BIO *b = NULL;
EVP_PKEY *pkey;
+ PKCS12 *p12;
b = BIO_new_file(filename, "r");
if (b == NULL) {
@@ -392,10 +396,41 @@ openssl_read_key(char *filename)
return NULL;
}
+ p12 = d2i_PKCS12_bio(b, NULL);
+ if (p12) {
+ const char *pass;
+ char buf[PEM_BUFSIZE];
+ if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0)) {
+ pass = "";
+ } else {
+ int len;
+
+ len = PEM_def_callback(buf, sizeof(buf), 0, NULL);
+ if (len < 0) {
+ fprintf(stderr, "Getting password for pkcs12 failed.\n");
+ openssl_print_errors();
+ goto out;
+ }
+ buf[len] = '\0';
+ pass = buf;
+ }
+ PKCS12_parse(p12, pass, &pkey, NULL, NULL);
+ if (!pkey) {
+ fprintf(stderr, "pkcs12 parsing failure.\n");
+ openssl_print_errors();
+ }
+ goto out;
+ }
+
+ /* must be plain PEM private key, so reset everything */
+ ERR_clear_error();
+ BIO_reset(b);
+
if ((pkey = PEM_read_bio_PrivateKey(b, NULL, PEM_def_callback, NULL)) == NULL) {
fprintf(stderr, "Reading key %s from disk failed.\n", filename);
openssl_print_errors();
}
+ out:
BIO_free(b);
return pkey;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 60c3e8d..742464f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -12,6 +12,7 @@ TESTS = fail_connect.sh \
create_ecc.sh \
wrap_ecc.sh \
wrap_generic_ecc.sh \
+ wrap_pkcs12.sh \
derive_ecc.sh \
create_non_tpm_keys.sh \
da_check.sh \
diff --git a/tests/wrap_pkcs12.sh b/tests/wrap_pkcs12.sh
new file mode 100755
index 0000000..57b0477
--- /dev/null
+++ b/tests/wrap_pkcs12.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+bindir=${srcdir}/..
+
+##
+# test is
+# 1. Create an openssl private key and self signed cert in pkcs12 bag
+# 2. Wrap the pkcs12 to an internal TPM private key
+# 3. create a new non CA cert with key and sign it with the TPM private key
+# 4. verify the signature
+
+openssl ecparam -genkey -name prime256v1 > tmp.param || exit 1
+openssl genpkey -paramfile tmp.param -out key.priv || exit 1
+openssl req -new -x509 -subj '/CN=test CA/' -key key.priv -out tmp.crt || exit 1
+openssl pkcs12 -out tmp.p12 -passout pass: -export -inkey key.priv -in tmp.crt
+
+${bindir}/create_tpm2_key -w tmp.p12 key.tpm || exit 1
+
+openssl req -new -newkey rsa:2048 -keyout key1.priv -subj '/CN=test intermediate/' -out tmp1.csr -nodes || exit 1
+openssl x509 -req -in tmp1.csr -CA tmp.crt -CAkey key.tpm -CAkeyform engine -engine tpm2 -set_serial 1 -out tmp1.crt -days 365 || exit 1
+
+openssl verify -CAfile tmp.crt tmp1.crt || exit 1