Skip to content

Commit

Permalink
Add: import of TPM keys
Browse files Browse the repository at this point in the history
Signed-off-by: Andreas Fuchs <[email protected]>
  • Loading branch information
Andreas Fuchs authored and t-higuchi committed Aug 28, 2019
1 parent d04c6ec commit 32f53d7
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 5 deletions.
2 changes: 2 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ TESTS_SHELL = test/ecdsa.sh \
test/rsasign.sh \
test/failload.sh \
test/failwrite.sh \
test/rsasign_importtpm.sh \
test/rsasign_importtpmparent.sh \
test/rsasign_parent.sh \
test/rsasign_parent_pass.sh \
test/rsasign_persistent.sh \
Expand Down
5 changes: 5 additions & 0 deletions include/tpm2-tss-engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ tpm2tss_tpm2data_read(const char *filename, TPM2_DATA **tpm2Datap);
int
tpm2tss_tpm2data_readtpm(uint32_t handle, TPM2_DATA **tpm2Datap);

int
tpm2tss_tpm2data_importtpm(const char *filenamepub, const char *filenametpm,
TPM2_HANDLE parent, int emptyAuth,
TPM2_DATA **tpm2Datap);

EVP_PKEY *
tpm2tss_rsa_makekey(TPM2_DATA *tpm2Data);

Expand Down
8 changes: 7 additions & 1 deletion man/tpm2tss-genkey.1.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
% tpm2tss-genkey(1) tpm2-tss-engine | General Commands Manual
%
% JUNE 2018
% MARCH 2019

# NAME
**tpm2tss-genkey**(1) -- generate TPM keys for tpm2-tss-engine
Expand Down Expand Up @@ -29,6 +29,12 @@ key information. This file can then be loaded with OpenSSL using
* `-c <curve>`, `--curve <curve>`:
If alg ecdsa is chosen, the curve for ecc (default: nist_p256)

* `-i <file>`, `--importpub <file>`:
Public key (TPM2B_PUBLIC) to be imported. Requires `-k`.

* `-k <file>`, `--importtpm <file>`:
The (encrypted) private key (TPM2B_PRIVATE) to be imported.

* `-e <exponent>`, `--exponent <exponent>`:
If alg rsa is chosen, the exponent for rsa (default: 65537)

Expand Down
70 changes: 70 additions & 0 deletions src/tpm2-tss-engine-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -596,3 +596,73 @@ init_tpm_key (ESYS_AUXCONTEXT *eactx_p, ESYS_TR *keyHandle, TPM2_DATA *tpm2Data)
esys_auxctx_free(eactx_p);
return r;
}

/** Deserialize a tpm key from disk
*
* Read a tpm key as marshaled TPM2B_PUBLIC and (encrypted) TPM2B_PRIVATE from
* disk and convert them into a TPM2_DATA representation
* @param filename The filename to read the data from.
* @param tpm2Datap The data after read.
* @retval 1 on success
* @retval 0 on failure
*/
//TODO: all the Errors !!!
int
tpm2tss_tpm2data_importtpm(const char *filenamepub, const char *filenametpm,
TPM2_HANDLE parent, int emptyAuth,
TPM2_DATA **tpm2Datap)
{
TSS2_RC r;
BIO *bio;
TPM2_DATA *tpm2data;
int filepub_size, filepriv_size;

uint8_t filepub[sizeof(TPM2B_PUBLIC)];
uint8_t filepriv[sizeof(TPM2B_PRIVATE)];

if ((bio = BIO_new_file(filenamepub, "r")) == NULL) {
ERR(tpm2tss_tpm2data_read, TPM2TSS_R_FILE_READ);
return 0;
}
filepub_size = BIO_read(bio, &filepub[0], sizeof(filepub));
BIO_free(bio);
if (filepub_size < 0) {
ERR(tpm2tss_tpm2data_read, TPM2TSS_R_FILE_READ);
return 0;
}

if ((bio = BIO_new_file(filenametpm, "r")) == NULL) {
ERR(tpm2tss_tpm2data_read, TPM2TSS_R_FILE_READ);
return 0;
}
filepriv_size = BIO_read(bio, &filepriv[0], sizeof(filepriv));
BIO_free(bio);
if (filepriv_size < 0) {
ERR(tpm2tss_tpm2data_read, TPM2TSS_R_FILE_READ);
return 0;
}

tpm2data = OPENSSL_malloc(sizeof(TPM2_DATA));
if (!tpm2data)
return 0;

memset(tpm2data, 0, sizeof(*tpm2data));
tpm2data->privatetype = KEY_TYPE_BLOB;
tpm2data->parent = parent;
tpm2data->emptyAuth = emptyAuth;

r = Tss2_MU_TPM2B_PUBLIC_Unmarshal(&filepub[0], filepub_size, NULL,
&tpm2data->pub);
ERRchktss(tpm2tss_tpm2data_read, r, goto error);

r = Tss2_MU_TPM2B_PRIVATE_Unmarshal(&filepriv[0], filepriv_size, NULL,
&tpm2data->priv);
ERRchktss(tpm2tss_tpm2data_read, r, goto error);

*tpm2Datap = tpm2data;
return 1;

error:
free(tpm2data);
return 0;
}
35 changes: 31 additions & 4 deletions src/tpm2tss-genkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ char *help =
" -c, --curve curve for ecc (default: nist_p256)\n"
" -e, --exponent exponent for rsa (default: 65537)\n"
" -h, --help print help\n"
" -i, --importpub Import a key and read its public portion from this file\n"
" -k, --importtpm Read a TPM private key from this file for import\n"
" -o, --ownerpw password for the owner hierarchy (default: none)\n"
" -p, --password password for the created key (default: none)\n"
" -P, --parent specific handle for the parent key (default: none)\n"
Expand All @@ -62,13 +64,15 @@ char *help =
" -W, --parentpw password for the parent key (default: none)\n"
"\n";

static const char *optstr = "a:c:e:ho:p:P:s:vW:";
static const char *optstr = "a:c:e:hi:k:o:p:P:s:vW:";

static const struct option long_options[] = {
{"alg", required_argument, 0, 'a'},
{"curve", required_argument, 0, 'c'},
{"exponent", required_argument, 0, 'e'},
{"help", no_argument, 0, 'h'},
{"importpub",required_argument, 0, 'i'},
{"importtpm",required_argument, 0, 'k'},
{"ownerpw", required_argument, 0, 'o'},
{"password", required_argument, 0, 'p'},
{"parent", required_argument, 0, 'P'},
Expand All @@ -83,6 +87,8 @@ static struct opt {
TPMI_ALG_PUBLIC alg;
TPMI_ECC_CURVE curve;
int exponent;
char *importpub;
char *importtpm;
char *ownerpw;
char *password;
TPM2_HANDLE parent;
Expand All @@ -108,6 +114,8 @@ parse_opts(int argc, char **argv)
opt.alg = TPM2_ALG_RSA;
opt.curve = TPM2_ECC_NIST_P256;
opt.exponent = 65537;
opt.importpub = NULL;
opt.importtpm = NULL;
opt.ownerpw = NULL;
opt.password = NULL;
opt.parent = 0;
Expand Down Expand Up @@ -155,6 +163,12 @@ parse_opts(int argc, char **argv)
exit(1);
}
break;
case 'i':
opt.importpub = optarg;
break;
case 'k':
opt.importtpm = optarg;
break;
case 'o':
opt.ownerpw = optarg;
break;
Expand Down Expand Up @@ -199,6 +213,12 @@ parse_opts(int argc, char **argv)
ERR("%s", help);
exit(1);
}

if (opt.importpub && !opt.importtpm) {
ERR("--importpub requires --importtpm");
return 1;
}

return 0;
}

Expand Down Expand Up @@ -301,6 +321,7 @@ main(int argc, char **argv)
if (parse_opts(argc, argv) != 0)
exit(1);

int r;
TPM2_DATA *tpm2Data = NULL;

/* Initialize the tpm2-tss engine */
Expand Down Expand Up @@ -331,13 +352,19 @@ main(int argc, char **argv)
return 1;
}

/* Generate the key */
VERB("Generating the key\n");
switch (opt.alg) {
if (opt.importpub && opt.importtpm) {
VERB("Importing the TPM key\n");
r = tpm2tss_tpm2data_importtpm(opt.importpub, opt.importtpm, opt.parent,
opt.password == NULL, &tpm2Data);
if (r != 1)
return 1;
} else switch (opt.alg) {
case TPM2_ALG_RSA:
VERB("Generating the rsa key\n");
tpm2Data = genkey_rsa();
break;
case TPM2_ALG_ECDSA:
VERB("Generating the ecdsa key\n");
tpm2Data = genkey_ecdsa();
break;
default:
Expand Down
36 changes: 36 additions & 0 deletions test/rsasign_importtpm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/bash

set -eufx

DIR=$(mktemp -d)
TPM_RSA_PUBKEY=${DIR}/rsakey.pub
TPM_RSA_KEY=${DIR}/rsakey
PARENT_CTX=${DIR}/primary_owner_key.ctx

echo -n "abcde12345abcde12345">${DIR}/mydata

tpm2_startup -c || true

# Create primary key as persistent handle
tpm2_createprimary --hierarchy=o -g sha256 -G ecc --context=${PARENT_CTX} --object-attributes=decrypt\|fixedtpm\|fixedparent\|sensitivedataorigin\|userwithauth\|noda\|restricted
tpm2_flushcontext -t

# Create an RSA key pair
echo "Generating RSA key pair"
tpm2_create --pwdk=abc --context-parent=${PARENT_CTX} -g sha256 -G rsa \
--pubfile=${TPM_RSA_PUBKEY} --privfile=${TPM_RSA_KEY} \
--object-attributes=sign\|decrypt\|fixedtpm\|fixedparent\|sensitivedataorigin\|userwithauth\|noda
tpm2_flushcontext -t

tpm2tss-genkey -i ${TPM_RSA_PUBKEY} -k ${TPM_RSA_KEY} -p abc ${DIR}/mykey

echo "abc" | openssl rsa -engine tpm2tss -inform engine -in ${DIR}/mykey -pubout -outform pem -out ${DIR}/mykey.pub -passin stdin

echo "abc" | openssl pkeyutl -engine tpm2tss -keyform engine -inkey ${DIR}/mykey -sign -in ${DIR}/mydata -out ${DIR}/mysig -passin stdin

#this is a workaround because -verify allways exits 1
R="$(openssl pkeyutl -pubin -inkey ${DIR}/mykey.pub -verify -in ${DIR}/mydata -sigfile ${DIR}/mysig || true)"
if ! echo $R | grep "Signature Verified Successfully" >/dev/null; then
echo $R
exit 1
fi
44 changes: 44 additions & 0 deletions test/rsasign_importtpmparent.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/bash

set -eufx

DIR=$(mktemp -d)
TPM_RSA_PUBKEY=${DIR}/rsakey.pub
TPM_RSA_KEY=${DIR}/rsakey
PARENT_CTX=${DIR}/primary_owner_key.ctx

echo -n "abcde12345abcde12345">${DIR}/mydata

tpm2_startup -c || true

# Create primary key as persistent handle
tpm2_createprimary --hierarchy=o -g sha256 -G rsa --context=${PARENT_CTX}
tpm2_flushcontext -t
#tpm2_evictcontrol --auth=o --context=${PARENT_CTX} --persistent 0x81010003
#tpm2_evictcontrol --auth=o --handle 0x81010003 --persistent 0x81010003
#tpm2_flushcontext -t
HANDLE=$(tpm2_evictcontrol --auth=o --context=${PARENT_CTX} --persistent 0x81010003 | cut -d ' ' -f 2)
tpm2_flushcontext -t

# Create an RSA key pair
echo "Generating RSA key pair"
tpm2_create --pwdk=abc --parent=${HANDLE} -g sha256 -G rsa \
--pubfile=${TPM_RSA_PUBKEY} --privfile=${TPM_RSA_KEY} \
--object-attributes=sign\|decrypt\|fixedtpm\|fixedparent\|sensitivedataorigin\|userwithauth\|noda
tpm2_flushcontext -t

tpm2tss-genkey -i ${TPM_RSA_PUBKEY} -k ${TPM_RSA_KEY} -p abc -P ${HANDLE} ${DIR}/mykey

echo "abc" | openssl rsa -engine tpm2tss -inform engine -in ${DIR}/mykey -pubout -outform pem -out ${DIR}/mykey.pub -passin stdin

echo "abc" | openssl pkeyutl -engine tpm2tss -keyform engine -inkey ${DIR}/mykey -sign -in ${DIR}/mydata -out ${DIR}/mysig -passin stdin

# Release persistent HANDLE
tpm2_evictcontrol --auth=o --handle 0x81010003 --persistent 0x81010003

#this is a workaround because -verify allways exits 1
R="$(openssl pkeyutl -pubin -inkey ${DIR}/mykey.pub -verify -in ${DIR}/mydata -sigfile ${DIR}/mysig || true)"
if ! echo $R | grep "Signature Verified Successfully" >/dev/null; then
echo $R
exit 1
fi

0 comments on commit 32f53d7

Please sign in to comment.