diff options
author | James Bottomley <James.Bottomley@HansenPartnership.com> | 2019-12-30 18:42:38 -0800 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2020-01-10 12:26:45 -0800 |
commit | 5ea29a4dba5083b5383929b895df32c9c7580d71 (patch) | |
tree | f37d3264e44d1be866bd3c680652d36cbb2f5f2a | |
parent | 48ee8aab42fa4fbfe59a8877527e1d78e562352d (diff) | |
download | openssl_tpm2_engine-5ea29a4dba5083b5383929b895df32c9c7580d71.tar.gz |
tpm2-common.c: move several routines into common code
These routines will be used by the seal/unseal command, so make them
common to facilitate this.
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r-- | create_tpm2_key.c | 247 | ||||
-rw-r--r-- | tpm2-common.c | 231 | ||||
-rw-r--r-- | tpm2-common.h | 13 |
3 files changed, 250 insertions, 241 deletions
diff --git a/create_tpm2_key.c b/create_tpm2_key.c index 5534fe3..11b2086 100644 --- a/create_tpm2_key.c +++ b/create_tpm2_key.c @@ -12,14 +12,9 @@ #include <strings.h> #include <errno.h> #include <unistd.h> -#include <fcntl.h> -#include <ctype.h> #include <arpa/inet.h> -#include <sys/stat.h> -#include <sys/mman.h> - #include <openssl/rsa.h> #include <openssl/pem.h> #include <openssl/evp.h> @@ -37,10 +32,6 @@ #include "tpm2-asn.h" #include "tpm2-common.h" -/* for use as a TPM_RC return type to indicate this is - * not a TPM error, so don't process the rc as one */ -#define NOT_TPM_ERROR (0xffffffff) - #define OPT_DEPRECATED 0x1ff #define OPT_RESTRICTED 0x1fe @@ -121,31 +112,6 @@ openssl_print_errors() ERR_print_errors_fp(stderr); } -/* from lib/hexdump.c (Linux kernel) */ -int hex_to_bin(char ch) -{ - if ((ch >= '0') && (ch <= '9')) - return ch - '0'; - ch = tolower(ch); - if ((ch >= 'a') && (ch <= 'f')) - return ch - 'a' + 10; - return -1; -} - -int hex2bin(unsigned char *dst, const char *src, size_t count) -{ - while (count--) { - int hi = hex_to_bin(*src++); - int lo = hex_to_bin(*src++); - - if ((hi < 0) || (lo < 0)) - return -1; - - *dst++ = (hi << 4) | lo; - } - return 0; -} - TPM_RC tpm2_ObjectPublic_GetName(TPM2B_NAME *name, TPMT_PUBLIC *tpmtPublic) { @@ -414,167 +380,6 @@ TPM_RC tpm2_outerwrap(EVP_PKEY *parent, return TPM_RC_ASYMMETRIC; } -TPM_RC -parse_policy_file(const char *policy_file, STACK_OF(TSSOPTPOLICY) *sk, - char *auth, TPMT_HA *digest) -{ - struct stat st; - char *data, *data_ptr; - unsigned char buf[2048]; - unsigned char *buf_ptr; - TSSOPTPOLICY *policy = NULL; - INT32 buf_len; - TPM_CC code; - TPM_RC rc = NOT_TPM_ERROR; - int fd, policy_auth_value = 0; - - if (stat(policy_file, &st) == -1) { - fprintf(stderr, "File %s cannot be accessed\n", policy_file); - return rc; - } - - fd = open(policy_file, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "File %s cannot be opened\n", policy_file); - return rc; - } - - data = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, - MAP_PRIVATE, fd, 0); - if (!data) { - fprintf(stderr, "mmap() failed\n"); - goto out; - } - - while ((data_ptr = strsep(&data, "\n"))) { - TPMT_HA hash_digest; - unsigned char *hash = (unsigned char *)hash_digest.digest.tssmax; - INT32 hash_len; - - buf_ptr = buf; - buf_len = strlen(data_ptr) / 2; - if (buf_len > sizeof(buf)) { - rc = NOT_TPM_ERROR; - fprintf(stderr, "line too long\n"); - goto out_munmap; - } - - if (!buf_len) - break; - - rc = hex2bin(buf, data_ptr, buf_len); - if (rc < 0) { - rc = NOT_TPM_ERROR; - fprintf(stderr, "hex2bin() failed\n"); - goto out_munmap; - } - - rc = TPM_CC_Unmarshal(&code, &buf_ptr, &buf_len); - if (rc) { - fprintf(stderr, "TPM_CC_Unmarshal() failed\n"); - goto out_munmap; - } - - if (code == TPM_CC_PolicyCounterTimer) { - /* for a countertimer, the policy is a hash of the hash */ - hash_digest.hashAlg = digest->hashAlg; - hash_len = TSS_GetDigestSize(digest->hashAlg); - TSS_Hash_Generate(&hash_digest, buf_len, buf_ptr, 0, NULL); - hash = hash_digest.digest.tssmax; - } else { - hash = buf_ptr; - hash_len = buf_len; - } - - rc = TSS_Hash_Generate(digest, - TSS_GetDigestSize(digest->hashAlg), - (uint8_t *)&digest->digest, - /* the command code */ - 4, buf_ptr - 4, - hash_len, hash, 0, NULL); - if (rc) { - fprintf(stderr, "TSS_Hash_Generate() failed\n"); - goto out_munmap; - } - - if (code == TPM_CC_PolicyAuthValue) - policy_auth_value = 1; - - policy = TSSOPTPOLICY_new(); - ASN1_INTEGER_set(policy->CommandCode, code); - ASN1_STRING_set(policy->CommandPolicy, buf_ptr, buf_len); - sk_TSSOPTPOLICY_push(sk, policy); - } - - if (auth && !policy_auth_value) { - rc = NOT_TPM_ERROR; - fprintf(stderr, "PolicyAuthValue command is required\n"); - } - -out_munmap: - munmap(data, st.st_size); -out: - close(fd); - return rc; -} - -int -openssl_write_tpmfile(const char *file, BYTE *pubkey, int pubkey_len, - BYTE *privkey, int privkey_len, int empty_auth, - TPM_HANDLE parent, STACK_OF(TSSOPTPOLICY) *sk, - int version, TPM2B_ENCRYPTED_SECRET *secret) -{ - union { - TSSLOADABLE tssl; - TSSPRIVKEY tpk; - } k; - BIO *outb; - - /* clear structure so as not to have to set optional parameters */ - memset(&k, 0, sizeof(k)); - if ((outb = BIO_new_file(file, "w")) == NULL) { - fprintf(stderr, "Error opening file for write: %s\n", file); - return 1; - } - if (version == 0) { - k.tssl.type = OBJ_txt2obj(OID_OldloadableKey, 1); - k.tssl.emptyAuth = empty_auth; - k.tssl.parent = ASN1_INTEGER_new(); - ASN1_INTEGER_set(k.tssl.parent, parent); - - k.tssl.pubkey = ASN1_OCTET_STRING_new(); - ASN1_STRING_set(k.tssl.pubkey, pubkey, pubkey_len); - k.tssl.privkey = ASN1_OCTET_STRING_new(); - ASN1_STRING_set(k.tssl.privkey, privkey, privkey_len); - k.tssl.policy = sk; - - PEM_write_bio_TSSLOADABLE(outb, &k.tssl); - } else { - if (secret) { - k.tpk.type = OBJ_txt2obj(OID_importableKey, 1); - k.tpk.secret = ASN1_OCTET_STRING_new(); - ASN1_STRING_set(k.tpk.secret, secret->t.secret, - secret->t.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); - - k.tpk.pubkey = ASN1_OCTET_STRING_new(); - ASN1_STRING_set(k.tpk.pubkey, pubkey, pubkey_len); - k.tpk.privkey = ASN1_OCTET_STRING_new(); - ASN1_STRING_set(k.tpk.privkey, privkey, privkey_len); - k.tpk.policy = sk; - - PEM_write_bio_TSSPRIVKEY(outb, &k.tpk); - } - - BIO_free(outb); - return 0; -} - EVP_PKEY * openssl_read_key(char *filename) { @@ -901,44 +706,6 @@ static void list_curves(void) exit(1); } -static TPM_HANDLE get_parent(const char *pstr) -{ - TPM_HANDLE p; - - if (strcmp(pstr, "owner") == 0) - p = TPM_RH_OWNER; - else if (strcmp(pstr, "platform") == 0) - p = TPM_RH_PLATFORM; - else if (strcmp(pstr, "endorsement") == 0) - p = TPM_RH_ENDORSEMENT; - else if (strcmp(pstr, "null") == 0) - p = TPM_RH_NULL; - else - p = strtoul(pstr, NULL, 16); - - if (((p & 0xff000000) == 0x40000000) && - (p == TPM_RH_OWNER || - p == TPM_RH_PLATFORM || - p == TPM_RH_ENDORSEMENT || - p == TPM_RH_NULL)) - return p; - else if ((p & 0xff000000) == 0x81000000) - return p; - - return 0; -} - -void free_policy(STACK_OF(TSSOPTPOLICY) *sk) -{ - TSSOPTPOLICY *policy; - - if (sk) - while ((policy = sk_TSSOPTPOLICY_pop(sk))) - TSSOPTPOLICY_free(policy); - - sk_TSSOPTPOLICY_free(sk); -} - /* * A restricted key needs a symmetric seed and algorithm so it can * derive a symmetric encryption key used to protect the sensitive @@ -1054,7 +821,7 @@ int main(int argc, char **argv) } break; case 'p': - parent = get_parent(optarg); + parent = tpm2_get_parent(optarg); if (parent == 0) { fprintf(stderr, "Invalid parent %s\n", optarg); exit(1); @@ -1159,7 +926,7 @@ int main(int argc, char **argv) goto out_err; } - rc = parse_policy_file(policyFilename, sk, auth, &digest); + rc = tpm2_parse_policy_file(policyFilename, sk, auth, &digest); if (rc) { reason = "parse_policy_file"; goto out_free_policy; @@ -1438,10 +1205,10 @@ int main(int argc, char **argv) privkey_len = 0; size = sizeof(privkey); TSS_TPM2B_PRIVATE_Marshal(priv, &privkey_len, &buffer, &size); - openssl_write_tpmfile(filename, pubkey, pubkey_len, - privkey, privkey_len, auth == NULL, parent, sk, - version, enc_secret); - free_policy(sk); + tpm2_write_tpmfile(filename, pubkey, pubkey_len, + privkey, privkey_len, auth == NULL, parent, sk, + version, enc_secret); + tpm2_free_policy(sk); exit(0); @@ -1453,7 +1220,7 @@ int main(int argc, char **argv) out_free_auth: free(auth); out_free_policy: - free_policy(sk); + tpm2_free_policy(sk); out_err: if (rc == NOT_TPM_ERROR) fprintf(stderr, "%s failed\n", reason); diff --git a/tpm2-common.c b/tpm2-common.c index 84b9093..c60b151 100644 --- a/tpm2-common.c +++ b/tpm2-common.c @@ -7,6 +7,12 @@ #include <stdio.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> +#include <ctype.h> + +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/mman.h> #include <openssl/asn1.h> #include <openssl/evp.h> @@ -23,8 +29,8 @@ #include TSSINCLUDE(tsscryptoh.h) #include TSSINCLUDE(Unmarshal_fp.h) -#include "tpm2-common.h" #include "tpm2-asn.h" +#include "tpm2-common.h" struct myTPM2B { UINT16 s; @@ -1361,6 +1367,229 @@ void tpm2_unload_key(TSS_CONTEXT *tssContext, TPM_HANDLE key) TSS_Delete(tssContext); } +TPM_HANDLE tpm2_get_parent(const char *pstr) +{ + TPM_HANDLE p; + + if (strcmp(pstr, "owner") == 0) + p = TPM_RH_OWNER; + else if (strcmp(pstr, "platform") == 0) + p = TPM_RH_PLATFORM; + else if (strcmp(pstr, "endorsement") == 0) + p = TPM_RH_ENDORSEMENT; + else if (strcmp(pstr, "null") == 0) + p = TPM_RH_NULL; + else + p = strtoul(pstr, NULL, 16); + + if (((p & 0xff000000) == 0x40000000) && + (p == TPM_RH_OWNER || + p == TPM_RH_PLATFORM || + p == TPM_RH_ENDORSEMENT || + p == TPM_RH_NULL)) + return p; + else if ((p & 0xff000000) == 0x81000000) + return p; + + return 0; +} + +int tpm2_write_tpmfile(const char *file, BYTE *pubkey, int pubkey_len, + BYTE *privkey, int privkey_len, int empty_auth, + TPM_HANDLE parent, STACK_OF(TSSOPTPOLICY) *sk, + int version, TPM2B_ENCRYPTED_SECRET *secret) +{ + union { + TSSLOADABLE tssl; + TSSPRIVKEY tpk; + } k; + BIO *outb; + + /* clear structure so as not to have to set optional parameters */ + memset(&k, 0, sizeof(k)); + if ((outb = BIO_new_file(file, "w")) == NULL) { + fprintf(stderr, "Error opening file for write: %s\n", file); + return 1; + } + if (version == 0) { + k.tssl.type = OBJ_txt2obj(OID_OldloadableKey, 1); + k.tssl.emptyAuth = empty_auth; + k.tssl.parent = ASN1_INTEGER_new(); + ASN1_INTEGER_set(k.tssl.parent, parent); + + k.tssl.pubkey = ASN1_OCTET_STRING_new(); + ASN1_STRING_set(k.tssl.pubkey, pubkey, pubkey_len); + k.tssl.privkey = ASN1_OCTET_STRING_new(); + ASN1_STRING_set(k.tssl.privkey, privkey, privkey_len); + k.tssl.policy = sk; + + PEM_write_bio_TSSLOADABLE(outb, &k.tssl); + } else { + if (secret) { + k.tpk.type = OBJ_txt2obj(OID_importableKey, 1); + k.tpk.secret = ASN1_OCTET_STRING_new(); + ASN1_STRING_set(k.tpk.secret, secret->t.secret, + secret->t.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); + + k.tpk.pubkey = ASN1_OCTET_STRING_new(); + ASN1_STRING_set(k.tpk.pubkey, pubkey, pubkey_len); + k.tpk.privkey = ASN1_OCTET_STRING_new(); + ASN1_STRING_set(k.tpk.privkey, privkey, privkey_len); + k.tpk.policy = sk; + + PEM_write_bio_TSSPRIVKEY(outb, &k.tpk); + } + + BIO_free(outb); + return 0; +} + +/* from lib/hexdump.c (Linux kernel) */ +int hex_to_bin(char ch) +{ + if ((ch >= '0') && (ch <= '9')) + return ch - '0'; + ch = tolower(ch); + if ((ch >= 'a') && (ch <= 'f')) + return ch - 'a' + 10; + return -1; +} + +int hex2bin(unsigned char *dst, const char *src, size_t count) +{ + while (count--) { + int hi = hex_to_bin(*src++); + int lo = hex_to_bin(*src++); + + if ((hi < 0) || (lo < 0)) + return -1; + + *dst++ = (hi << 4) | lo; + } + return 0; +} + +TPM_RC tpm2_parse_policy_file(const char *policy_file, + STACK_OF(TSSOPTPOLICY) *sk, + char *auth, TPMT_HA *digest) +{ + struct stat st; + char *data, *data_ptr; + unsigned char buf[2048]; + unsigned char *buf_ptr; + TSSOPTPOLICY *policy = NULL; + INT32 buf_len; + TPM_CC code; + TPM_RC rc = NOT_TPM_ERROR; + int fd, policy_auth_value = 0; + + if (stat(policy_file, &st) == -1) { + fprintf(stderr, "File %s cannot be accessed\n", policy_file); + return rc; + } + + fd = open(policy_file, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "File %s cannot be opened\n", policy_file); + return rc; + } + + data = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE, fd, 0); + if (!data) { + fprintf(stderr, "mmap() failed\n"); + goto out; + } + + while ((data_ptr = strsep(&data, "\n"))) { + TPMT_HA hash_digest; + unsigned char *hash = (unsigned char *)hash_digest.digest.tssmax; + INT32 hash_len; + + buf_ptr = buf; + buf_len = strlen(data_ptr) / 2; + if (buf_len > sizeof(buf)) { + rc = NOT_TPM_ERROR; + fprintf(stderr, "line too long\n"); + goto out_munmap; + } + + if (!buf_len) + break; + + rc = hex2bin(buf, data_ptr, buf_len); + if (rc < 0) { + rc = NOT_TPM_ERROR; + fprintf(stderr, "hex2bin() failed\n"); + goto out_munmap; + } + + rc = TPM_CC_Unmarshal(&code, &buf_ptr, &buf_len); + if (rc) { + fprintf(stderr, "TPM_CC_Unmarshal() failed\n"); + goto out_munmap; + } + + if (code == TPM_CC_PolicyCounterTimer) { + /* for a countertimer, the policy is a hash of the hash */ + hash_digest.hashAlg = digest->hashAlg; + hash_len = TSS_GetDigestSize(digest->hashAlg); + TSS_Hash_Generate(&hash_digest, buf_len, buf_ptr, 0, NULL); + hash = hash_digest.digest.tssmax; + } else { + hash = buf_ptr; + hash_len = buf_len; + } + + rc = TSS_Hash_Generate(digest, + TSS_GetDigestSize(digest->hashAlg), + (uint8_t *)&digest->digest, + /* the command code */ + 4, buf_ptr - 4, + hash_len, hash, 0, NULL); + if (rc) { + fprintf(stderr, "TSS_Hash_Generate() failed\n"); + goto out_munmap; + } + + if (code == TPM_CC_PolicyAuthValue) + policy_auth_value = 1; + + policy = TSSOPTPOLICY_new(); + ASN1_INTEGER_set(policy->CommandCode, code); + ASN1_STRING_set(policy->CommandPolicy, buf_ptr, buf_len); + sk_TSSOPTPOLICY_push(sk, policy); + } + + if (auth && !policy_auth_value) { + rc = NOT_TPM_ERROR; + fprintf(stderr, "PolicyAuthValue command is required\n"); + } + +out_munmap: + munmap(data, st.st_size); +out: + close(fd); + return rc; +} + +void tpm2_free_policy(STACK_OF(TSSOPTPOLICY) *sk) +{ + TSSOPTPOLICY *policy; + + if (sk) + while ((policy = sk_TSSOPTPOLICY_pop(sk))) + TSSOPTPOLICY_free(policy); + + sk_TSSOPTPOLICY_free(sk); +} + IMPLEMENT_ASN1_FUNCTIONS(TSSOPTPOLICY) IMPLEMENT_ASN1_FUNCTIONS(TSSLOADABLE) IMPLEMENT_ASN1_FUNCTIONS(TSSPRIVKEY) diff --git a/tpm2-common.h b/tpm2-common.h index 536cedb..0e5d415 100644 --- a/tpm2-common.h +++ b/tpm2-common.h @@ -4,6 +4,10 @@ #define T2_AES_KEY_BITS 128 #define T2_AES_KEY_BYTES (T2_AES_KEY_BITS/8) +/* for use as a TPM_RC return type to indicate this is + * not a TPM error, so don't process the rc as one */ +#define NOT_TPM_ERROR (0xffffffff) + struct policy_command { TPM_CC code; INT32 size; @@ -63,4 +67,13 @@ TPM_HANDLE tpm2_load_key(TSS_CONTEXT **tsscp, struct app_data *app_data, void tpm2_unload_key(TSS_CONTEXT *tssContext, TPM_HANDLE key); void tpm2_delete(struct app_data *app_data); char *tpm2_get_auth(UI_METHOD *ui, char *input_string, void *cb_data); +TPM_HANDLE tpm2_get_parent(const char *pstr); +int tpm2_write_tpmfile(const char *file, BYTE *pubkey, int pubkey_len, + BYTE *privkey, int privkey_len, int empty_auth, + TPM_HANDLE parent, STACK_OF(TSSOPTPOLICY) *sk, + int version, TPM2B_ENCRYPTED_SECRET *secret); +TPM_RC tpm2_parse_policy_file(const char *policy_file, + STACK_OF(TSSOPTPOLICY) *sk, + char *auth, TPMT_HA *digest); +void tpm2_free_policy(STACK_OF(TSSOPTPOLICY) *sk); #endif |