diff --git a/SOURCES/0002-Don-t-assume-end-of-argv-is-NULL.patch b/SOURCES/0002-Don-t-assume-end-of-argv-is-NULL.patch new file mode 100644 index 0000000..4bc3186 --- /dev/null +++ b/SOURCES/0002-Don-t-assume-end-of-argv-is-NULL.patch @@ -0,0 +1,46 @@ +From 3520df21494727e5dcde19e079d06d8d9899c7f1 Mon Sep 17 00:00:00 2001 +From: Erik Larsson +Date: Sat, 21 Nov 2020 10:59:13 +0100 +Subject: [PATCH 01/17] Don't assume end of argv is NULL + +On a musl based system argv[optind] && strcmp(...) where optind > argc might read random memory and segfault. + +Signed-off-by: Erik Larsson +--- + lib/tpm2_options.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/tpm2_options.c b/lib/tpm2_options.c +index e9aaa036..9fa583c6 100644 +--- a/lib/tpm2_options.c ++++ b/lib/tpm2_options.c +@@ -300,7 +300,7 @@ tpm2_option_code tpm2_handle_options(int argc, char **argv, + if (argv[optind - 1]) { + if (!strcmp(argv[optind - 1], "--help=no-man") || + !strcmp(argv[optind - 1], "-h=no-man") || +- (argv[optind] && !strcmp(argv[optind], "no-man"))) { ++ (argc < optind && !strcmp(argv[optind], "no-man"))) { + manpager = false; + optind++; + /* +@@ -309,7 +309,7 @@ tpm2_option_code tpm2_handle_options(int argc, char **argv, + */ + } else if (!strcmp(argv[optind - 1], "--help=man") || + !strcmp(argv[optind - 1], "-h=man") || +- (argv[optind] && !strcmp(argv[optind], "man"))) { ++ (argc < optind && !strcmp(argv[optind], "man"))) { + manpager = true; + explicit_manpager = true; + optind++; +@@ -318,7 +318,7 @@ tpm2_option_code tpm2_handle_options(int argc, char **argv, + * argv[0] = "tool name" + * argv[1] = "--help" argv[2] = 0 + */ +- if (!argv[optind] && argc == 2) { ++ if (optind >= argc && argc == 2) { + manpager = false; + } else { + /* +-- +2.31.1 + diff --git a/SOURCES/0003-tpm2_options-fix-possible-null-ptr-passed-to-strdup.patch b/SOURCES/0003-tpm2_options-fix-possible-null-ptr-passed-to-strdup.patch new file mode 100644 index 0000000..b3deac9 --- /dev/null +++ b/SOURCES/0003-tpm2_options-fix-possible-null-ptr-passed-to-strdup.patch @@ -0,0 +1,31 @@ +From 2a064f4c91a90ab95fe354a42e1166a4c64452fb Mon Sep 17 00:00:00 2001 +From: William Roberts +Date: Wed, 25 Nov 2020 07:48:44 -0600 +Subject: [PATCH 02/17] tpm2_options: fix possible null ptr passed to strdup + +Fixes: +../lib/tpm2_options.c:201:20: warning: Null pointer passed as an argument to a 'nonnull' parameter + command_copy = strdup(command); + +Signed-off-by: William Roberts +--- + lib/tpm2_options.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/lib/tpm2_options.c b/lib/tpm2_options.c +index 9fa583c6..c2e18bad 100644 +--- a/lib/tpm2_options.c ++++ b/lib/tpm2_options.c +@@ -193,8 +193,7 @@ void tpm2_print_usage(const char *command, struct tpm2_options *tool_opts) { + unsigned int i; + bool indent = true; + char *command_copy; +- +- if (!tool_opts) { ++ if (!tool_opts || !command) { + return; + } + +-- +2.31.1 + diff --git a/SOURCES/0004-tpm2_identity_util-move-create_name-into-utility-lib.patch b/SOURCES/0004-tpm2_identity_util-move-create_name-into-utility-lib.patch new file mode 100644 index 0000000..ae72fb7 --- /dev/null +++ b/SOURCES/0004-tpm2_identity_util-move-create_name-into-utility-lib.patch @@ -0,0 +1,143 @@ +From 6a3100ad060934228a1bec06ae43b41f5ea8a51b Mon Sep 17 00:00:00 2001 +From: Trammell hudson +Date: Fri, 26 Mar 2021 17:23:07 +0000 +Subject: [PATCH 03/17] tpm2_identity_util: move create_name() into utility + library + +Signed-off-by: Trammell Hudson +--- + lib/tpm2_identity_util.c | 40 ++++++++++++++++++++++++++++++++++++++ + lib/tpm2_identity_util.h | 10 ++++++++++ + tools/tpm2_import.c | 42 +--------------------------------------- + 3 files changed, 51 insertions(+), 41 deletions(-) + +diff --git a/lib/tpm2_identity_util.c b/lib/tpm2_identity_util.c +index a3b0e387..e11137ab 100644 +--- a/lib/tpm2_identity_util.c ++++ b/lib/tpm2_identity_util.c +@@ -423,3 +423,43 @@ void tpm2_identity_util_calculate_outer_integrity(TPMI_ALG_HASH parent_name_alg, + encrypted_duplicate_sensitive->size, pubname->name, pubname->size, + protection_hmac_key->buffer, outer_hmac); + } ++ ++bool tpm2_identity_create_name(TPM2B_PUBLIC *public, TPM2B_NAME *pubname) { ++ ++ /* ++ * A TPM2B_NAME is the name of the algorithm, followed by the hash. ++ * Calculate the name by: ++ * 1. Marshaling the name algorithm ++ * 2. Marshaling the TPMT_PUBLIC past the name algorithm from step 1. ++ * 3. Hash the TPMT_PUBLIC portion in marshaled data. ++ */ ++ ++ TPMI_ALG_HASH name_alg = public->publicArea.nameAlg; ++ ++ // Step 1 - set beginning of name to hash alg ++ size_t hash_offset = 0; ++ Tss2_MU_UINT16_Marshal(name_alg, pubname->name, pubname->size, ++ &hash_offset); ++ ++ // Step 2 - marshal TPMTP ++ TPMT_PUBLIC marshaled_tpmt; ++ size_t tpmt_marshalled_size = 0; ++ Tss2_MU_TPMT_PUBLIC_Marshal(&public->publicArea, ++ (uint8_t *) &marshaled_tpmt, sizeof(public->publicArea), ++ &tpmt_marshalled_size); ++ ++ // Step 3 - Hash the data into name just past the alg type. ++ digester d = tpm2_openssl_halg_to_digester(name_alg); ++ if (!d) { ++ return false; ++ } ++ ++ d((const unsigned char *) &marshaled_tpmt, tpmt_marshalled_size, ++ pubname->name + hash_offset); ++ ++ //Set the name size, UINT16 followed by HASH ++ UINT16 hash_size = tpm2_alg_util_get_hash_size(name_alg); ++ pubname->size = hash_size + hash_offset; ++ ++ return true; ++} +diff --git a/lib/tpm2_identity_util.h b/lib/tpm2_identity_util.h +index 0ac55793..61e10376 100644 +--- a/lib/tpm2_identity_util.h ++++ b/lib/tpm2_identity_util.h +@@ -102,4 +102,14 @@ void tpm2_identity_util_calculate_outer_integrity(TPMI_ALG_HASH parent_name_alg, + TPM2B_MAX_BUFFER *encrypted_duplicate_sensitive, + TPM2B_DIGEST *outer_hmac); + ++/** ++ * Computes the name of a TPM key. ++ * ++ * @param public ++ * Public key structure ++ * @param pubname ++ * The name structure to populate. ++ */ ++bool tpm2_identity_create_name(TPM2B_PUBLIC *public, TPM2B_NAME *pubname); ++ + #endif /* LIB_TPM2_IDENTITY_UTIL_H_ */ +diff --git a/tools/tpm2_import.c b/tools/tpm2_import.c +index eb8dd9a7..a5d1b4e6 100644 +--- a/tools/tpm2_import.c ++++ b/tools/tpm2_import.c +@@ -74,46 +74,6 @@ static tool_rc readpublic(ESYS_CONTEXT *ectx, ESYS_TR handle, + return tpm2_readpublic(ectx, handle, public, NULL, NULL); + } + +-static bool create_name(TPM2B_PUBLIC *public, TPM2B_NAME *pubname) { +- +- /* +- * A TPM2B_NAME is the name of the algorithm, followed by the hash. +- * Calculate the name by: +- * 1. Marshaling the name algorithm +- * 2. Marshaling the TPMT_PUBLIC past the name algorithm from step 1. +- * 3. Hash the TPMT_PUBLIC portion in marshaled data. +- */ +- +- TPMI_ALG_HASH name_alg = public->publicArea.nameAlg; +- +- // Step 1 - set beginning of name to hash alg +- size_t hash_offset = 0; +- Tss2_MU_UINT16_Marshal(name_alg, pubname->name, pubname->size, +- &hash_offset); +- +- // Step 2 - marshal TPMTP +- TPMT_PUBLIC marshaled_tpmt; +- size_t tpmt_marshalled_size = 0; +- Tss2_MU_TPMT_PUBLIC_Marshal(&public->publicArea, +- (uint8_t *) &marshaled_tpmt, sizeof(public->publicArea), +- &tpmt_marshalled_size); +- +- // Step 3 - Hash the data into name just past the alg type. +- digester d = tpm2_openssl_halg_to_digester(name_alg); +- if (!d) { +- return false; +- } +- +- d((const unsigned char *) &marshaled_tpmt, tpmt_marshalled_size, +- pubname->name + 2); +- +- //Set the name size, UINT16 followed by HASH +- UINT16 hash_size = tpm2_alg_util_get_hash_size(name_alg); +- pubname->size = hash_size + 2; +- +- return true; +-} +- + static void create_import_key_private_data(TPM2B_PRIVATE *private, + TPMI_ALG_HASH parent_name_alg, + TPM2B_MAX_BUFFER *encrypted_duplicate_sensitive, +@@ -155,7 +115,7 @@ static tool_rc key_import(ESYS_CONTEXT *ectx, TPM2B_PUBLIC *parent_pub, + * Calculate the object name. + */ + TPM2B_NAME pubname = TPM2B_TYPE_INIT(TPM2B_NAME, name); +- bool res = create_name(pubkey, &pubname); ++ bool res = tpm2_identity_create_name(pubkey, &pubname); + if (!res) { + return false; + } +-- +2.31.1 + diff --git a/SOURCES/0005-openssl-Remove-support-for-OpenSSL-1.1.0.patch b/SOURCES/0005-openssl-Remove-support-for-OpenSSL-1.1.0.patch new file mode 100644 index 0000000..d7721ed --- /dev/null +++ b/SOURCES/0005-openssl-Remove-support-for-OpenSSL-1.1.0.patch @@ -0,0 +1,254 @@ +From 61989b4c0a2da337a5c8df56e68c83e73259ed75 Mon Sep 17 00:00:00 2001 +From: Petr Gotthard +Date: Sat, 7 Aug 2021 11:39:52 +0200 +Subject: [PATCH 04/17] openssl: Remove support for OpenSSL < 1.1.0 + +The OpenSSL 1.0.2 is no longer maintained. Supporting an EOL crypto +library is not a good idea. + + - Compared to the upstream commit 1e439d85 changes related to functions + and features not previously backported were ommited. + +Signed-off-by: Petr Gotthard +--- + configure.ac | 2 +- + doc/CHANGELOG.md | 5 +++ + doc/INSTALL.md | 2 +- + doc/RELEASE.md | 7 ---- + lib/tpm2_openssl.c | 87 ---------------------------------------------- + lib/tpm2_openssl.h | 10 ------ + 6 files changed, 7 insertions(+), 106 deletions(-) + +diff --git a/configure.ac b/configure.ac +index a3988e15..9561fa86 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -58,7 +58,7 @@ PKG_CHECK_MODULES([TSS2_TCTILDR], [tss2-tctildr]) + PKG_CHECK_MODULES([TSS2_MU], [tss2-mu]) + PKG_CHECK_MODULES([TSS2_RC], [tss2-rc]) + PKG_CHECK_MODULES([TSS2_SYS], [tss2-sys]) +-PKG_CHECK_MODULES([CRYPTO], [libcrypto >= 1.0.2g]) ++PKG_CHECK_MODULES([CRYPTO], [libcrypto >= 1.1.0]) + PKG_CHECK_MODULES([CURL], [libcurl]) + PKG_CHECK_MODULES([UUID], [uuid]) + +diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md +index 87573fd7..b244dfee 100644 +--- a/doc/CHANGELOG.md ++++ b/doc/CHANGELOG.md +@@ -1,5 +1,10 @@ + ## Changelog + ++### next ++ ++ * openssl: ++ - Dropped support for OpenSSL < 1.1.0 ++ + ### 5.0 - 2020-11-16 + + #### Non Backwards Compatible Changes +diff --git a/doc/INSTALL.md b/doc/INSTALL.md +index b23b8d61..ab160581 100644 +--- a/doc/INSTALL.md ++++ b/doc/INSTALL.md +@@ -19,7 +19,7 @@ To build and install the tpm2-tools software the following software is required: + * C compiler + * C Library Development Libraries and Header Files (for pthreads headers) + * ESAPI - TPM2.0 TSS ESAPI library (tss2-esys) and header files +- * OpenSSL libcrypto library and header files ++ * OpenSSL libcrypto library and header files (version >= 1.1.0) + * Curl library and header files + * Universally Unique ID library (UUID) + +diff --git a/doc/RELEASE.md b/doc/RELEASE.md +index e2c72a67..8769b57d 100644 +--- a/doc/RELEASE.md ++++ b/doc/RELEASE.md +@@ -23,13 +23,6 @@ the next release. + - [3.0.X](https://github.com/tpm2-software/tpm2-tools/tree/3.0.X): EOL after + 3.2.1 release. + +-## OpenSSL +- +-tpm2-tools relies heavily on OpenSSL. OpenSSL will be EOL'ing 1.0.2 at the end +-of 2019, see: https://www.openssl.org/blog/blog/2018/05/18/new-lts/. When this +-occurs, we will remove OSSL 1.0.2 support from the tpm2-tools repository as +-supporting an EOL crypto library is not a good idea. +- + # Release Information + + Releases shall be tagged following semantic version guidelines found at: +diff --git a/lib/tpm2_openssl.c b/lib/tpm2_openssl.c +index e769d6df..877d2764 100644 +--- a/lib/tpm2_openssl.c ++++ b/lib/tpm2_openssl.c +@@ -72,58 +72,6 @@ const EVP_MD *tpm2_openssl_halg_from_tpmhalg(TPMI_ALG_HASH algorithm) { + /* no return, not possible */ + } + +-#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11) +-int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) { +- +- if ((r->n == NULL && n == NULL) || (r->e == NULL && e == NULL)) { +- return 0; +- } +- +- if (n != NULL) { +- BN_free(r->n); +- r->n = n; +- } +- +- if (e != NULL) { +- BN_free(r->e); +- r->e = e; +- } +- +- if (d != NULL) { +- BN_free(r->d); +- r->d = d; +- } +- +- return 1; +-} +- +-void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) { +- if(p) { +- *p = r->p; +- } +- +- if (q) { +- *q = r->q; +- } +-} +- +-int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) { +- +- if (!r || !s) { +- return 0; +- } +- +- BN_clear_free(sig->r); +- BN_clear_free(sig->s); +- +- sig->r = r; +- sig->s = s; +- +- return 1; +-} +- +-#endif +- + bool tpm2_openssl_hash_compute_data(TPMI_ALG_HASH halg, BYTE *buffer, + UINT16 length, TPM2B_DIGEST *digest) { + +@@ -422,54 +370,28 @@ out: + + HMAC_CTX *tpm2_openssl_hmac_new() { + HMAC_CTX *ctx; +-#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11) +- ctx = malloc(sizeof(*ctx)); +-#else + ctx = HMAC_CTX_new(); +-#endif + if (!ctx) + return NULL; + +-#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11) +- HMAC_CTX_init(ctx); +-#endif +- + return ctx; + } + + void tpm2_openssl_hmac_free(HMAC_CTX *ctx) { +-#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11) +- HMAC_CTX_cleanup(ctx); +- free(ctx); +-#else + HMAC_CTX_free(ctx); +-#endif + } + + EVP_CIPHER_CTX *tpm2_openssl_cipher_new(void) { + EVP_CIPHER_CTX *ctx; +-#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11) +- ctx = malloc(sizeof(*ctx)); +-#else + ctx = EVP_CIPHER_CTX_new(); +-#endif + if (!ctx) + return NULL; + +-#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11) +- EVP_CIPHER_CTX_init(ctx); +-#endif +- + return ctx; + } + + void tpm2_openssl_cipher_free(EVP_CIPHER_CTX *ctx) { +-#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11) +- EVP_CIPHER_CTX_cleanup(ctx); +- free(ctx); +-#else + EVP_CIPHER_CTX_free(ctx); +-#endif + } + + digester tpm2_openssl_halg_to_digester(TPMI_ALG_HASH halg) { +@@ -680,12 +602,7 @@ static bool load_public_RSA_from_key(RSA *k, TPM2B_PUBLIC *pub) { + const BIGNUM *n; /* modulus */ + const BIGNUM *e; /* public key exponent */ + +-#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11) +- n = k->n; +- e = k->e; +-#else + RSA_get0_key(k, &n, &e, NULL); +-#endif + + /* + * The size of the modulus is the key size in RSA, store this as the +@@ -1006,11 +923,7 @@ static bool load_private_RSA_from_key(RSA *k, TPM2B_SENSITIVE *priv) { + + const BIGNUM *p; /* the private key exponent */ + +-#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11) +- p = k->p; +-#else + RSA_get0_factors(k, &p, NULL); +-#endif + + TPMT_SENSITIVE *sa = &priv->sensitiveArea; + +diff --git a/lib/tpm2_openssl.h b/lib/tpm2_openssl.h +index 46c8f9c0..8e3e0c17 100644 +--- a/lib/tpm2_openssl.h ++++ b/lib/tpm2_openssl.h +@@ -13,10 +13,6 @@ + + #include "pcr.h" + +-#if (OPENSSL_VERSION_NUMBER < 0x1010000fL && !defined(LIBRESSL_VERSION_NUMBER)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L) /* OpenSSL 1.1.0 */ +-#define LIB_TPM2_OPENSSL_OPENSSL_PRE11 +-#endif +- + #if OPENSSL_VERSION_NUMBER >= 0x10101000L + #define EC_POINT_set_affine_coordinates_tss(group, tpm_pub_key, bn_x, bn_y, dmy) \ + EC_POINT_set_affine_coordinates(group, tpm_pub_key, bn_x, bn_y, dmy) +@@ -32,12 +28,6 @@ + EC_POINT_get_affine_coordinates_GFp(group, tpm_pub_key, bn_x, bn_y, dmy) + #endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ + +-#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11) +-int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); +-void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); +-int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); +-#endif +- + /** + * Function prototype for a hashing routine. + * +-- +2.31.1 + diff --git a/SOURCES/0006-openssl-Remove-functions-that-have-no-effect-in-Open.patch b/SOURCES/0006-openssl-Remove-functions-that-have-no-effect-in-Open.patch new file mode 100644 index 0000000..41c0216 --- /dev/null +++ b/SOURCES/0006-openssl-Remove-functions-that-have-no-effect-in-Open.patch @@ -0,0 +1,48 @@ +From 8c1968a1e52c3d45a96509e9eba753357ad377c9 Mon Sep 17 00:00:00 2001 +From: Petr Gotthard +Date: Sat, 7 Aug 2021 11:45:14 +0200 +Subject: [PATCH 05/17] openssl: Remove functions that have no effect in + OpenSSL >= 1.1.0 + +This will work with OpenSSL 1.1.0 through 3.0.0. + +Signed-off-by: Petr Gotthard +--- + lib/tpm2_convert.c | 1 - + tools/tpm2_tool.c | 8 -------- + 2 files changed, 9 deletions(-) + +diff --git a/lib/tpm2_convert.c b/lib/tpm2_convert.c +index 27a0effe..cc1c18ab 100644 +--- a/lib/tpm2_convert.c ++++ b/lib/tpm2_convert.c +@@ -262,7 +262,6 @@ static bool tpm2_convert_pubkey_bio(TPMT_PUBLIC *public, + "Unsupported key type for requested output format. Only RSA is supported."); + } + +- ERR_free_strings(); + return result; + } + +diff --git a/tools/tpm2_tool.c b/tools/tpm2_tool.c +index f4865266..edd04c83 100644 +--- a/tools/tpm2_tool.c ++++ b/tools/tpm2_tool.c +@@ -230,14 +230,6 @@ int main(int argc, char **argv) { + tpm2_errata_init(ctx.ectx); + } + +- /* +- * Load the openssl error strings and algorithms +- * so library routines work as expected. +- */ +- OpenSSL_add_all_algorithms(); +- OpenSSL_add_all_ciphers(); +- ERR_load_crypto_strings(); +- + /* + * Call the specific tool, all tools implement this function instead of + * 'main'. +-- +2.31.1 + diff --git a/SOURCES/0007-openssl-Remove-unnecesary-EVP_CIPHER_CTX-and-HMAC_CT.patch b/SOURCES/0007-openssl-Remove-unnecesary-EVP_CIPHER_CTX-and-HMAC_CT.patch new file mode 100644 index 0000000..6a2d105 --- /dev/null +++ b/SOURCES/0007-openssl-Remove-unnecesary-EVP_CIPHER_CTX-and-HMAC_CT.patch @@ -0,0 +1,150 @@ +From 43ad483907069798920a949a3cc9615cb3156975 Mon Sep 17 00:00:00 2001 +From: Petr Gotthard +Date: Sat, 7 Aug 2021 11:56:22 +0200 +Subject: [PATCH 06/17] openssl: Remove unnecesary EVP_CIPHER_CTX and HMAC_CTX + wrappers + +Signed-off-by: Petr Gotthard +--- + lib/tpm2_identity_util.c | 7 +++++-- + lib/tpm2_kdfa.c | 4 ++-- + lib/tpm2_openssl.c | 26 -------------------------- + lib/tpm2_openssl.h | 31 ------------------------------- + 4 files changed, 7 insertions(+), 61 deletions(-) + +diff --git a/lib/tpm2_identity_util.c b/lib/tpm2_identity_util.c +index e11137ab..a268295f 100644 +--- a/lib/tpm2_identity_util.c ++++ b/lib/tpm2_identity_util.c +@@ -289,7 +289,10 @@ static bool aes_encrypt_buffers(TPMT_SYM_DEF_OBJECT *sym, + return false; + } + +- EVP_CIPHER_CTX *ctx = tpm2_openssl_cipher_new(); ++ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); ++ if (!ctx) { ++ return false; ++ } + + int rc = EVP_EncryptInit_ex(ctx, cipher, NULL, encryption_key, iv); + if (!rc) { +@@ -336,7 +339,7 @@ static bool aes_encrypt_buffers(TPMT_SYM_DEF_OBJECT *sym, + result = true; + + out: +- tpm2_openssl_cipher_free(ctx); ++ EVP_CIPHER_CTX_free(ctx); + + return result; + } +diff --git a/lib/tpm2_kdfa.c b/lib/tpm2_kdfa.c +index 354516e8..5747b3ca 100644 +--- a/lib/tpm2_kdfa.c ++++ b/lib/tpm2_kdfa.c +@@ -40,7 +40,7 @@ TSS2_RC tpm2_kdfa(TPMI_ALG_HASH hash_alg, TPM2B *key, char *label, + return TPM2_RC_HASH; + } + +- HMAC_CTX *ctx = tpm2_openssl_hmac_new(); ++ HMAC_CTX *ctx = HMAC_CTX_new(); + if (!ctx) { + LOG_ERR("HMAC context allocation failed"); + return TPM2_RC_MEMORY; +@@ -100,7 +100,7 @@ TSS2_RC tpm2_kdfa(TPMI_ALG_HASH hash_alg, TPM2B *key, char *label, + result_key->size = bytes; + + err: +- tpm2_openssl_hmac_free(ctx); ++ HMAC_CTX_free(ctx); + + return rval; + } +diff --git a/lib/tpm2_openssl.c b/lib/tpm2_openssl.c +index 877d2764..1752525e 100644 +--- a/lib/tpm2_openssl.c ++++ b/lib/tpm2_openssl.c +@@ -368,32 +368,6 @@ out: + return result; + } + +-HMAC_CTX *tpm2_openssl_hmac_new() { +- HMAC_CTX *ctx; +- ctx = HMAC_CTX_new(); +- if (!ctx) +- return NULL; +- +- return ctx; +-} +- +-void tpm2_openssl_hmac_free(HMAC_CTX *ctx) { +- HMAC_CTX_free(ctx); +-} +- +-EVP_CIPHER_CTX *tpm2_openssl_cipher_new(void) { +- EVP_CIPHER_CTX *ctx; +- ctx = EVP_CIPHER_CTX_new(); +- if (!ctx) +- return NULL; +- +- return ctx; +-} +- +-void tpm2_openssl_cipher_free(EVP_CIPHER_CTX *ctx) { +- EVP_CIPHER_CTX_free(ctx); +-} +- + digester tpm2_openssl_halg_to_digester(TPMI_ALG_HASH halg) { + + switch (halg) { +diff --git a/lib/tpm2_openssl.h b/lib/tpm2_openssl.h +index 8e3e0c17..642e4635 100644 +--- a/lib/tpm2_openssl.h ++++ b/lib/tpm2_openssl.h +@@ -67,20 +67,6 @@ int tpm2_openssl_halgid_from_tpmhalg(TPMI_ALG_HASH algorithm); + */ + const EVP_MD *tpm2_openssl_halg_from_tpmhalg(TPMI_ALG_HASH algorithm); + +-/** +- * Start an openssl hmac session. +- * @return +- * A valid session pointer or NULL on error. +- */ +-HMAC_CTX *tpm2_openssl_hmac_new(); +- +-/** +- * Free an hmac context created via tpm2_openssl_hmac_new(). +- * @param ctx +- * The context to release resources of. +- */ +-void tpm2_openssl_hmac_free(HMAC_CTX *ctx); +- + /** + * Hash a byte buffer. + * @param halg +@@ -161,23 +147,6 @@ bool tpm2_openssl_hash_pcr_banks_le(TPMI_ALG_HASH hashAlg, + bool tpm2_openssl_pcr_extend(TPMI_ALG_HASH halg, BYTE *pcr, + const BYTE *data, UINT16 length); + +-/** +- * Obtains an OpenSSL EVP_CIPHER_CTX dealing with version +- * API changes in OSSL. +- * +- * @return +- * An Initialized OpenSSL EVP_CIPHER_CTX. +- */ +-EVP_CIPHER_CTX *tpm2_openssl_cipher_new(void); +- +-/** +- * Free's an EVP_CIPHER_CTX obtained via tpm2_openssl_cipher_new() +- * dealing with OSSL API version changes. +- * @param ctx +- * The EVP_CIPHER_CTX to free. +- */ +-void tpm2_openssl_cipher_free(EVP_CIPHER_CTX *ctx); +- + /** + * Returns a function pointer capable of performing the + * given digest from a TPMI_HASH_ALG. +-- +2.31.1 + diff --git a/SOURCES/0008-openssl-Replace-SHA256_CTX-by-EVP_MD_CTX.patch b/SOURCES/0008-openssl-Replace-SHA256_CTX-by-EVP_MD_CTX.patch new file mode 100644 index 0000000..c78be34 --- /dev/null +++ b/SOURCES/0008-openssl-Replace-SHA256_CTX-by-EVP_MD_CTX.patch @@ -0,0 +1,104 @@ +From 59f35567cf810d9eafdeedced5dc5571d9b33dfd Mon Sep 17 00:00:00 2001 +From: Petr Gotthard +Date: Sat, 7 Aug 2021 12:26:15 +0200 +Subject: [PATCH 07/17] openssl: Replace SHA256_CTX by EVP_MD_CTX + +The EVP_MD_CTX_new() was introduced in OpenSSL 1.1.0 and +the SHA256_CTX was deprecated in OpenSSL 3.0.0. + +Signed-off-by: Petr Gotthard +--- + tools/tpm2_getekcertificate.c | 28 +++++++++++++++------------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +diff --git a/tools/tpm2_getekcertificate.c b/tools/tpm2_getekcertificate.c +index b480dbc3..81600b61 100644 +--- a/tools/tpm2_getekcertificate.c ++++ b/tools/tpm2_getekcertificate.c +@@ -63,20 +63,20 @@ static unsigned char *hash_ek_public(void) { + return NULL; + } + +- SHA256_CTX sha256; +- int is_success = SHA256_Init(&sha256); ++ EVP_MD_CTX *sha256 = EVP_MD_CTX_new(); ++ int is_success = EVP_DigestInit(sha256, EVP_sha256()); + if (!is_success) { +- LOG_ERR("SHA256_Init failed"); ++ LOG_ERR("EVP_DigestInit failed"); + goto err; + } + + switch (ctx.out_public->publicArea.type) { + case TPM2_ALG_RSA: +- is_success = SHA256_Update(&sha256, ++ is_success = EVP_DigestUpdate(sha256, + ctx.out_public->publicArea.unique.rsa.buffer, + ctx.out_public->publicArea.unique.rsa.size); + if (!is_success) { +- LOG_ERR("SHA256_Update failed"); ++ LOG_ERR("EVP_DigestUpdate failed"); + goto err; + } + +@@ -85,27 +85,27 @@ static unsigned char *hash_ek_public(void) { + goto err; + } + BYTE buf[3] = { 0x1, 0x00, 0x01 }; // Exponent +- is_success = SHA256_Update(&sha256, buf, sizeof(buf)); ++ is_success = EVP_DigestUpdate(sha256, buf, sizeof(buf)); + if (!is_success) { +- LOG_ERR("SHA256_Update failed"); ++ LOG_ERR("EVP_DigestUpdate failed"); + goto err; + } + break; + + case TPM2_ALG_ECC: +- is_success = SHA256_Update(&sha256, ++ is_success = EVP_DigestUpdate(sha256, + ctx.out_public->publicArea.unique.ecc.x.buffer, + ctx.out_public->publicArea.unique.ecc.x.size); + if (!is_success) { +- LOG_ERR("SHA256_Update failed"); ++ LOG_ERR("EVP_DigestUpdate failed"); + goto err; + } + +- is_success = SHA256_Update(&sha256, ++ is_success = EVP_DigestUpdate(sha256, + ctx.out_public->publicArea.unique.ecc.y.buffer, + ctx.out_public->publicArea.unique.ecc.y.size); + if (!is_success) { +- LOG_ERR("SHA256_Update failed"); ++ LOG_ERR("EVP_DigestUpdate failed"); + goto err; + } + break; +@@ -115,12 +115,13 @@ static unsigned char *hash_ek_public(void) { + goto err; + } + +- is_success = SHA256_Final(hash, &sha256); ++ is_success = EVP_DigestFinal_ex(sha256, hash, NULL); + if (!is_success) { +- LOG_ERR("SHA256_Final failed"); ++ LOG_ERR("EVP_DigestFinal failed"); + goto err; + } + ++ EVP_MD_CTX_free(sha256); + if (ctx.verbose) { + tpm2_tool_output("public-key-hash:\n"); + tpm2_tool_output(" sha256: "); +@@ -134,6 +135,7 @@ static unsigned char *hash_ek_public(void) { + return hash; + err: + free(hash); ++ EVP_MD_CTX_free(sha256); + return NULL; + } + +-- +2.31.1 + diff --git a/SOURCES/0009-openssl-Replace-deprecated-X509_get_-by-X509_getm_.patch b/SOURCES/0009-openssl-Replace-deprecated-X509_get_-by-X509_getm_.patch new file mode 100644 index 0000000..5ccfe2b --- /dev/null +++ b/SOURCES/0009-openssl-Replace-deprecated-X509_get_-by-X509_getm_.patch @@ -0,0 +1,31 @@ +From 0dfb7b70f77ddcb8a82ca45f04e028c5fcfc350e Mon Sep 17 00:00:00 2001 +From: Petr Gotthard +Date: Sat, 7 Aug 2021 12:29:28 +0200 +Subject: [PATCH 08/17] openssl: Replace deprecated X509_get_ by X509_getm_ + +The X509_get_notBefore() and X509_get_notAfter() were deprecated already +in OpenSSL 1.1.0. + +Signed-off-by: Petr Gotthard +--- + tools/misc/tpm2_certifyX509certutil.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/misc/tpm2_certifyX509certutil.c b/tools/misc/tpm2_certifyX509certutil.c +index e56da2d3..62ed644a 100644 +--- a/tools/misc/tpm2_certifyX509certutil.c ++++ b/tools/misc/tpm2_certifyX509certutil.c +@@ -260,8 +260,8 @@ static tool_rc generate_partial_X509() { + goto out_err; + } + +- X509_gmtime_adj(X509_get_notBefore(cert), 0); // add valid not before +- X509_gmtime_adj(X509_get_notAfter(cert), valid_days * 86400); // add valid not after ++ X509_gmtime_adj(X509_getm_notBefore(cert), 0); // add valid not before ++ X509_gmtime_adj(X509_getm_notAfter(cert), valid_days * 86400); // add valid not after + + X509_NAME *subject = X509_get_subject_name(cert); + if (!subject) { +-- +2.31.1 + diff --git a/SOURCES/0010-openssl-Convert-deprecated-SHA256-384-digesters-to-E.patch b/SOURCES/0010-openssl-Convert-deprecated-SHA256-384-digesters-to-E.patch new file mode 100644 index 0000000..4f760b9 --- /dev/null +++ b/SOURCES/0010-openssl-Convert-deprecated-SHA256-384-digesters-to-E.patch @@ -0,0 +1,209 @@ +From 220b7e0afa943693a4fdafd9a5b8d9e38ea4e785 Mon Sep 17 00:00:00 2001 +From: Petr Gotthard +Date: Sat, 7 Aug 2021 15:54:51 +0200 +Subject: [PATCH 09/17] openssl: Convert deprecated SHA256|384 digesters to + EVP_Digest + +The EVP_Digest function is available since OpenSSL 1.1.0 + +Signed-off-by: Petr Gotthard +--- + lib/tpm2_identity_util.c | 34 ++++++++++++++++++++++++---------- + lib/tpm2_kdfe.c | 13 +++++++++++-- + lib/tpm2_openssl.c | 17 ----------------- + lib/tpm2_openssl.h | 28 ---------------------------- + lib/tpm2_util.c | 15 +++++++++++---- + 5 files changed, 46 insertions(+), 61 deletions(-) + +diff --git a/lib/tpm2_identity_util.c b/lib/tpm2_identity_util.c +index a268295f..e0c3f404 100644 +--- a/lib/tpm2_identity_util.c ++++ b/lib/tpm2_identity_util.c +@@ -391,11 +391,20 @@ bool tpm2_identity_util_calculate_inner_integrity(TPMI_ALG_HASH name_alg, + Tss2_MU_UINT16_Marshal(hash_size, marshalled_sensitive_and_name_digest, + sizeof(uint16_t), &digest_size_info); + +- digester d = tpm2_openssl_halg_to_digester(name_alg); +- d(buffer_marshalled_sensitiveArea, +- marshalled_sensitive_size_info + marshalled_sensitive_size +- + pubname->size, +- marshalled_sensitive_and_name_digest + digest_size_info); ++ const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(name_alg); ++ if (!md) { ++ LOG_ERR("Algorithm not supported: %x", name_alg); ++ return false; ++ } ++ int rc = EVP_Digest(buffer_marshalled_sensitiveArea, ++ marshalled_sensitive_size_info + marshalled_sensitive_size ++ + pubname->size, ++ marshalled_sensitive_and_name_digest + digest_size_info, ++ NULL, md, NULL); ++ if (!rc) { ++ LOG_ERR("Hash calculation failed"); ++ return false; ++ } + + //Inner integrity + encrypted_inner_integrity->size = marshalled_sensitive_size_info +@@ -452,16 +461,21 @@ bool tpm2_identity_create_name(TPM2B_PUBLIC *public, TPM2B_NAME *pubname) { + &tpmt_marshalled_size); + + // Step 3 - Hash the data into name just past the alg type. +- digester d = tpm2_openssl_halg_to_digester(name_alg); +- if (!d) { ++ const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(name_alg); ++ if (!md) { ++ LOG_ERR("Algorithm not supported: %x", name_alg); + return false; + } + +- d((const unsigned char *) &marshaled_tpmt, tpmt_marshalled_size, +- pubname->name + hash_offset); ++ unsigned int hash_size; ++ int rc = EVP_Digest(&marshaled_tpmt, tpmt_marshalled_size, ++ pubname->name + hash_offset, &hash_size, md, NULL); ++ if (!rc) { ++ LOG_ERR("Hash calculation failed"); ++ return false; ++ } + + //Set the name size, UINT16 followed by HASH +- UINT16 hash_size = tpm2_alg_util_get_hash_size(name_alg); + pubname->size = hash_size + hash_offset; + + return true; +diff --git a/lib/tpm2_kdfe.c b/lib/tpm2_kdfe.c +index e8aeb04c..aa4d3e0b 100644 +--- a/lib/tpm2_kdfe.c ++++ b/lib/tpm2_kdfe.c +@@ -42,13 +42,22 @@ TSS2_RC tpm2_kdfe( + tpm2_util_concat_buffer(&hash_input, (TPM2B *) party_u); + tpm2_util_concat_buffer(&hash_input, (TPM2B *) party_v); + +- digester d = tpm2_openssl_halg_to_digester(hash_alg); ++ const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(hash_alg); ++ if (!md) { ++ LOG_ERR("Algorithm not supported: %x", hash_alg); ++ return TPM2_RC_HASH; ++ } + + for (done = 0, counter = 1; done < bytes; done += hash_size, counter++) { + counter_be = tpm2_util_hton_32(counter); + memcpy(hash_input.buffer, &counter_be, 4); + +- d(hash_input.buffer, hash_input.size, result_key->buffer + done); ++ int rc = EVP_Digest(hash_input.buffer, hash_input.size, ++ result_key->buffer + done, NULL, md, NULL); ++ if (!rc) { ++ LOG_ERR("Hash calculation failed"); ++ return TPM2_RC_MEMORY; ++ } + } + // truncate the result to the desired size + result_key->size = bytes; +diff --git a/lib/tpm2_openssl.c b/lib/tpm2_openssl.c +index 1752525e..cdce92f8 100644 +--- a/lib/tpm2_openssl.c ++++ b/lib/tpm2_openssl.c +@@ -368,23 +368,6 @@ out: + return result; + } + +-digester tpm2_openssl_halg_to_digester(TPMI_ALG_HASH halg) { +- +- switch (halg) { +- case TPM2_ALG_SHA1: +- return SHA1; +- case TPM2_ALG_SHA256: +- return SHA256; +- case TPM2_ALG_SHA384: +- return SHA384; +- case TPM2_ALG_SHA512: +- return SHA512; +- /* no default */ +- } +- +- return NULL; +-} +- + /* + * Per man openssl(1), handle the following --passin formats: + * pass:password +diff --git a/lib/tpm2_openssl.h b/lib/tpm2_openssl.h +index 642e4635..78cb826a 100644 +--- a/lib/tpm2_openssl.h ++++ b/lib/tpm2_openssl.h +@@ -28,23 +28,6 @@ + EC_POINT_get_affine_coordinates_GFp(group, tpm_pub_key, bn_x, bn_y, dmy) + #endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ + +-/** +- * Function prototype for a hashing routine. +- * +- * This is a wrapper around OSSL SHA256|384 and etc digesters. +- * +- * @param d +- * The data to digest. +- * @param n +- * The length of the data to digest. +- * @param md +- * The output message digest. +- * @return +- * A pointer to the digest or NULL on error. +- */ +-typedef unsigned char *(*digester)(const unsigned char *d, size_t n, +- unsigned char *md); +- + static inline const char *tpm2_openssl_get_err(void) { + return ERR_error_string(ERR_get_error(), NULL); + } +@@ -147,17 +130,6 @@ bool tpm2_openssl_hash_pcr_banks_le(TPMI_ALG_HASH hashAlg, + bool tpm2_openssl_pcr_extend(TPMI_ALG_HASH halg, BYTE *pcr, + const BYTE *data, UINT16 length); + +-/** +- * Returns a function pointer capable of performing the +- * given digest from a TPMI_HASH_ALG. +- * +- * @param halg +- * The hashing algorithm to use. +- * @return +- * NULL on failure or a valid digester on success. +- */ +-digester tpm2_openssl_halg_to_digester(TPMI_ALG_HASH halg); +- + typedef enum tpm2_openssl_load_rc tpm2_openssl_load_rc; + enum tpm2_openssl_load_rc { + lprc_error = 0, /* an error has occurred */ +diff --git a/lib/tpm2_util.c b/lib/tpm2_util.c +index 4125a4b9..d2c654db 100644 +--- a/lib/tpm2_util.c ++++ b/lib/tpm2_util.c +@@ -579,13 +579,20 @@ bool tpm2_util_calc_unique(TPMI_ALG_HASH name_alg, + memcpy(buf.buffer, seed->buffer, seed->size); + memcpy(&buf.buffer[seed->size], key->buffer, key->size); + +- digester d = tpm2_openssl_halg_to_digester(name_alg); +- if (!d) { ++ const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(name_alg); ++ if (!md) { ++ LOG_ERR("Algorithm not supported: %x", name_alg); + return false; + } + +- unique_data->size = tpm2_alg_util_get_hash_size(name_alg); +- d(buf.buffer, buf.size, unique_data->buffer); ++ unsigned int hash_size; ++ int rc = EVP_Digest(buf.buffer, buf.size, unique_data->buffer, &hash_size, ++ md, NULL); ++ if (!rc) { ++ LOG_ERR("Hash calculation failed"); ++ return false; ++ } ++ unique_data->size = hash_size; + + return true; + } +-- +2.31.1 + diff --git a/SOURCES/0011-openssl-Rename-tpm2_openssl_halg_from_tpmhalg.patch b/SOURCES/0011-openssl-Rename-tpm2_openssl_halg_from_tpmhalg.patch new file mode 100644 index 0000000..9eeaedf --- /dev/null +++ b/SOURCES/0011-openssl-Rename-tpm2_openssl_halg_from_tpmhalg.patch @@ -0,0 +1,194 @@ +From b32168af24708f42a0ee28252912e3155505e983 Mon Sep 17 00:00:00 2001 +From: Petr Gotthard +Date: Tue, 10 Aug 2021 11:49:00 +0200 +Subject: [PATCH 10/17] openssl: Rename tpm2_openssl_halg_from_tpmhalg + +Change its name to tpm2_openssl_md_from_tpmhalg for better naming +consistency with the openssl. + +Signed-off-by: Petr Gotthard +--- + lib/tpm2_identity_util.c | 8 ++++---- + lib/tpm2_kdfa.c | 2 +- + lib/tpm2_kdfe.c | 2 +- + lib/tpm2_openssl.c | 12 ++++++------ + lib/tpm2_openssl.h | 2 +- + lib/tpm2_util.c | 4 ++-- + tools/misc/tpm2_checkquote.c | 2 +- + 7 files changed, 16 insertions(+), 16 deletions(-) + +diff --git a/lib/tpm2_identity_util.c b/lib/tpm2_identity_util.c +index e0c3f404..ba0c0e1c 100644 +--- a/lib/tpm2_identity_util.c ++++ b/lib/tpm2_identity_util.c +@@ -134,7 +134,7 @@ static bool share_secret_with_tpm2_rsa_public_key(TPM2B_DIGEST *protection_seed, + unsigned char encoded[TPM2_MAX_DIGEST_BUFFER]; + return_code = RSA_padding_add_PKCS1_OAEP_mgf1(encoded, mod_size, + protection_seed->buffer, protection_seed->size, label, label_len, +- tpm2_openssl_halg_from_tpmhalg(parent_name_alg), NULL); ++ tpm2_openssl_md_from_tpmhalg(parent_name_alg), NULL); + if (return_code != 1) { + LOG_ERR("Failed RSA_padding_add_PKCS1_OAEP_mgf1\n"); + goto error; +@@ -356,7 +356,7 @@ static void hmac_outer_integrity(TPMI_ALG_HASH parent_name_alg, + + UINT16 hash_size = tpm2_alg_util_get_hash_size(parent_name_alg); + +- HMAC(tpm2_openssl_halg_from_tpmhalg(parent_name_alg), hmac_key, hash_size, ++ HMAC(tpm2_openssl_md_from_tpmhalg(parent_name_alg), hmac_key, hash_size, + to_hmac_buffer, buffer1_size + buffer2_size, + outer_integrity_hmac->buffer, &size); + outer_integrity_hmac->size = size; +@@ -391,7 +391,7 @@ bool tpm2_identity_util_calculate_inner_integrity(TPMI_ALG_HASH name_alg, + Tss2_MU_UINT16_Marshal(hash_size, marshalled_sensitive_and_name_digest, + sizeof(uint16_t), &digest_size_info); + +- const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(name_alg); ++ const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(name_alg); + if (!md) { + LOG_ERR("Algorithm not supported: %x", name_alg); + return false; +@@ -461,7 +461,7 @@ bool tpm2_identity_create_name(TPM2B_PUBLIC *public, TPM2B_NAME *pubname) { + &tpmt_marshalled_size); + + // Step 3 - Hash the data into name just past the alg type. +- const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(name_alg); ++ const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(name_alg); + if (!md) { + LOG_ERR("Algorithm not supported: %x", name_alg); + return false; +diff --git a/lib/tpm2_kdfa.c b/lib/tpm2_kdfa.c +index 5747b3ca..c8d0a2e1 100644 +--- a/lib/tpm2_kdfa.c ++++ b/lib/tpm2_kdfa.c +@@ -34,7 +34,7 @@ TSS2_RC tpm2_kdfa(TPMI_ALG_HASH hash_alg, TPM2B *key, char *label, + + i = 1; + +- const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(hash_alg); ++ const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(hash_alg); + if (!md) { + LOG_ERR("Algorithm not supported for hmac: %x", hash_alg); + return TPM2_RC_HASH; +diff --git a/lib/tpm2_kdfe.c b/lib/tpm2_kdfe.c +index aa4d3e0b..84718b9f 100644 +--- a/lib/tpm2_kdfe.c ++++ b/lib/tpm2_kdfe.c +@@ -42,7 +42,7 @@ TSS2_RC tpm2_kdfe( + tpm2_util_concat_buffer(&hash_input, (TPM2B *) party_u); + tpm2_util_concat_buffer(&hash_input, (TPM2B *) party_v); + +- const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(hash_alg); ++ const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(hash_alg); + if (!md) { + LOG_ERR("Algorithm not supported: %x", hash_alg); + return TPM2_RC_HASH; +diff --git a/lib/tpm2_openssl.c b/lib/tpm2_openssl.c +index cdce92f8..9cc362af 100644 +--- a/lib/tpm2_openssl.c ++++ b/lib/tpm2_openssl.c +@@ -55,7 +55,7 @@ int tpm2_openssl_halgid_from_tpmhalg(TPMI_ALG_HASH algorithm) { + /* no return, not possible */ + } + +-const EVP_MD *tpm2_openssl_halg_from_tpmhalg(TPMI_ALG_HASH algorithm) { ++const EVP_MD *tpm2_openssl_md_from_tpmhalg(TPMI_ALG_HASH algorithm) { + + switch (algorithm) { + case TPM2_ALG_SHA1: +@@ -77,7 +77,7 @@ bool tpm2_openssl_hash_compute_data(TPMI_ALG_HASH halg, BYTE *buffer, + + bool result = false; + +- const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(halg); ++ const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(halg); + if (!md) { + return false; + } +@@ -121,7 +121,7 @@ bool tpm2_openssl_pcr_extend(TPMI_ALG_HASH halg, BYTE *pcr, + + bool result = false; + +- const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(halg); ++ const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(halg); + if (!md) { + return false; + } +@@ -170,7 +170,7 @@ bool tpm2_openssl_hash_pcr_values(TPMI_ALG_HASH halg, TPML_DIGEST *digests, + + bool result = false; + +- const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(halg); ++ const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(halg); + if (!md) { + return false; + } +@@ -222,7 +222,7 @@ bool tpm2_openssl_hash_pcr_banks(TPMI_ALG_HASH hash_alg, + UINT32 vi = 0, di = 0, i; + bool result = false; + +- const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(hash_alg); ++ const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(hash_alg); + if (!md) { + return false; + } +@@ -299,7 +299,7 @@ bool tpm2_openssl_hash_pcr_banks_le(TPMI_ALG_HASH hash_alg, + UINT32 vi = 0, di = 0, i; + bool result = false; + +- const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(hash_alg); ++ const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(hash_alg); + if (!md) { + return false; + } +diff --git a/lib/tpm2_openssl.h b/lib/tpm2_openssl.h +index 78cb826a..b757baa5 100644 +--- a/lib/tpm2_openssl.h ++++ b/lib/tpm2_openssl.h +@@ -48,7 +48,7 @@ int tpm2_openssl_halgid_from_tpmhalg(TPMI_ALG_HASH algorithm); + * @return + * A pointer to a message digester or NULL on failure. + */ +-const EVP_MD *tpm2_openssl_halg_from_tpmhalg(TPMI_ALG_HASH algorithm); ++const EVP_MD *tpm2_openssl_md_from_tpmhalg(TPMI_ALG_HASH algorithm); + + /** + * Hash a byte buffer. +diff --git a/lib/tpm2_util.c b/lib/tpm2_util.c +index d2c654db..c4dc68e4 100644 +--- a/lib/tpm2_util.c ++++ b/lib/tpm2_util.c +@@ -579,7 +579,7 @@ bool tpm2_util_calc_unique(TPMI_ALG_HASH name_alg, + memcpy(buf.buffer, seed->buffer, seed->size); + memcpy(&buf.buffer[seed->size], key->buffer, key->size); + +- const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(name_alg); ++ const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(name_alg); + if (!md) { + LOG_ERR("Algorithm not supported: %x", name_alg); + return false; +@@ -951,7 +951,7 @@ bool tpm2_calq_qname(TPM2B_NAME *pqname, + // QNB ≔ HB (QNA || NAMEB) + bool result = false; + +- const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(halg); ++ const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(halg); + + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + if (!mdctx) { +diff --git a/tools/misc/tpm2_checkquote.c b/tools/misc/tpm2_checkquote.c +index ca78238e..5e0c42a5 100644 +--- a/tools/misc/tpm2_checkquote.c ++++ b/tools/misc/tpm2_checkquote.c +@@ -74,7 +74,7 @@ static bool verify(void) { + /* get the digest alg */ + /* TODO SPlit loading on plain vs tss format to detect the hash alg */ + /* If its a plain sig we need -g */ +- const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(ctx.halg); ++ const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(ctx.halg); + // TODO error handling + + int rc = EVP_PKEY_verify_init(pkey_ctx); +-- +2.31.1 + diff --git a/SOURCES/0012-openssl-Use-EVP_MAC_update-instead-HMAC_Update-on-Op.patch b/SOURCES/0012-openssl-Use-EVP_MAC_update-instead-HMAC_Update-on-Op.patch new file mode 100644 index 0000000..beaab9f --- /dev/null +++ b/SOURCES/0012-openssl-Use-EVP_MAC_update-instead-HMAC_Update-on-Op.patch @@ -0,0 +1,103 @@ +From d67cbd4e6dc7ac83fd0c06a382a89d12f921628a Mon Sep 17 00:00:00 2001 +From: Petr Gotthard +Date: Sun, 15 Aug 2021 11:54:00 +0200 +Subject: [PATCH 11/17] openssl: Use EVP_MAC_update instead HMAC_Update on + OpenSSL >= 3.0.0 + +The HMAC_Update is deprecated in OpenSSL 3.0, but the replacement +EVP_MAC_update was added in OpenSSL 3.0, so version specific code is +needed. + +Signed-off-by: Petr Gotthard +--- + lib/tpm2_kdfa.c | 35 +++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/lib/tpm2_kdfa.c b/lib/tpm2_kdfa.c +index c8d0a2e1..5eb8d558 100644 +--- a/lib/tpm2_kdfa.c ++++ b/lib/tpm2_kdfa.c +@@ -2,6 +2,13 @@ + + #include + ++#include ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++#include ++#else ++#include ++#endif ++ + #include "log.h" + #include "tpm2_kdfa.h" + #include "tpm2_openssl.h" +@@ -40,13 +47,27 @@ TSS2_RC tpm2_kdfa(TPMI_ALG_HASH hash_alg, TPM2B *key, char *label, + return TPM2_RC_HASH; + } + ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + HMAC_CTX *ctx = HMAC_CTX_new(); ++#else ++ EVP_MAC *hmac = EVP_MAC_fetch(NULL, "HMAC", NULL); ++ EVP_MAC_CTX *ctx = EVP_MAC_CTX_new(hmac); ++#endif + if (!ctx) { + LOG_ERR("HMAC context allocation failed"); + return TPM2_RC_MEMORY; + } + ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + int rc = HMAC_Init_ex(ctx, key->buffer, key->size, md, NULL); ++#else ++ OSSL_PARAM params[2]; ++ ++ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_DIGEST, ++ (char *)EVP_MD_get0_name(md), 0); ++ params[1] = OSSL_PARAM_construct_end(); ++ int rc = EVP_MAC_init(ctx, key->buffer, key->size, params); ++#endif + if (!rc) { + LOG_ERR("HMAC Init failed: %s", ERR_error_string(rc, NULL)); + rval = TPM2_RC_MEMORY; +@@ -71,7 +92,11 @@ TSS2_RC tpm2_kdfa(TPMI_ALG_HASH hash_alg, TPM2B *key, char *label, + int c; + for (c = 0; c < j; c++) { + TPM2B_DIGEST *digest = buffer_list[c]; ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + int rc = HMAC_Update(ctx, digest->buffer, digest->size); ++#else ++ int rc = EVP_MAC_update(ctx, digest->buffer, digest->size); ++#endif + if (!rc) { + LOG_ERR("HMAC Update failed: %s", ERR_error_string(rc, NULL)); + rval = TPM2_RC_MEMORY; +@@ -79,8 +104,13 @@ TSS2_RC tpm2_kdfa(TPMI_ALG_HASH hash_alg, TPM2B *key, char *label, + } + } + ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + unsigned size = sizeof(tmpResult.buffer); + int rc = HMAC_Final(ctx, tmpResult.buffer, &size); ++#else ++ size_t size; ++ int rc = EVP_MAC_final(ctx, tmpResult.buffer, &size, sizeof(tmpResult.buffer)); ++#endif + if (!rc) { + LOG_ERR("HMAC Final failed: %s", ERR_error_string(rc, NULL)); + rval = TPM2_RC_MEMORY; +@@ -100,7 +130,12 @@ TSS2_RC tpm2_kdfa(TPMI_ALG_HASH hash_alg, TPM2B *key, char *label, + result_key->size = bytes; + + err: ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + HMAC_CTX_free(ctx); ++#else ++ EVP_MAC_CTX_free(ctx); ++ EVP_MAC_free(hmac); ++#endif + + return rval; + } +-- +2.31.1 + diff --git a/SOURCES/0013-openssl-Remove-unnecessary-compatibility-function.patch b/SOURCES/0013-openssl-Remove-unnecessary-compatibility-function.patch new file mode 100644 index 0000000..c5ca0b9 --- /dev/null +++ b/SOURCES/0013-openssl-Remove-unnecessary-compatibility-function.patch @@ -0,0 +1,50 @@ +From d295e6214ec4562b3940ac4a88178a260e656929 Mon Sep 17 00:00:00 2001 +From: Petr Gotthard +Date: Sun, 15 Aug 2021 13:50:36 +0200 +Subject: [PATCH 12/17] openssl: Remove unnecessary compatibility function + +This was required for OpenSSL < 1.1.0 only. + +Signed-off-by: Petr Gotthard +--- + lib/tpm2_openssl.c | 24 ------------------------ + 1 file changed, 24 deletions(-) + +diff --git a/lib/tpm2_openssl.c b/lib/tpm2_openssl.c +index 9cc362af..ea1d6c3b 100644 +--- a/lib/tpm2_openssl.c ++++ b/lib/tpm2_openssl.c +@@ -14,30 +14,6 @@ + #include "tpm2_openssl.h" + #include "tpm2_systemdeps.h" + +-/* compatibility function for OpenSSL versions < 1.1.0 */ +-#if OPENSSL_VERSION_NUMBER < 0x10100000L +-static int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) { +- int r; +- int topad; +- int islen; +- +- islen = BN_num_bytes(a); +- +- if (tolen < islen) +- return -1; +- +- topad = tolen - islen; +- +- memset(to, 0x00, topad); +- r = BN_bn2bin(a, to + topad); +- if (r == 0) { +- return -1; +- } +- +- return tolen; +-} +-#endif +- + int tpm2_openssl_halgid_from_tpmhalg(TPMI_ALG_HASH algorithm) { + + switch (algorithm) { +-- +2.31.1 + diff --git a/SOURCES/0014-openssl-Implement-EVP_PKEY-based-key-import.patch b/SOURCES/0014-openssl-Implement-EVP_PKEY-based-key-import.patch new file mode 100644 index 0000000..aa7851d --- /dev/null +++ b/SOURCES/0014-openssl-Implement-EVP_PKEY-based-key-import.patch @@ -0,0 +1,555 @@ +From 7852dfbda959aa326de7dcd341f6e4808d918e15 Mon Sep 17 00:00:00 2001 +From: Petr Gotthard +Date: Sun, 15 Aug 2021 14:01:06 +0200 +Subject: [PATCH 13/17] openssl: Implement EVP_PKEY based key import + +The `RSA_KEY` and `EC_KEY` are not publicly available in OpenSSL 3.0 and +the generic `EVP_PKEY` must be used instead. +Since import of raw keys still requires access to the internal structures +the OpenSSL 3.0 introduced a completely new approach to access key internals. + +Signed-off-by: Petr Gotthard +--- + lib/tpm2_openssl.c | 297 ++++++++++++++++++++++++++++----------------- + lib/tpm2_openssl.h | 12 -- + 2 files changed, 184 insertions(+), 125 deletions(-) + +diff --git a/lib/tpm2_openssl.c b/lib/tpm2_openssl.c +index ea1d6c3b..036127c3 100644 +--- a/lib/tpm2_openssl.c ++++ b/lib/tpm2_openssl.c +@@ -6,7 +6,11 @@ + #include + + #include ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + #include ++#else ++#include ++#endif + + #include "files.h" + #include "log.h" +@@ -516,8 +520,9 @@ static bool handle_ossl_pass(const char *passin, char **pass) { + return pfn(passin, pass); + } + +-static bool load_public_RSA_from_key(RSA *k, TPM2B_PUBLIC *pub) { ++static bool load_public_RSA_from_key(EVP_PKEY *key, TPM2B_PUBLIC *pub) { + ++ bool result = false; + TPMT_PUBLIC *pt = &pub->publicArea; + pt->type = TPM2_ALG_RSA; + +@@ -532,11 +537,33 @@ static bool load_public_RSA_from_key(RSA *k, TPM2B_PUBLIC *pub) { + sym->keyBits.sym = 0; + sym->mode.sym = TPM2_ALG_NULL; + ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + const BIGNUM *n; /* modulus */ + const BIGNUM *e; /* public key exponent */ + ++ RSA *k = EVP_PKEY_get0_RSA(key); ++ if (!k) { ++ LOG_ERR("Could not retrieve RSA key"); ++ goto out; ++ } ++ + RSA_get0_key(k, &n, &e, NULL); ++#else ++ BIGNUM *n = NULL; /* modulus */ ++ BIGNUM *e = NULL; /* public key exponent */ ++ ++ int rc = EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_RSA_N, &n); ++ if (!rc) { ++ LOG_ERR("Could not read public modulus N"); ++ goto out; ++ } + ++ rc = EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_RSA_E, &e); ++ if (!rc) { ++ LOG_ERR("Could not read public exponent E"); ++ goto out; ++ } ++#endif + /* + * The size of the modulus is the key size in RSA, store this as the + * keyBits in the RSA details. +@@ -549,7 +576,7 @@ static bool load_public_RSA_from_key(RSA *k, TPM2B_PUBLIC *pub) { + break; + default: + LOG_ERR("RSA key-size %u is not supported", rdetail->keyBits); +- return false; ++ goto out; + } + + /* copy the modulus to the unique RSA field */ +@@ -557,47 +584,25 @@ static bool load_public_RSA_from_key(RSA *k, TPM2B_PUBLIC *pub) { + int success = BN_bn2bin(n, pt->unique.rsa.buffer); + if (!success) { + LOG_ERR("Could not copy public modulus N"); +- return false; +- } +- +- /*Make sure that we can fit the exponent into a UINT32 */ +- unsigned e_size = BN_num_bytes(e); +- if (e_size > sizeof(rdetail->exponent)) { +- LOG_ERR( +- "Exponent is too big. Got %d expected less than or equal to %zu", +- e_size, sizeof(rdetail->exponent)); +- return false; +- } +- +- /* +- * Copy the exponent into the field. +- * Returns 1 on success false on error. +- */ +- return BN_bn2bin(e, (unsigned char *) &rdetail->exponent); +-} +- +-static RSA *tpm2_openssl_get_public_RSA_from_pem(FILE *f, const char *path) { +- +- /* +- * Public PEM files appear in two formats: +- * 1. PEM format, read with PEM_read_RSA_PUBKEY +- * 2. PKCS#1 format, read with PEM_read_RSAPublicKey +- * +- * See: +- * - https://stackoverflow.com/questions/7818117/why-i-cant-read-openssl-generated-rsa-pub-key-with-pem-read-rsapublickey +- */ +- RSA *pub = PEM_read_RSA_PUBKEY(f, NULL, NULL, NULL); +- if (!pub) { +- pub = PEM_read_RSAPublicKey(f, NULL, NULL, NULL); ++ goto out; + } + +- if (!pub) { +- ERR_print_errors_fp(stderr); +- LOG_ERR("Reading public PEM file \"%s\" failed", path); +- return NULL; ++ unsigned long exp = BN_get_word(e); ++ if (exp == 0xffffffffL) { ++ LOG_ERR("Could not copy public exponent E"); ++ goto out; + } ++ rdetail->exponent = exp; + +- return pub; ++ result = true; ++out: ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ /* k,n,e point to internal structrues and must not be freed after use */ ++#else ++ BN_free(n); ++ BN_free(e); ++#endif ++ return result; + } + + static bool load_public_RSA_from_pem(FILE *f, const char *path, +@@ -611,15 +616,19 @@ static bool load_public_RSA_from_pem(FILE *f, const char *path, + * See: + * - https://stackoverflow.com/questions/7818117/why-i-cant-read-openssl-generated-rsa-pub-key-with-pem-read-rsapublickey + */ +- RSA *k = tpm2_openssl_get_public_RSA_from_pem(f, path); ++ EVP_PKEY *k = PEM_read_PUBKEY(f, NULL, NULL, NULL); + if (!k) { +- /* tpm2_openssl_get_public_RSA_from_pem() should already log errors */ ++ ERR_print_errors_fp(stderr); ++ LOG_ERR("Reading public PEM file \"%s\" failed", path); + return false; + } + +- bool result = load_public_RSA_from_key(k, pub); ++ bool result = false; ++ if (EVP_PKEY_base_id(k) == EVP_PKEY_RSA) { ++ result = load_public_RSA_from_key(k, pub); ++ } + +- RSA_free(k); ++ EVP_PKEY_free(k); + + return result; + } +@@ -682,39 +691,41 @@ int tpm2_ossl_curve_to_nid(TPMI_ECC_CURVE curve) { + return -1; + } + +-static bool load_public_ECC_from_key(EC_KEY *k, TPM2B_PUBLIC *pub) { ++static bool load_public_ECC_from_key(EVP_PKEY *key, TPM2B_PUBLIC *pub) { + ++ BIGNUM *y = NULL; ++ BIGNUM *x = NULL; ++ int nid; ++ unsigned keysize; + bool result = false; + +- BIGNUM *y = BN_new(); +- BIGNUM *x = BN_new(); +- if (!x || !y) { +- LOG_ERR("oom"); +- goto out; +- } +- + /* + * Set the algorithm type + */ + pub->publicArea.type = TPM2_ALG_ECC; ++ TPMS_ECC_PARMS *pp = &pub->publicArea.parameters.eccDetail; + + /* +- * Get the curve type ++ * Get the curve type and the public key (X and Y) + */ +- const EC_GROUP *group = EC_KEY_get0_group(k); +- int nid = EC_GROUP_get_curve_name(group); ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ EC_KEY *k = EVP_PKEY_get0_EC_KEY(key); ++ if (!k) { ++ LOG_ERR("Could not retrieve ECC key"); ++ goto out; ++ } + +- TPMS_ECC_PARMS *pp = &pub->publicArea.parameters.eccDetail; +- TPM2_ECC_CURVE curve_id = ossl_nid_to_curve(nid); // Not sure what lines up with NIST 256... +- if (curve_id == TPM2_ALG_ERROR) { ++ y = BN_new(); ++ x = BN_new(); ++ if (!x || !y) { ++ LOG_ERR("oom"); + goto out; + } + +- pp->curveID = curve_id; ++ const EC_GROUP *group = EC_KEY_get0_group(k); ++ nid = EC_GROUP_get_curve_name(group); ++ keysize = (EC_GROUP_get_degree(group) + 7) / 8; + +- /* +- * Set the unique data to the public key. +- */ + const EC_POINT *point = EC_KEY_get0_public_key(k); + + int ret = EC_POINT_get_affine_coordinates_tss(group, point, x, y, NULL); +@@ -722,6 +733,39 @@ static bool load_public_ECC_from_key(EC_KEY *k, TPM2B_PUBLIC *pub) { + LOG_ERR("Could not get X and Y affine coordinates"); + goto out; + } ++#else ++ char curve_name[80]; ++ ++ int rc = EVP_PKEY_get_utf8_string_param(key, OSSL_PKEY_PARAM_GROUP_NAME, ++ curve_name, sizeof(curve_name), NULL); ++ if (!rc) { ++ LOG_ERR("Could not read ECC curve name"); ++ goto out; ++ } ++ nid = OBJ_txt2nid(curve_name); ++ keysize = (EVP_PKEY_bits(key) + 7) / 8; ++ ++ rc = EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_EC_PUB_X, &x); ++ if (!rc) { ++ LOG_ERR("Could not read public X coordinate"); ++ goto out; ++ } ++ ++ rc = EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_EC_PUB_Y, &y); ++ if (!rc) { ++ LOG_ERR("Could not read public Y coordinate"); ++ goto out; ++ } ++#endif ++ ++ /* ++ * Set the curve type ++ */ ++ TPM2_ECC_CURVE curve_id = ossl_nid_to_curve(nid); // Not sure what lines up with NIST 256... ++ if (curve_id == TPM2_ALG_ERROR) { ++ goto out; ++ } ++ pp->curveID = curve_id; + + /* + * Copy the X and Y coordinate data into the ECC unique field, +@@ -730,28 +774,26 @@ static bool load_public_ECC_from_key(EC_KEY *k, TPM2B_PUBLIC *pub) { + TPM2B_ECC_PARAMETER *X = &pub->publicArea.unique.ecc.x; + TPM2B_ECC_PARAMETER *Y = &pub->publicArea.unique.ecc.y; + +- unsigned x_size = (EC_GROUP_get_degree(group) + 7) / 8; +- if (x_size > sizeof(X->buffer)) { ++ if (keysize > sizeof(X->buffer)) { + LOG_ERR("X coordinate is too big. Got %u expected less than or equal to" +- " %zu", x_size, sizeof(X->buffer)); ++ " %zu", keysize, sizeof(X->buffer)); + goto out; + } + +- unsigned y_size = (EC_GROUP_get_degree(group) + 7) / 8; +- if (y_size > sizeof(Y->buffer)) { ++ if (keysize > sizeof(Y->buffer)) { + LOG_ERR("X coordinate is too big. Got %u expected less than or equal to" +- " %zu", y_size, sizeof(Y->buffer)); ++ " %zu", keysize, sizeof(Y->buffer)); + goto out; + } + +- X->size = BN_bn2binpad(x, X->buffer, x_size); +- if (X->size != x_size) { ++ X->size = BN_bn2binpad(x, X->buffer, keysize); ++ if (X->size != keysize) { + LOG_ERR("Error converting X point BN to binary"); + goto out; + } + +- Y->size = BN_bn2binpad(y, Y->buffer, y_size); +- if (Y->size != y_size) { ++ Y->size = BN_bn2binpad(y, Y->buffer, keysize); ++ if (Y->size != keysize) { + LOG_ERR("Error converting Y point BN to binary"); + goto out; + } +@@ -771,43 +813,28 @@ static bool load_public_ECC_from_key(EC_KEY *k, TPM2B_PUBLIC *pub) { + sym->mode.sym = TPM2_ALG_NULL; + + result = true; +- + out: +- if (x) { +- BN_free(x); +- } +- if (y) { +- BN_free(y); +- } +- ++ BN_free(x); ++ BN_free(y); + return result; + } + +-EC_KEY *tpm2_openssl_get_public_ECC_from_pem(FILE *f, const char *path) { +- +- EC_KEY *pub = PEM_read_EC_PUBKEY(f, NULL, NULL, NULL); +- if (!pub) { +- ERR_print_errors_fp(stderr); +- LOG_ERR("Reading public PEM file \"%s\" failed", path); +- return NULL; +- } +- +- return pub; +-} +- + static bool load_public_ECC_from_pem(FILE *f, const char *path, + TPM2B_PUBLIC *pub) { + +- EC_KEY *k = tpm2_openssl_get_public_ECC_from_pem(f, path); ++ EVP_PKEY *k = PEM_read_PUBKEY(f, NULL, NULL, NULL); + if (!k) { + ERR_print_errors_fp(stderr); + LOG_ERR("Reading PEM file \"%s\" failed", path); + return false; + } + +- bool result = load_public_ECC_from_key(k, pub); ++ bool result = false; ++ if (EVP_PKEY_base_id(k) == EVP_PKEY_EC) { ++ result = load_public_ECC_from_key(k, pub); ++ } + +- EC_KEY_free(k); ++ EVP_PKEY_free(k); + + return result; + } +@@ -852,11 +879,27 @@ static bool load_public_AES_from_file(FILE *f, const char *path, + return tpm2_util_calc_unique(name_alg, key, seed, unique); + } + +-static bool load_private_RSA_from_key(RSA *k, TPM2B_SENSITIVE *priv) { ++static bool load_private_RSA_from_key(EVP_PKEY *key, TPM2B_SENSITIVE *priv) { + +- const BIGNUM *p; /* the private key exponent */ ++ bool result = false; ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ const BIGNUM *p = NULL; /* the private key exponent */ + ++ RSA *k = EVP_PKEY_get0_RSA(key); ++ if (!k) { ++ LOG_ERR("Could not retrieve RSA key"); ++ goto out; ++ } + RSA_get0_factors(k, &p, NULL); ++#else ++ BIGNUM *p = NULL; /* the private key exponent */ ++ ++ int rc = EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_RSA_FACTOR1, &p); ++ if (!rc) { ++ LOG_ERR("Could not read private key"); ++ goto out; ++ } ++#endif + + TPMT_SENSITIVE *sa = &priv->sensitiveArea; + +@@ -868,7 +911,7 @@ static bool load_private_RSA_from_key(RSA *k, TPM2B_SENSITIVE *priv) { + if (priv_bytes > sizeof(pkr->buffer)) { + LOG_ERR("Expected prime \"d\" to be less than or equal to %zu," + " got: %u", sizeof(pkr->buffer), priv_bytes); +- return false; ++ goto out; + } + + pkr->size = priv_bytes; +@@ -877,10 +920,16 @@ static bool load_private_RSA_from_key(RSA *k, TPM2B_SENSITIVE *priv) { + if (!success) { + ERR_print_errors_fp(stderr); + LOG_ERR("Could not copy private exponent \"d\""); +- return false; ++ goto out; + } +- +- return true; ++ result = true; ++out: ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ /* k,p point to internal structrues and must not be freed after use */ ++#else ++ BN_free(p); ++#endif ++ return result; + } + + bool tpm2_openssl_load_public(const char *path, TPMI_ALG_PUBLIC alg, +@@ -912,8 +961,9 @@ bool tpm2_openssl_load_public(const char *path, TPMI_ALG_PUBLIC alg, + return result; + } + +-static bool load_private_ECC_from_key(EC_KEY *k, TPM2B_SENSITIVE *priv) { ++static bool load_private_ECC_from_key(EVP_PKEY *key, TPM2B_SENSITIVE *priv) { + ++ bool result = false; + /* + * private data + */ +@@ -921,22 +971,45 @@ static bool load_private_ECC_from_key(EC_KEY *k, TPM2B_SENSITIVE *priv) { + + TPM2B_ECC_PARAMETER *p = &priv->sensitiveArea.sensitive.ecc; + ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ EC_KEY *k = EVP_PKEY_get0_EC_KEY(key); ++ if (!k) { ++ LOG_ERR("Could not retrieve ECC key"); ++ goto out; ++ } ++ + const EC_GROUP *group = EC_KEY_get0_group(k); + const BIGNUM *b = EC_KEY_get0_private_key(k); +- + unsigned priv_bytes = (EC_GROUP_get_degree(group) + 7) / 8; ++#else ++ BIGNUM *b = NULL; /* the private key exponent */ ++ ++ int rc = EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_PRIV_KEY, &b); ++ if (!rc) { ++ LOG_ERR("Could not read ECC private key"); ++ goto out; ++ } ++ unsigned priv_bytes = (EVP_PKEY_bits(key) + 7) / 8; ++#endif ++ + if (priv_bytes > sizeof(p->buffer)) { + LOG_ERR("Expected ECC private portion to be less than or equal to %zu," + " got: %u", sizeof(p->buffer), priv_bytes); +- return false; ++ goto out; + } + + p->size = BN_bn2binpad(b, p->buffer, priv_bytes); + if (p->size != priv_bytes) { +- return false; ++ goto out; + } +- +- return true; ++ result = true; ++out: ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ /* k,b point to internal structrues and must not be freed after use */ ++#else ++ BN_free(b); ++#endif ++ return result; + } + + static tpm2_openssl_load_rc load_private_ECC_from_pem(FILE *f, const char *path, +@@ -950,8 +1023,7 @@ static tpm2_openssl_load_rc load_private_ECC_from_pem(FILE *f, const char *path, + return lprc_error; + } + +- EC_KEY *k = PEM_read_ECPrivateKey(f, NULL, +- NULL, (void *) pass); ++ EVP_PKEY *k = PEM_read_PrivateKey(f, NULL, NULL, (void *) pass); + free(pass); + if (!k) { + ERR_print_errors_fp(stderr); +@@ -976,14 +1048,14 @@ static tpm2_openssl_load_rc load_private_ECC_from_pem(FILE *f, const char *path, + rc |= lprc_public; + + out: +- EC_KEY_free(k); ++ EVP_PKEY_free(k); + return rc; + } + + static tpm2_openssl_load_rc load_private_RSA_from_pem(FILE *f, const char *path, + const char *passin, TPM2B_PUBLIC *pub, TPM2B_SENSITIVE *priv) { + +- RSA *k = NULL; ++ EVP_PKEY *k = NULL; + + tpm2_openssl_load_rc rc = lprc_error; + +@@ -993,8 +1065,7 @@ static tpm2_openssl_load_rc load_private_RSA_from_pem(FILE *f, const char *path, + return lprc_error; + } + +- k = PEM_read_RSAPrivateKey(f, NULL, +- NULL, (void *) pass); ++ k = PEM_read_PrivateKey(f, NULL, NULL, (void *) pass); + free(pass); + if (!k) { + ERR_print_errors_fp(stderr); +@@ -1016,7 +1087,7 @@ static tpm2_openssl_load_rc load_private_RSA_from_pem(FILE *f, const char *path, + rc |= lprc_public; + } + out: +- RSA_free(k); ++ EVP_PKEY_free(k); + return rc; + } + +diff --git a/lib/tpm2_openssl.h b/lib/tpm2_openssl.h +index b757baa5..5579ae45 100644 +--- a/lib/tpm2_openssl.h ++++ b/lib/tpm2_openssl.h +@@ -196,18 +196,6 @@ tpm2_openssl_load_rc tpm2_openssl_load_private(const char *path, + bool tpm2_openssl_load_public(const char *path, TPMI_ALG_PUBLIC alg, + TPM2B_PUBLIC *pub); + +-/** +- * Retrieves a public portion of an ECC key from a PEM file. +- * +- * @param f +- * The FILE object that is open for reading the path. +- * @param path +- * The path to load from. +- * @return +- * The public structure. +- */ +-EC_KEY* tpm2_openssl_get_public_ECC_from_pem(FILE *f, const char *path); +- + /** + * Maps an ECC curve to an openssl nid value. + * @param curve +-- +2.31.1 + diff --git a/SOURCES/0015-openssl-Implement-EVP_PKEY-based-key-export.patch b/SOURCES/0015-openssl-Implement-EVP_PKEY-based-key-export.patch new file mode 100644 index 0000000..8b72443 --- /dev/null +++ b/SOURCES/0015-openssl-Implement-EVP_PKEY-based-key-export.patch @@ -0,0 +1,484 @@ +From e34d393d7c73a58b3bf6fccbe88ea1eedfe1d7b7 Mon Sep 17 00:00:00 2001 +From: Petr Gotthard +Date: Sun, 15 Aug 2021 15:58:28 +0200 +Subject: [PATCH 14/17] openssl: Implement EVP_PKEY based key export + +The `RSA_KEY` and `EC_KEY` are not publicly available in OpenSSL 3.0 and +the generic `EVP_PKEY` must be used instead. + +Signed-off-by: Petr Gotthard +--- + lib/tpm2_convert.c | 319 ++++++++++++++++++++++++++++++++------------- + lib/tpm2_convert.h | 20 +++ + 2 files changed, 245 insertions(+), 94 deletions(-) + +diff --git a/lib/tpm2_convert.c b/lib/tpm2_convert.c +index cc1c18ab..986fc1a7 100644 +--- a/lib/tpm2_convert.c ++++ b/lib/tpm2_convert.c +@@ -9,6 +9,13 @@ + #include + #include + #include ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++#include ++#else ++#include ++#include ++#include ++#endif + + #include "files.h" + #include "log.h" +@@ -70,36 +77,49 @@ bool tpm2_convert_pubkey_save(TPM2B_PUBLIC *public, + return false; + } + +-static bool convert_pubkey_RSA(TPMT_PUBLIC *public, +- tpm2_convert_pubkey_fmt format, BIO *bio) { ++EVP_PKEY *convert_pubkey_RSA(TPMT_PUBLIC *public) { + +- bool ret = false; +- RSA *ssl_rsa_key = NULL; ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ RSA *rsa_key = NULL; ++#else ++ OSSL_PARAM_BLD *build = NULL; ++ OSSL_PARAM *params = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++#endif + BIGNUM *e = NULL, *n = NULL; ++ EVP_PKEY *pkey = NULL; + + UINT32 exponent = (public->parameters).rsaDetail.exponent; + if (exponent == 0) { + exponent = 0x10001; + } + +- // OpenSSL expects this in network byte order +- exponent = tpm2_util_hton_32(exponent); +- ssl_rsa_key = RSA_new(); +- if (!ssl_rsa_key) { +- print_ssl_error("Failed to allocate OpenSSL RSA structure"); ++ n = BN_bin2bn(public->unique.rsa.buffer, public->unique.rsa.size, NULL); ++ if (!n) { ++ print_ssl_error("Failed to convert data to SSL internal format"); + goto error; + } + +- e = BN_bin2bn((void*) &exponent, sizeof(exponent), NULL); +- n = BN_bin2bn(public->unique.rsa.buffer, public->unique.rsa.size, +- NULL); ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ rsa_key = RSA_new(); ++ if (!rsa_key) { ++ print_ssl_error("Failed to allocate OpenSSL RSA structure"); ++ goto error; ++ } + +- if (!n || !e) { ++ e = BN_new(); ++ if (!e) { ++ print_ssl_error("Failed to convert data to SSL internal format"); ++ goto error; ++ } ++ int rc = BN_set_word(e, exponent); ++ if (!rc) { + print_ssl_error("Failed to convert data to SSL internal format"); + goto error; + } + +- if (!RSA_set0_key(ssl_rsa_key, n, e, NULL)) { ++ rc = RSA_set0_key(rsa_key, n, e, NULL); ++ if (!rc) { + print_ssl_error("Failed to set RSA modulus and exponent components"); + goto error; + } +@@ -107,162 +127,273 @@ static bool convert_pubkey_RSA(TPMT_PUBLIC *public, + /* modulus and exponent components are now owned by the RSA struct */ + n = e = NULL; + +- int ssl_res = 0; ++ pkey = EVP_PKEY_new(); ++ if (!pkey) { ++ print_ssl_error("Failed to allocate OpenSSL EVP structure"); ++ goto error; ++ } + +- switch (format) { +- case pubkey_format_pem: +- ssl_res = PEM_write_bio_RSA_PUBKEY(bio, ssl_rsa_key); +- break; +- case pubkey_format_der: +- ssl_res = i2d_RSA_PUBKEY_bio(bio, ssl_rsa_key); +- break; +- default: +- LOG_ERR("Invalid OpenSSL target format %d encountered", format); ++ rc = EVP_PKEY_assign_RSA(pkey, rsa_key); ++ if (!rc) { ++ print_ssl_error("Failed to set OpenSSL EVP structure"); ++ EVP_PKEY_free(pkey); ++ pkey = NULL; ++ goto error; ++ } ++ /* rsa key is now owner by the EVP_PKEY struct */ ++ rsa_key = NULL; ++#else ++ build = OSSL_PARAM_BLD_new(); ++ if (!build) { ++ print_ssl_error("Failed to allocate OpenSSL parameters"); + goto error; + } + +- if (ssl_res <= 0) { +- print_ssl_error("OpenSSL public key conversion failed"); ++ int rc = OSSL_PARAM_BLD_push_BN(build, OSSL_PKEY_PARAM_RSA_N, n); ++ if (!rc) { ++ print_ssl_error("Failed to set RSA modulus"); + goto error; + } + +- ret = true; ++ rc = OSSL_PARAM_BLD_push_uint32(build, OSSL_PKEY_PARAM_RSA_E, exponent); ++ if (!rc) { ++ print_ssl_error("Failed to set RSA exponent"); ++ goto error; ++ } + +- error: if (n) { +- BN_free(n); ++ params = OSSL_PARAM_BLD_to_param(build); ++ if (!params) { ++ print_ssl_error("Failed to build OpenSSL parameters"); ++ goto error; + } +- if (e) { +- BN_free(e); ++ ++ ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); ++ if (!ctx) { ++ print_ssl_error("Failed to allocate RSA key context"); ++ goto error; + } +- if (ssl_rsa_key) { +- RSA_free(ssl_rsa_key); ++ ++ rc = EVP_PKEY_fromdata_init(ctx); ++ if (rc <= 0) { ++ print_ssl_error("Failed to initialize RSA key creation"); ++ goto error; + } + +- return ret; ++ rc = EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params); ++ if (rc <= 0) { ++ print_ssl_error("Failed to create a RSA public key"); ++ goto error; ++ } ++#endif ++error: ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ RSA_free(rsa_key); ++#else ++ EVP_PKEY_CTX_free(ctx); ++ OSSL_PARAM_free(params); ++ OSSL_PARAM_BLD_free(build); ++#endif ++ BN_free(n); ++ BN_free(e); ++ return pkey; + } + +-static bool convert_pubkey_ECC(TPMT_PUBLIC *public, +- tpm2_convert_pubkey_fmt format, BIO *bio) { ++EVP_PKEY *convert_pubkey_ECC(TPMT_PUBLIC *public) { + + BIGNUM *x = NULL; + BIGNUM *y = NULL; +- EC_KEY *key = NULL; + EC_POINT *point = NULL; +- const EC_GROUP *group = NULL; +- +- bool result = false; ++ EC_GROUP *group = NULL; ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ EC_KEY *ec_key = NULL; ++#else ++ OSSL_PARAM_BLD *build = NULL; ++ OSSL_PARAM *params = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ unsigned char *puboct = NULL; ++ size_t bsize; ++#endif ++ EVP_PKEY *pkey = NULL; + + TPMS_ECC_PARMS *tpm_ecc = &public->parameters.eccDetail; + TPMS_ECC_POINT *tpm_point = &public->unique.ecc; + ++ /* ++ * Set the affine coordinates for the point ++ */ ++ x = BN_bin2bn(tpm_point->x.buffer, tpm_point->x.size, NULL); ++ if (!x) { ++ print_ssl_error("Could not convert x coordinate to BN"); ++ goto out; ++ } ++ ++ y = BN_bin2bn(tpm_point->y.buffer, tpm_point->y.size, NULL); ++ if (!y) { ++ print_ssl_error("Could not convert y coordinate to BN"); ++ goto out; ++ } ++ + int nid = tpm2_ossl_curve_to_nid(tpm_ecc->curveID); + if (nid < 0) { +- return false; ++ goto out; + } + + /* +- * Create an empty EC key by the NID ++ * Create a new point in the group, which is the public key. + */ +- key = EC_KEY_new_by_curve_name(nid); +- if (!key) { +- print_ssl_error("Failed to create EC key from nid"); +- return false; +- } +- +- group = EC_KEY_get0_group(key); ++ group = EC_GROUP_new_by_curve_name(nid); + if (!group) { + print_ssl_error("EC key missing group"); + goto out; + } + +- /* +- * Create a new point in the group, which is the public key. +- */ + point = EC_POINT_new(group); + ++ int rc = EC_POINT_set_affine_coordinates_tss(group, point, x, y, NULL); ++ if (!rc) { ++ print_ssl_error("Could not set affine coordinates"); ++ goto out; ++ } ++ ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + /* +- * Set the affine coordinates for the point ++ * Create an empty EC key by the NID + */ +- x = BN_bin2bn(tpm_point->x.buffer, tpm_point->x.size, NULL); +- if (!x) { +- print_ssl_error("Could not convert x coordinate to BN"); ++ ec_key = EC_KEY_new_by_curve_name(nid); ++ if (!ec_key) { ++ print_ssl_error("Failed to create EC key from nid"); ++ return false; ++ } ++ ++ rc = EC_KEY_set_public_key(ec_key, point); ++ if (!rc) { ++ print_ssl_error("Could not set point as public key portion"); + goto out; + } + +- y = BN_bin2bn(tpm_point->y.buffer, tpm_point->y.size, NULL); +- if (!y) { +- print_ssl_error("Could not convert y coordinate to BN"); ++ if ((pkey = EVP_PKEY_new()) == NULL) { ++ print_ssl_error("Failed to allocate OpenSSL EVP structure"); + goto out; + } + +- int rc = EC_POINT_set_affine_coordinates_tss(group, point, x, y, NULL); ++ rc = EVP_PKEY_assign_EC_KEY(pkey, ec_key); + if (!rc) { +- print_ssl_error("Could not set affine coordinates"); ++ print_ssl_error("Failed to set OpenSSL EVP structure"); ++ EVP_PKEY_free(pkey); ++ pkey = NULL; ++ goto out; ++ } ++ /* rsa key is now owner by the EVP_PKEY struct */ ++ ec_key = NULL; ++#else ++ build = OSSL_PARAM_BLD_new(); ++ if (!build) { ++ print_ssl_error("Failed to allocate OpenSSL parameters"); + goto out; + } + +- rc = EC_KEY_set_public_key(key, point); ++ rc = OSSL_PARAM_BLD_push_utf8_string(build, OSSL_PKEY_PARAM_GROUP_NAME, ++ (char *)OBJ_nid2sn(nid), 0); + if (!rc) { +- print_ssl_error("Could not set point as public key portion"); ++ print_ssl_error("Failed to set the EC group name"); + goto out; + } + +- int ssl_res = 0; +- +- switch (format) { +- case pubkey_format_pem: +- ssl_res = PEM_write_bio_EC_PUBKEY(bio, key); +- break; +- case pubkey_format_der: +- ssl_res = i2d_EC_PUBKEY_bio(bio, key); +- break; +- default: +- LOG_ERR("Invalid OpenSSL target format %d encountered", format); ++ bsize = EC_POINT_point2buf(group, point, ++ POINT_CONVERSION_COMPRESSED, ++ &puboct, NULL); ++ if (bsize == 0) { ++ print_ssl_error("Failed compress the EC public key"); + goto out; + } + +- if (ssl_res <= 0) { +- print_ssl_error("OpenSSL public key conversion failed"); ++ rc = OSSL_PARAM_BLD_push_octet_string(build, OSSL_PKEY_PARAM_PUB_KEY, ++ puboct, bsize); ++ if (!rc) { ++ print_ssl_error("Failed set the EC public key"); + goto out; + } + +- result = true; +- +-out: +- if (x) { +- BN_free(x); ++ params = OSSL_PARAM_BLD_to_param(build); ++ if (!params) { ++ print_ssl_error("Failed to build OpenSSL parameters"); ++ goto out; + } +- if (y) { +- BN_free(y); ++ ++ ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); ++ if (!ctx) { ++ print_ssl_error("Failed to allocate EC key context"); ++ goto out; + } +- if (point) { +- EC_POINT_free(point); ++ ++ rc = EVP_PKEY_fromdata_init(ctx); ++ if (rc <= 0) { ++ print_ssl_error("Failed to initialize EC key creation"); ++ goto out; + } +- if (key) { +- EC_KEY_free(key); ++ ++ rc = EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params); ++ if (rc <= 0) { ++ print_ssl_error("Failed to create a EC public key"); ++ goto out; + } ++#endif + +- return result; ++out: ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ EC_KEY_free(ec_key); ++#else ++ EVP_PKEY_CTX_free(ctx); ++ OSSL_PARAM_free(params); ++ OSSL_PARAM_BLD_free(build); ++ OPENSSL_free(puboct); ++#endif ++ EC_POINT_free(point); ++ EC_GROUP_free(group); ++ BN_free(x); ++ BN_free(y); ++ return pkey; + } + + static bool tpm2_convert_pubkey_bio(TPMT_PUBLIC *public, + tpm2_convert_pubkey_fmt format, BIO *bio) { + +- bool result = false; ++ EVP_PKEY *pubkey = NULL; ++ int ssl_res = 0; + + switch (public->type) { + case TPM2_ALG_RSA: +- result = convert_pubkey_RSA(public, format, bio); ++ pubkey = convert_pubkey_RSA(public); + break; + case TPM2_ALG_ECC: +- result = convert_pubkey_ECC(public, format, bio); ++ pubkey = convert_pubkey_ECC(public); + break; + default: +- LOG_ERR( +- "Unsupported key type for requested output format. Only RSA is supported."); ++ LOG_ERR("Unsupported key type for requested output format."); + } + +- return result; ++ if (pubkey == NULL) ++ return false; ++ ++ switch (format) { ++ case pubkey_format_pem: ++ ssl_res = PEM_write_bio_PUBKEY(bio, pubkey); ++ break; ++ case pubkey_format_der: ++ ssl_res = i2d_PUBKEY_bio(bio, pubkey); ++ break; ++ default: ++ LOG_ERR("Invalid OpenSSL target format %d encountered", format); ++ } ++ ++ EVP_PKEY_free(pubkey); ++ ++ if (ssl_res <= 0) { ++ print_ssl_error("OpenSSL public key conversion failed"); ++ return false; ++ } ++ ++ return true; + } + + static bool tpm2_convert_pubkey_ssl(TPMT_PUBLIC *public, +diff --git a/lib/tpm2_convert.h b/lib/tpm2_convert.h +index f8c82155..bddb455d 100644 +--- a/lib/tpm2_convert.h ++++ b/lib/tpm2_convert.h +@@ -45,6 +45,26 @@ tpm2_convert_pubkey_fmt tpm2_convert_pubkey_fmt_from_optarg(const char *label); + bool tpm2_convert_pubkey_save(TPM2B_PUBLIC *public, + tpm2_convert_pubkey_fmt format, const char *path); + ++/** ++ * Converts the given RSA public key structure into the EVP_PKEY. ++ * ++ * @param public ++ * TPM2 public key structure structure. ++ * @return ++ * OpenSSL key structure, or NULL on error. ++ */ ++EVP_PKEY *convert_pubkey_RSA(TPMT_PUBLIC *public); ++ ++/** ++ * Converts the given ECC public key structure into the EVP_PKEY. ++ * ++ * @param public ++ * TPM2 public key structure structure. ++ * @return ++ * OpenSSL key structure, or NULL on error. ++ */ ++EVP_PKEY *convert_pubkey_ECC(TPMT_PUBLIC *public); ++ + /** + * Parses the given command line signature format option string and returns + * the corresponding signature_format enum value. +-- +2.31.1 + diff --git a/SOURCES/0016-openssl-Convert-deprecated-ECDH_compute_key-to-EVP_P.patch b/SOURCES/0016-openssl-Convert-deprecated-ECDH_compute_key-to-EVP_P.patch new file mode 100644 index 0000000..cedd951 --- /dev/null +++ b/SOURCES/0016-openssl-Convert-deprecated-ECDH_compute_key-to-EVP_P.patch @@ -0,0 +1,286 @@ +From 0caac28c1fa2d62dbf7c5a6c65346f6d3399d22c Mon Sep 17 00:00:00 2001 +From: Petr Gotthard +Date: Sun, 15 Aug 2021 16:26:06 +0200 +Subject: [PATCH 15/17] openssl: Convert deprecated ECDH_compute_key to + EVP_PKEY_derive + +The EC_KEY functions are replaced by corresponding EVP_PKEY functions. +The tpm2_get_EC_public_key function is replaced by convert_pubkey_ECC +from lib/tpm2_convert.c. + +Signed-off-by: Petr Gotthard +--- + lib/tpm2_kdfe.c | 186 +++++++++++++++++++++++------------------------- + 1 file changed, 89 insertions(+), 97 deletions(-) + +diff --git a/lib/tpm2_kdfe.c b/lib/tpm2_kdfe.c +index 84718b9f..91027e32 100644 +--- a/lib/tpm2_kdfe.c ++++ b/lib/tpm2_kdfe.c +@@ -5,12 +5,16 @@ + #include + + #include ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + #include +- ++#else ++#include ++#endif + #include + #include + + #include "log.h" ++#include "tpm2_convert.h" + #include "tpm2_openssl.h" + #include "tpm2_alg_util.h" + #include "tpm2_util.h" +@@ -65,72 +69,18 @@ TSS2_RC tpm2_kdfe( + return rval; + } + +-static EC_POINT * tpm2_get_EC_public_key(TPM2B_PUBLIC *public) { +- EC_POINT *q = NULL; +- BIGNUM *bn_qx, *bn_qy; +- EC_KEY *key; +- const EC_GROUP *group; +- bool rval; +- TPMS_ECC_PARMS *tpm_ecc = &public->publicArea.parameters.eccDetail; +- TPMS_ECC_POINT *tpm_point = &public->publicArea.unique.ecc; +- +- int nid = tpm2_ossl_curve_to_nid(tpm_ecc->curveID); +- if (nid < 0) { +- return NULL; +- } +- +- key = EC_KEY_new_by_curve_name(nid); +- if (!key) { +- LOG_ERR("Failed to create EC key from nid"); +- return NULL; +- } +- +- bn_qx = BN_bin2bn(tpm_point->x.buffer, tpm_point->x.size, NULL); +- bn_qy = BN_bin2bn(tpm_point->y.buffer, tpm_point->y.size, NULL); +- if ((bn_qx == NULL) || (bn_qy == NULL)) { +- LOG_ERR("Could not convert EC public key to BN"); +- goto out; +- } +- group = EC_KEY_get0_group(key); +- if (!group) { +- LOG_ERR("EC key missing group"); +- goto out; +- } +- q = EC_POINT_new(group); +- if (q == NULL) { +- LOG_ERR("Could not allocate EC_POINT"); +- goto out; +- } +- +- rval = EC_POINT_set_affine_coordinates_tss(group, q, bn_qx, bn_qy, NULL); +- if (rval == false) { +- LOG_ERR("Could not set affine_coordinates"); +- EC_POINT_free(q); +- q = NULL; +- } +- +-out: +- if (bn_qx) { +- BN_free(bn_qx); +- } +- if (bn_qy) { +- BN_free(bn_qy); +- } +- if (key) { +- EC_KEY_free(key); +- } +- +- return q; +-} +- +- +-static bool get_public_key_from_ec_key(EC_KEY *key, TPMS_ECC_POINT *point) { +- BIGNUM *x = BN_new(); +- BIGNUM *y = BN_new(); +- const EC_POINT *pubkey = EC_KEY_get0_public_key(key); ++static bool get_public_key_from_ec_key(EVP_PKEY *pkey, TPMS_ECC_POINT *point) { ++ BIGNUM *x = NULL; ++ BIGNUM *y = NULL; + unsigned int nbx, nby; + bool result = false; + ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ EC_KEY *key = EVP_PKEY_get0_EC_KEY(pkey); ++ const EC_POINT *pubkey = EC_KEY_get0_public_key(key); ++ ++ x = BN_new(); ++ y = BN_new(); + if ((x == NULL) || (y == NULL) || (pubkey == NULL)) { + LOG_ERR("Failed to allocate memory to store EC public key."); + goto out; +@@ -138,6 +88,18 @@ static bool get_public_key_from_ec_key(EC_KEY *key, TPMS_ECC_POINT *point) { + + EC_POINT_get_affine_coordinates_tss(EC_KEY_get0_group(key), + pubkey, x, y, NULL); ++#else ++ int rc = EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &x); ++ if (!rc) { ++ LOG_ERR("Failed to get EC public key X."); ++ goto out; ++ } ++ rc = EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &y); ++ if (!rc) { ++ LOG_ERR("Failed to get EC public key Y."); ++ goto out; ++ } ++#endif + nbx = BN_num_bytes(x); + nby = BN_num_bytes(y); + if ((nbx > sizeof(point->x.buffer))|| +@@ -153,29 +115,41 @@ static bool get_public_key_from_ec_key(EC_KEY *key, TPMS_ECC_POINT *point) { + result = true; + + out: +- if (x) { +- BN_free(x); +- } +- if (y) { +- BN_free(y); +- } ++ BN_free(x); ++ BN_free(y); + return result; + } + + +-static int get_ECDH_shared_secret(EC_KEY *key, +- const EC_POINT *p_pub, TPM2B_ECC_PARAMETER *secret) { ++static int get_ECDH_shared_secret(EVP_PKEY *pkey, ++ EVP_PKEY *p_pub, TPM2B_ECC_PARAMETER *secret) { + +- int shared_secret_length; ++ EVP_PKEY_CTX *ctx; ++ int result = -1; + +- shared_secret_length = EC_GROUP_get_degree(EC_KEY_get0_group(key)); +- shared_secret_length = (shared_secret_length + 7) / 8; +- if ((size_t) shared_secret_length > sizeof(secret->buffer)) { ++ ctx = EVP_PKEY_CTX_new(pkey, NULL); ++ if (!ctx) + return -1; +- } +- secret->size = ECDH_compute_key(secret->buffer, +- shared_secret_length, p_pub, key, NULL); +- return secret->size; ++ ++ int rc = EVP_PKEY_derive_init(ctx); ++ if (rc <= 0) ++ goto out; ++ ++ rc = EVP_PKEY_derive_set_peer(ctx, p_pub); ++ if (rc <= 0) ++ goto out; ++ ++ size_t shared_secret_length = sizeof(secret->buffer); ++ rc = EVP_PKEY_derive(ctx, secret->buffer, &shared_secret_length); ++ if (rc <= 0) ++ goto out; ++ ++ secret->size = shared_secret_length; ++ result = secret->size; ++ ++out: ++ EVP_PKEY_CTX_free(ctx); ++ return result; + } + + +@@ -190,25 +164,42 @@ bool ecdh_derive_seed_and_encrypted_seed( + TPMI_ALG_HASH parent_name_alg = parent_pub->publicArea.nameAlg; + UINT16 parent_hash_size = tpm2_alg_util_get_hash_size(parent_name_alg); + bool result = false; +- EC_KEY *key = NULL; +- EC_POINT *qsv = NULL; ++ EVP_PKEY_CTX *ctx; ++ EVP_PKEY *pkey = NULL; ++ EVP_PKEY *qsv = NULL; + TPMS_ECC_POINT qeu; + bool qeu_is_valid; + TPM2B_ECC_PARAMETER ecc_secret; + + // generate an ephemeral key + int nid = tpm2_ossl_curve_to_nid(tpm_ecc->curveID); +- if (nid >= 0) { +- key = EC_KEY_new_by_curve_name(nid); +- } +- if (key == NULL) { +- LOG_ERR("Failed to create EC key from curveID"); ++ ++ ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); ++ if (!ctx) { ++ LOG_ERR("Failed to create key creation context"); + return false; + } +- EC_KEY_generate_key(key); ++ ++ int rc = EVP_PKEY_keygen_init(ctx); ++ if (rc <= 0) { ++ LOG_ERR("Failed to initialize key creation"); ++ goto out; ++ } ++ ++ rc = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); ++ if (rc <= 0) { ++ LOG_ERR("Failed to set EC curve NID %i", nid); ++ goto out; ++ } ++ ++ rc = EVP_PKEY_keygen(ctx, &pkey); ++ if (rc <= 0) { ++ LOG_ERR("Failed to generate the ephemeral EC key"); ++ goto out; ++ } + + // get public key for the ephemeral key +- qeu_is_valid = get_public_key_from_ec_key(key, &qeu); ++ qeu_is_valid = get_public_key_from_ec_key(pkey, &qeu); + if (qeu_is_valid == false) { + LOG_ERR("Could not get the ECC public key"); + goto out; +@@ -226,13 +217,17 @@ bool ecdh_derive_seed_and_encrypted_seed( + out_sym_seed->size = offset; + + /* get parents public key */ +- qsv = tpm2_get_EC_public_key(parent_pub); ++ qsv = convert_pubkey_ECC(&parent_pub->publicArea); + if (qsv == NULL) { + LOG_ERR("Could not get parent's public key"); + goto out; + } + +- get_ECDH_shared_secret(key, qsv, &ecc_secret); ++ rc = get_ECDH_shared_secret(pkey, qsv, &ecc_secret); ++ if (rc <= 0) { ++ LOG_ERR("Could not derive shared secret"); ++ goto out; ++ } + + /* derive seed using KDFe */ + TPM2B_ECC_PARAMETER *party_u_info = &qeu.x; +@@ -244,11 +239,8 @@ bool ecdh_derive_seed_and_encrypted_seed( + result = true; + + out: +- if (qsv) { +- EC_POINT_free(qsv); +- } +- if (key) { +- EC_KEY_free(key); +- } ++ EVP_PKEY_free(qsv); ++ EVP_PKEY_free(pkey); ++ EVP_PKEY_CTX_free(ctx); + return result; + } +-- +2.31.1 + diff --git a/SOURCES/0017-openssl-Reimplement-RSA-OAEP-encryption-using-EVP-fu.patch b/SOURCES/0017-openssl-Reimplement-RSA-OAEP-encryption-using-EVP-fu.patch new file mode 100644 index 0000000..ba6a3da --- /dev/null +++ b/SOURCES/0017-openssl-Reimplement-RSA-OAEP-encryption-using-EVP-fu.patch @@ -0,0 +1,240 @@ +From 317c1ea1d9893d6f4f837196648c53b7f7dd762f Mon Sep 17 00:00:00 2001 +From: Petr Gotthard +Date: Sun, 15 Aug 2021 17:22:44 +0200 +Subject: [PATCH 16/17] openssl: Reimplement RSA OAEP encryption using EVP + functions + +The RSA_padding_add_PKCS1_OAEP_mgf1 is deprecated and the entire +semi-custom implementation of OAEP is unnecessary. +The Part 1, B.10.3 talks about a standard OAEP with a given label, +which can be easily implemented using the standard EVP functions. +Also, the public key retrieval can be replaced by invocation of +convert_pubkey_RSA from lib/tpm2_convert.c + +Signed-off-by: Petr Gotthard +--- + lib/tpm2_identity_util.c | 162 +++++++++++---------------------------- + 1 file changed, 43 insertions(+), 119 deletions(-) + +diff --git a/lib/tpm2_identity_util.c b/lib/tpm2_identity_util.c +index ba0c0e1c..b04a56d6 100644 +--- a/lib/tpm2_identity_util.c ++++ b/lib/tpm2_identity_util.c +@@ -10,6 +10,7 @@ + + #include "log.h" + #include "tpm2_alg_util.h" ++#include "tpm2_convert.h" + #include "tpm2_identity_util.h" + #include "tpm2_kdfa.h" + #include "tpm2_kdfe.h" +@@ -17,73 +18,6 @@ + + // Identity-related functionality that the TPM normally does, but using OpenSSL + +-#if defined(LIBRESSL_VERSION_NUMBER) +-static int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, +- const unsigned char *from, int flen, const unsigned char *param, int plen, +- const EVP_MD *md, const EVP_MD *mgf1md) { +- +- int ret = 0; +- int i, emlen = tlen - 1; +- unsigned char *db, *seed; +- unsigned char *dbmask, seedmask[EVP_MAX_MD_SIZE]; +- int mdlen; +- +- if (md == NULL) +- md = EVP_sha1(); +- if (mgf1md == NULL) +- mgf1md = md; +- +- mdlen = EVP_MD_size(md); +- +- if (flen > emlen - 2 * mdlen - 1) { +- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, +- RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); +- return 0; +- } +- +- if (emlen < 2 * mdlen + 1) { +- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, +- RSA_R_KEY_SIZE_TOO_SMALL); +- return 0; +- } +- +- to[0] = 0; +- seed = to + 1; +- db = to + mdlen + 1; +- +- if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL)) +- return 0; +- memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1); +- db[emlen - flen - mdlen - 1] = 0x01; +- memcpy(db + emlen - flen - mdlen, from, (unsigned int)flen); +- if (RAND_bytes(seed, mdlen) <= 0) +- return 0; +- +- dbmask = OPENSSL_malloc(emlen - mdlen); +- if (dbmask == NULL) { +- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE); +- return 0; +- } +- +- if (PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md) < 0) +- goto err; +- for (i = 0; i < emlen - mdlen; i++) +- db[i] ^= dbmask[i]; +- +- if (PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md) < 0) +- goto err; +- for (i = 0; i < mdlen; i++) +- seed[i] ^= seedmask[i]; +- +- ret = 1; +- +-err: +- OPENSSL_free(dbmask); +- +- return ret; +-} +-#endif +- + static TPM2_KEY_BITS get_pub_asym_key_bits(TPM2B_PUBLIC *public) { + + TPMU_PUBLIC_PARMS *p = &public->publicArea.parameters; +@@ -102,19 +36,13 @@ static bool share_secret_with_tpm2_rsa_public_key(TPM2B_DIGEST *protection_seed, + TPM2B_PUBLIC *parent_pub, unsigned char *label, int label_len, + TPM2B_ENCRYPTED_SECRET *encrypted_protection_seed) { + bool rval = false; +- RSA *rsa = NULL; +- +- // Public modulus (RSA-only!) +- TPMI_RSA_KEY_BITS mod_size_bits = +- parent_pub->publicArea.parameters.rsaDetail.keyBits; +- UINT16 mod_size = mod_size_bits / 8; +- TPM2B *pub_key_val = (TPM2B *) &parent_pub->publicArea.unique.rsa; +- unsigned char *pub_modulus = malloc(mod_size); +- if (pub_modulus == NULL) { +- LOG_ERR("Failed to allocate memory to store public key's modulus."); ++ EVP_PKEY_CTX *ctx = NULL; ++ ++ EVP_PKEY *pkey = convert_pubkey_RSA(&parent_pub->publicArea); ++ if (pkey == NULL) { ++ LOG_ERR("Failed to retrieve public key"); + return false; + } +- memcpy(pub_modulus, pub_key_val->buffer, mod_size); + + TPMI_ALG_HASH parent_name_alg = parent_pub->publicArea.nameAlg; + +@@ -122,70 +50,66 @@ static bool share_secret_with_tpm2_rsa_public_key(TPM2B_DIGEST *protection_seed, + * RSA Secret Sharing uses a randomly generated seed (Part 1, B.10.3). + */ + protection_seed->size = tpm2_alg_util_get_hash_size(parent_name_alg); +- int return_code = RAND_bytes(protection_seed->buffer, protection_seed->size); +- if (return_code != 1) { ++ int rc = RAND_bytes(protection_seed->buffer, protection_seed->size); ++ if (rc != 1) { + LOG_ERR("Failed to get random bytes"); + goto error; + } + + /* +- * This is the biggest buffer value, so it should always be sufficient. ++ * The seed value will be OAEP encrypted with a given L parameter. + */ +- unsigned char encoded[TPM2_MAX_DIGEST_BUFFER]; +- return_code = RSA_padding_add_PKCS1_OAEP_mgf1(encoded, mod_size, +- protection_seed->buffer, protection_seed->size, label, label_len, +- tpm2_openssl_md_from_tpmhalg(parent_name_alg), NULL); +- if (return_code != 1) { +- LOG_ERR("Failed RSA_padding_add_PKCS1_OAEP_mgf1\n"); +- goto error; +- } +- BIGNUM* bne = BN_new(); +- if (!bne) { +- LOG_ERR("BN_new for bne failed\n"); ++ ctx = EVP_PKEY_CTX_new(pkey, NULL); ++ if (!ctx) { ++ LOG_ERR("Failed EVP_PKEY_CTX_new"); + goto error; + } +- return_code = BN_set_word(bne, RSA_F4); +- if (return_code != 1) { +- LOG_ERR("BN_set_word failed\n"); +- BN_free(bne); ++ ++ rc = EVP_PKEY_encrypt_init(ctx); ++ if (rc <= 0) { ++ LOG_ERR("Failed EVP_PKEY_encrypt_init"); + goto error; + } +- rsa = RSA_new(); +- if (!rsa) { +- LOG_ERR("RSA_new failed\n"); +- BN_free(bne); ++ ++ rc = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING); ++ if (rc <= 0) { ++ LOG_ERR("Failed EVP_PKEY_CTX_set_rsa_padding"); + goto error; + } +- return_code = RSA_generate_key_ex(rsa, mod_size_bits, bne, NULL); +- BN_free(bne); +- if (return_code != 1) { +- LOG_ERR("RSA_generate_key_ex failed\n"); ++ ++ rc = EVP_PKEY_CTX_set_rsa_oaep_md(ctx, ++ tpm2_openssl_md_from_tpmhalg(parent_name_alg)); ++ if (rc <= 0) { ++ LOG_ERR("Failed EVP_PKEY_CTX_set_rsa_oaep_md"); + goto error; + } +- BIGNUM *n = BN_bin2bn(pub_modulus, mod_size, NULL); +- if (n == NULL) { +- LOG_ERR("BN_bin2bn failed\n"); ++ ++ // the library will take ownership of the label ++ char *newlabel = strdup((const char *)label); ++ if (newlabel == NULL) { ++ LOG_ERR("Failed to allocate label"); + goto error; + } +- if (!RSA_set0_key(rsa, n, NULL, NULL)) { +- LOG_ERR("RSA_set0_key failed\n"); +- BN_free(n); ++ ++ rc = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, newlabel, label_len); ++ if (rc <= 0) { ++ LOG_ERR("Failed EVP_PKEY_CTX_set0_rsa_oaep_label"); ++ free(newlabel); + goto error; + } +- // Encrypting +- encrypted_protection_seed->size = mod_size; +- return_code = RSA_public_encrypt(mod_size, encoded, +- encrypted_protection_seed->secret, rsa, RSA_NO_PADDING); +- if (return_code < 0) { +- LOG_ERR("Failed RSA_public_encrypt\n"); ++ ++ size_t outlen = sizeof(TPMU_ENCRYPTED_SECRET); ++ if (EVP_PKEY_encrypt(ctx, encrypted_protection_seed->secret, &outlen, ++ protection_seed->buffer, protection_seed->size) <= 0) { ++ LOG_ERR("Failed EVP_PKEY_encrypt\n"); + goto error; + } +- ++ encrypted_protection_seed->size = outlen; + rval = true; + + error: +- free(pub_modulus); +- RSA_free(rsa); ++ EVP_PKEY_CTX_free(ctx); ++ EVP_PKEY_free(pkey); + return rval; + } + +-- +2.31.1 + diff --git a/SOURCES/0018-Generate-partial-X.509-certificate-using-own-struct.patch b/SOURCES/0018-Generate-partial-X.509-certificate-using-own-struct.patch new file mode 100644 index 0000000..abdafe1 --- /dev/null +++ b/SOURCES/0018-Generate-partial-X.509-certificate-using-own-struct.patch @@ -0,0 +1,282 @@ +From 22ecb8a2c00db7a53508d2106957e0c112a5a020 Mon Sep 17 00:00:00 2001 +From: Petr Gotthard +Date: Tue, 31 Aug 2021 12:27:35 +0200 +Subject: [PATCH 17/17] Generate partial X.509 certificate using own struct + +The tpm2_certifyX509certutil.c:generate_partial_X509() creates a partial +(in fact, an incomplete) certificate, see Part 3, 18.8.1. The OpenSSL +team decided that starting from 3.0 the i2d should not create invalid +encodings, so we need to create an own ASN.1 structure for this. + +The structure is adapted from +https://github.com/openssl/openssl/issues/16257#issuecomment-895448370. + +Fixes: #2813 + +Signed-off-by: Petr Gotthard +--- + tools/misc/tpm2_certifyX509certutil.c | 179 +++++++++----------------- + 1 file changed, 59 insertions(+), 120 deletions(-) + +diff --git a/tools/misc/tpm2_certifyX509certutil.c b/tools/misc/tpm2_certifyX509certutil.c +index 62ed644a..5eea08e8 100644 +--- a/tools/misc/tpm2_certifyX509certutil.c ++++ b/tools/misc/tpm2_certifyX509certutil.c +@@ -8,6 +8,8 @@ + #include + #include + ++#include ++#include + #include + #include + #include +@@ -15,6 +17,46 @@ + #include "log.h" + #include "tpm2_tool.h" + ++typedef struct { ++ ASN1_TIME *notBefore; ++ ASN1_TIME *notAfter; ++} TPM2_PARTIAL_CERT_VALIDITY; ++ ++typedef struct { ++ X509_ALGOR *algorithm; ++ X509_NAME *issuer; ++ TPM2_PARTIAL_CERT_VALIDITY *validity; ++ X509_NAME *subject; ++ STACK_OF(X509_EXTENSION) *extensions; ++} TPM2_PARTIAL_CERT; ++ ++ASN1_SEQUENCE(TPM2_PARTIAL_CERT_VALIDITY) = { ++ ASN1_SIMPLE(TPM2_PARTIAL_CERT_VALIDITY, notBefore, ASN1_TIME), ++ ASN1_SIMPLE(TPM2_PARTIAL_CERT_VALIDITY, notAfter, ASN1_TIME), ++} ASN1_SEQUENCE_END(TPM2_PARTIAL_CERT_VALIDITY) ++ ++/* partialCertificate per Part 3, 18.8.1 */ ++ASN1_SEQUENCE(TPM2_PARTIAL_CERT) = { ++ ASN1_OPT(TPM2_PARTIAL_CERT, algorithm, X509_ALGOR), ++ ASN1_SIMPLE(TPM2_PARTIAL_CERT, issuer, X509_NAME), ++ ASN1_SIMPLE(TPM2_PARTIAL_CERT, validity, TPM2_PARTIAL_CERT_VALIDITY), ++ ASN1_SIMPLE(TPM2_PARTIAL_CERT, subject, X509_NAME), ++ ASN1_EXP_SEQUENCE_OF(TPM2_PARTIAL_CERT, extensions, X509_EXTENSION, 3), ++} ASN1_SEQUENCE_END(TPM2_PARTIAL_CERT) ++ ++IMPLEMENT_ASN1_FUNCTIONS(TPM2_PARTIAL_CERT) ++ ++int i2d_TPM2_PARTIAL_CERT_bio(BIO *bp, const TPM2_PARTIAL_CERT *a) ++{ ++ return ASN1_i2d_bio_of(TPM2_PARTIAL_CERT, i2d_TPM2_PARTIAL_CERT, bp, a); ++} ++ ++int TPM2_add_ext(TPM2_PARTIAL_CERT *x, X509_EXTENSION *ex, int loc) ++{ ++ return (X509v3_add_ext(&(x->extensions), ex, loc) != NULL); ++} ++ ++ + struct tpm_gen_partial_cert { + const char *out_path; + const char *valid_str; +@@ -95,80 +137,6 @@ static struct name_fields names[] = { + .def = "CA Unit" }, + }; + +-static tool_rc fixup_cert(const char *cert) { +- +- int fd = open(cert, O_RDONLY); +- if (fd < 0) { +- LOG_ERR("open failed"); +- return tool_rc_general_error; +- } +- +- struct stat fs; +- int ret = fstat(fd, &fs); +- if (ret < 0) { +- close(fd); +- return tool_rc_general_error; +- } +- +- ssize_t size = fs.st_size; +- if (size < 100 || size > 255) { +- LOG_ERR("Wrong cert size %zd", size); +- close(fd); +- return tool_rc_general_error; /* there is something wrong with this cert */ +- } +- +- char* buf = calloc(1, size); +- if (!buf) { +- LOG_ERR("Alloc failed"); +- close(fd); +- return tool_rc_general_error; +- } +- +- tool_rc rc = tool_rc_success; +- ret = read(fd, buf, size); +- close(fd); +- if (ret != size) { +- LOG_ERR("read failed"); +- rc = tool_rc_general_error; +- goto out; +- } +- +- fd = open(cert, O_WRONLY | O_TRUNC); +- if (fd < 0) { +- LOG_ERR("second open failed"); +- rc = tool_rc_general_error; +- goto out; +- } +- +- /* We need to skip one wrapping sequence (8 bytes) and one +- * sequence with one empty byte field at the end (5 bytes). +- * Fix the size here */ +- buf[2] = size - 16; +- +- /* Write the external sequence with the fixed size */ +- ret = write(fd, buf, 3); +- if (ret != 3) { +- LOG_ERR("write failed"); +- rc = tool_rc_general_error; +- close(fd); +- goto out; +- } +- +- /* skip the wrapping sequence the write the rest +- * without the 5 bytes at the end */ +- ret = write(fd, buf + 11, size - 16); +- close(fd); +- if (ret != size - 16) { +- LOG_ERR("second write failed"); +- rc = tool_rc_general_error; +- } +- +-out: +- free(buf); +- +- return rc; +-} +- + static int populate_fields(X509_NAME *name, const char *opt) { + + char *name_opt = strdup(opt); +@@ -228,19 +196,14 @@ static tool_rc generate_partial_X509() { + } + + X509_EXTENSION *extv3 = NULL; +- X509 *cert = X509_new(); ++ TPM2_PARTIAL_CERT *cert = TPM2_PARTIAL_CERT_new(); + if (!cert) { +- LOG_ERR("X509_new"); +- goto out_err; +- } +- +- X509_NAME *issuer = X509_get_issuer_name(cert); +- if (!issuer) { +- LOG_ERR("X509_get_issuer_name"); ++ LOG_ERR("TPM2_PARTIAL_CERT_new"); + goto out_err; + } + +- int fields_added = populate_fields(issuer, ctx.issuer); ++ /* populate issuer */ ++ int fields_added = populate_fields(cert->issuer, ctx.issuer); + if (fields_added <= 0) { + LOG_ERR("Could not parse any issuer fields"); + goto out_err; +@@ -248,28 +211,18 @@ static tool_rc generate_partial_X509() { + LOG_INFO("Added %d issuer fields", fields_added); + } + +- int ret = X509_set_issuer_name(cert, issuer); // add issuer +- if (ret != 1) { +- LOG_ERR("X509_set_issuer_name"); +- goto out_err; +- } +- ++ /* populate validity */ + unsigned int valid_days; + if (!tpm2_util_string_to_uint32(ctx.valid_str, &valid_days)) { + LOG_ERR("string_to_uint32"); + goto out_err; + } + +- X509_gmtime_adj(X509_getm_notBefore(cert), 0); // add valid not before +- X509_gmtime_adj(X509_getm_notAfter(cert), valid_days * 86400); // add valid not after +- +- X509_NAME *subject = X509_get_subject_name(cert); +- if (!subject) { +- LOG_ERR("X509_get_subject_name"); +- goto out_err; +- } ++ X509_gmtime_adj(cert->validity->notBefore, 0); // add valid not before ++ X509_gmtime_adj(cert->validity->notAfter, valid_days * 86400); // add valid not after + +- fields_added = populate_fields(subject, ctx.subject); ++ /* populate subject */ ++ fields_added = populate_fields(cert->subject, ctx.subject); + if (fields_added <= 0) { + LOG_ERR("Could not parse any subject fields"); + goto out_err; +@@ -277,51 +230,37 @@ static tool_rc generate_partial_X509() { + LOG_INFO("Added %d subject fields", fields_added); + } + +- ret = X509_set_subject_name(cert, subject); // add subject +- if (ret != 1) { +- LOG_ERR("X509_NAME_add_entry_by_txt"); +- goto out_err; +- } +- ++ /* populate extensions */ + extv3 = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, +- "critical,digitalSignature,keyCertSign,cRLSign"); ++ "critical,digitalSignature,keyCertSign,cRLSign"); + if (!extv3) { + LOG_ERR("X509V3_EXT_conf_nid"); + goto out_err; + } + +- ret = X509_add_ext(cert, extv3, -1); // add required v3 extention: key usage ++ int ret = TPM2_add_ext(cert, extv3, -1); // add required v3 extention: key usage + if (ret != 1) { + LOG_ERR("X509_add_ext"); + goto out_err; + } + +- ret = i2d_X509_bio(cert_out, cert); // print cert in DER format ++ /* output */ ++ ret = i2d_TPM2_PARTIAL_CERT_bio(cert_out, cert); // print cert in DER format + if (ret != 1) { + LOG_ERR("i2d_X509_bio"); + goto out_err; + } + + X509_EXTENSION_free(extv3); +- X509_free(cert); ++ TPM2_PARTIAL_CERT_free(cert); + BIO_free_all(cert_out); + +- ret = fixup_cert(ctx.out_path); +- if (ret) { +- LOG_ERR("fixup_cert"); +- return tool_rc_general_error; +- } +- + return tool_rc_success; + + out_err: + BIO_free_all(cert_out); +- if (cert) { +- X509_free(cert); +- } +- if (extv3) { +- X509_EXTENSION_free(extv3); +- } ++ X509_EXTENSION_free(extv3); ++ TPM2_PARTIAL_CERT_free(cert); + + return tool_rc_general_error; + } +-- +2.31.1 + diff --git a/SOURCES/0019-build-Use-hardcoded-version-variable.patch b/SOURCES/0019-build-Use-hardcoded-version-variable.patch new file mode 100644 index 0000000..ba05609 --- /dev/null +++ b/SOURCES/0019-build-Use-hardcoded-version-variable.patch @@ -0,0 +1,32 @@ +From 395651f059ceb21d56c44cddda05e055caa0fd19 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20Hor=C3=A1=C4=8Dek?= + +Date: Mon, 18 Oct 2021 19:04:54 +0200 +Subject: [PATCH] build: Use hardcoded version variable +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Before this commit the version was generated from git tag/commit hash. +This caused problems with having empty version variable while building +outside of git. Fix this by hardcoding the variable. + +Signed-off-by: Štěpán Horáček +--- + configure.ac | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 9561fa86..2bf3a790 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1,5 +1,4 @@ +-AC_INIT([tpm2-tools], +- [m4_esyscmd_s([git describe --tags --always --dirty])]) ++AC_INIT([tpm2-tools], [5.0]) + AC_CONFIG_MACRO_DIR([m4]) + + AX_IS_RELEASE([dash-version]) +-- +2.31.1 + diff --git a/SPECS/tpm2-tools.spec b/SPECS/tpm2-tools.spec index 3b54d42..699846d 100644 --- a/SPECS/tpm2-tools.spec +++ b/SPECS/tpm2-tools.spec @@ -2,13 +2,31 @@ Name: tpm2-tools Version: 5.0 -Release: 8%{?candidate:.%{candidate}}%{?dist} +Release: 10%{?candidate:.%{candidate}}%{?dist} Summary: A bunch of TPM testing toolS build upon tpm2-tss License: BSD URL: https://github.com/tpm2-software/tpm2-tools Source0: https://github.com/tpm2-software/tpm2-tools/releases/download/%{version}%{?candidate:-%{candidate}}/%{name}-%{version}%{?candidate:-%{candidate}}.tar.gz Patch0: 0001-tpm2_import-fix-fixed-AES-key-CVE-2021-3565.patch +Patch1: 0002-Don-t-assume-end-of-argv-is-NULL.patch +Patch2: 0003-tpm2_options-fix-possible-null-ptr-passed-to-strdup.patch +Patch3: 0004-tpm2_identity_util-move-create_name-into-utility-lib.patch +Patch4: 0005-openssl-Remove-support-for-OpenSSL-1.1.0.patch +Patch5: 0006-openssl-Remove-functions-that-have-no-effect-in-Open.patch +Patch6: 0007-openssl-Remove-unnecesary-EVP_CIPHER_CTX-and-HMAC_CT.patch +Patch7: 0008-openssl-Replace-SHA256_CTX-by-EVP_MD_CTX.patch +Patch8: 0009-openssl-Replace-deprecated-X509_get_-by-X509_getm_.patch +Patch9: 0010-openssl-Convert-deprecated-SHA256-384-digesters-to-E.patch +Patch10: 0011-openssl-Rename-tpm2_openssl_halg_from_tpmhalg.patch +Patch11: 0012-openssl-Use-EVP_MAC_update-instead-HMAC_Update-on-Op.patch +Patch12: 0013-openssl-Remove-unnecessary-compatibility-function.patch +Patch13: 0014-openssl-Implement-EVP_PKEY-based-key-import.patch +Patch14: 0015-openssl-Implement-EVP_PKEY-based-key-export.patch +Patch15: 0016-openssl-Convert-deprecated-ECDH_compute_key-to-EVP_P.patch +Patch16: 0017-openssl-Reimplement-RSA-OAEP-encryption-using-EVP-fu.patch +Patch17: 0018-Generate-partial-X.509-certificate-using-own-struct.patch +Patch18: 0019-build-Use-hardcoded-version-variable.patch BuildRequires: make BuildRequires: gcc-c++ @@ -33,6 +51,7 @@ tpm2-tools is a batch of tools for tpm2.0. It is based on tpm2-tss. %autosetup -p1 -n %{name}-%{version}%{?candidate:-%{candidate}} %build +autoreconf -i # LTO exposes a latent uninitialized variable "value" in the function # "nt". # This has been reported to the maintainer (Yunying), but they have not # responded and I am not comfortable enough with the code to know if a trivial @@ -58,6 +77,14 @@ tpm2-tools is a batch of tools for tpm2.0. It is based on tpm2-tss. %{_mandir}/man1/tss2_*.1.gz %changelog +* Mon Oct 25 2021 Štěpán Horáček - 5.0-10 +- Fix the version not being reported + Resolves: rhbz#2015941 + +* Fri Oct 1 2021 Štěpán Horáček - 5.0-9 +- Fix a segfault on ppc64le and add support for OpenSSL 3 + Resolves: rhbz#1989617 + * Tue Aug 10 2021 Mohan Boddu - 5.0-8 - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags Related: rhbz#1991688