diff options
author | James Bottomley <James.Bottomley@HansenPartnership.com> | 2020-03-03 12:35:54 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2020-03-04 07:53:44 -0800 |
commit | 686f8f78e5604d55018c7ef819a59c9ea819e890 (patch) | |
tree | 3448d170780e5f8fec4d9e744c1845629e62daf7 | |
parent | 51f575dbf48a3bed907fca66f4db10beb81f9301 (diff) | |
download | openssl_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.c | 37 | ||||
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rwxr-xr-x | tests/wrap_pkcs12.sh | 22 |
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 |