From 42b51de62cf4f4bbb92ef63deaa4cd9181f21beb Mon Sep 17 00:00:00 2001 From: Dan Streetman Date: Thu, 8 Dec 2022 16:57:47 -0500 Subject: [PATCH] tpm2: move openssl-required ifdef code out of policy-building function (cherry picked from commit 958982415808eeec956e79c4f7ca030af5af1b71) Related: RHEL-16182 --- src/shared/tpm2-util.c | 98 +++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 40 deletions(-) diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index 722ae3ca9c..ea04d0a892 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -1262,21 +1262,38 @@ static int tpm2_make_encryption_session( return 0; } +static int openssl_pubkey_to_tpm2_pubkey( + const void *pubkey, + size_t pubkey_size, + TPM2B_PUBLIC *output, + void **ret_fp, + size_t *ret_fp_size) { + #if HAVE_OPENSSL -static int openssl_pubkey_to_tpm2_pubkey(EVP_PKEY *input, TPM2B_PUBLIC *output) { #if OPENSSL_VERSION_MAJOR >= 3 _cleanup_(BN_freep) BIGNUM *n = NULL, *e = NULL; #else const BIGNUM *n = NULL, *e = NULL; const RSA *rsa = NULL; #endif - int n_bytes, e_bytes; + int r, n_bytes, e_bytes; - assert(input); + assert(pubkey); + assert(pubkey_size > 0); assert(output); /* Converts an OpenSSL public key to a structure that the TPM chip can process. */ + _cleanup_fclose_ FILE *f = NULL; + f = fmemopen((void*) pubkey, pubkey_size, "r"); + if (!f) + return log_oom(); + + _cleanup_(EVP_PKEY_freep) EVP_PKEY *input = NULL; + input = PEM_read_PUBKEY(f, NULL, NULL, NULL); + if (!input) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse PEM public key."); + if (EVP_PKEY_base_id(input) != EVP_PKEY_RSA) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Provided public key is not an RSA key."); @@ -1343,22 +1360,38 @@ static int openssl_pubkey_to_tpm2_pubkey(EVP_PKEY *input, TPM2B_PUBLIC *output) if (BN_bn2bin(e, (unsigned char*) &output->publicArea.parameters.rsaDetail.exponent) <= 0) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to convert RSA exponent."); + if (ret_fp) { + _cleanup_free_ void *fp = NULL; + size_t fp_size; + + assert(ret_fp_size); + + r = pubkey_fingerprint(input, EVP_sha256(), &fp, &fp_size); + if (r < 0) + return log_error_errno(r, "Failed to calculate public key fingerprint: %m"); + + *ret_fp = TAKE_PTR(fp); + *ret_fp_size = fp_size; + } + return 0; +#else /* HAVE_OPENSSL */ + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled."); +#endif } static int find_signature( JsonVariant *v, - uint16_t pcr_bank, - uint32_t pcr_mask, - EVP_PKEY *pk, + const TPML_PCR_SELECTION *pcr_selection, + const void *fp, + size_t fp_size, const void *policy, size_t policy_size, void *ret_signature, size_t *ret_signature_size) { - _cleanup_free_ void *fp = NULL; +#if HAVE_OPENSSL JsonVariant *b, *i; - size_t fp_size; const char *k; int r; @@ -1368,6 +1401,12 @@ static int find_signature( if (!json_variant_is_object(v)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Signature is not a JSON object."); + uint16_t pcr_bank = pcr_selection->pcrSelections[0].hash; + uint32_t pcr_mask; + r = tpm2_tpml_pcr_selection_to_mask(pcr_selection, pcr_bank, &pcr_mask); + if (r < 0) + return r; + k = tpm2_hash_alg_to_string(pcr_bank); if (!k) return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Don't know PCR bank %" PRIu16, pcr_bank); @@ -1411,12 +1450,6 @@ static int find_signature( if (r < 0) return log_error_errno(r, "Failed to decode fingerprint in JSON data: %m"); - if (!fp) { - r = pubkey_fingerprint(pk, EVP_sha256(), &fp, &fp_size); - if (r < 0) - return log_error_errno(r, "Failed to calculate public key fingerprint: %m"); - } - if (memcmp_nn(fp, fp_size, fpj_data, fpj_size) != 0) continue; /* Not for this public key */ @@ -1441,8 +1474,10 @@ static int find_signature( } return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Couldn't find signature for this PCR bank, PCR index and public key."); -} +#else /* HAVE_OPENSSL */ + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled."); #endif +} static int tpm2_make_policy_session( Tpm2Context *c, @@ -1504,21 +1539,6 @@ static int tpm2_make_policy_session( } } -#if HAVE_OPENSSL - _cleanup_(EVP_PKEY_freep) EVP_PKEY *pk = NULL; - if (pubkey_size > 0) { - /* If a pubkey is specified, load it to validate it, even if the PCR mask for this is - * actually zero, and we are thus not going to use it. */ - _cleanup_fclose_ FILE *f = fmemopen((void*) pubkey, pubkey_size, "r"); - if (!f) - return log_oom(); - - pk = PEM_read_PUBKEY(f, NULL, NULL, NULL); - if (!pk) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse PEM public key."); - } -#endif - _cleanup_tpm2_handle_ Tpm2Handle *session = NULL; r = tpm2_handle_new(c, &session); if (r < 0) @@ -1541,12 +1561,14 @@ static int tpm2_make_policy_session( "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc)); if (pubkey_pcr_mask != 0) { -#if HAVE_OPENSSL + _cleanup_free_ void *fp = NULL; + size_t fp_size = 0; + TPM2B_PUBLIC pubkey_tpm2; + log_debug("Configuring public key based PCR policy."); - /* First: load public key into the TPM */ - TPM2B_PUBLIC pubkey_tpm2; - r = openssl_pubkey_to_tpm2_pubkey(pk, &pubkey_tpm2); + /* Convert the PEM key to TPM2 format */ + r = openssl_pubkey_to_tpm2_pubkey(pubkey, pubkey_size, &pubkey_tpm2, &fp, &fp_size); if (r < 0) return r; @@ -1614,9 +1636,8 @@ static int tpm2_make_policy_session( r = find_signature( signature_json, - pcr_bank, - pubkey_pcr_mask, - pk, + &pcr_selection, + fp, fp_size, approved_policy->buffer, approved_policy->size, &signature_raw, @@ -1680,9 +1701,6 @@ static int tpm2_make_policy_session( if (rc != TSS2_RC_SUCCESS) return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to push Authorize policy into TPM: %s", sym_Tss2_RC_Decode(rc)); -#else - return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled."); -#endif } if (hash_pcr_mask != 0) {