diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index 3efeb99158..1bd2a12acb 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -2279,20 +2279,19 @@ static int tpm2_build_sealing_policy( const Tpm2Handle *session, uint32_t hash_pcr_mask, uint16_t pcr_bank, - const void *pubkey, - size_t pubkey_size, + const TPM2B_PUBLIC *public, + const void *fp, + size_t fp_size, uint32_t pubkey_pcr_mask, JsonVariant *signature_json, bool use_pin, TPM2B_DIGEST **ret_policy_digest) { - TSS2_RC rc; int r; assert(c); assert(session); - assert(pubkey || pubkey_size == 0); - assert(pubkey_pcr_mask == 0 || pubkey_size > 0); + assert(pubkey_pcr_mask == 0 || public); log_debug("Building sealing policy."); @@ -2305,128 +2304,11 @@ static int tpm2_build_sealing_policy( } if (pubkey_pcr_mask != 0) { - _cleanup_free_ void *fp = NULL; - size_t fp_size = 0; - TPM2B_PUBLIC pubkey_tpm2; - - log_debug("Configuring public key based PCR policy."); - - /* 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; - - _cleanup_tpm2_handle_ Tpm2Handle *pubkey_handle = NULL; - r = tpm2_handle_new(c, &pubkey_handle); - if (r < 0) - return r; - - rc = sym_Esys_LoadExternal( - c->esys_context, - ESYS_TR_NONE, - ESYS_TR_NONE, - ESYS_TR_NONE, - NULL, - &pubkey_tpm2, -#if HAVE_TSS2_ESYS3 - /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested - * hierarchy, older versions need TPM2_RH_* instead. */ - ESYS_TR_RH_OWNER, -#else - TPM2_RH_OWNER, -#endif - &pubkey_handle->esys_handle); - if (rc != TSS2_RC_SUCCESS) - return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), - "Failed to load public key into TPM: %s", sym_Tss2_RC_Decode(rc)); - - /* Acquire the "name" of what we just loaded */ - _cleanup_(Esys_Freep) TPM2B_NAME *pubkey_name = NULL; - r = tpm2_get_name(c, pubkey_handle, &pubkey_name); - if (r < 0) - return r; - - /* Put together the PCR policy we want to use */ TPML_PCR_SELECTION pcr_selection; tpm2_tpml_pcr_selection_from_mask(pubkey_pcr_mask, (TPMI_ALG_HASH)pcr_bank, &pcr_selection); - _cleanup_(Esys_Freep) TPM2B_DIGEST *approved_policy = NULL; - r = tpm2_policy_pcr(c, session, &pcr_selection, &approved_policy); + r = tpm2_policy_authorize(c, session, &pcr_selection, public, fp, fp_size, signature_json, NULL); if (r < 0) return r; - - /* When we are unlocking and have a signature, let's pass it to the TPM */ - _cleanup_(Esys_Freep) TPMT_TK_VERIFIED *check_ticket_buffer = NULL; - const TPMT_TK_VERIFIED *check_ticket; - if (signature_json) { - _cleanup_free_ void *signature_raw = NULL; - size_t signature_size; - - r = find_signature( - signature_json, - &pcr_selection, - fp, fp_size, - approved_policy->buffer, - approved_policy->size, - &signature_raw, - &signature_size); - if (r < 0) - return r; - - /* TPM2_VerifySignature() will only verify the RSA part of the RSA+SHA256 signature, - * hence we need to do the SHA256 part ourselves, first */ - TPM2B_DIGEST signature_hash = *approved_policy; - r = tpm2_digest_rehash(TPM2_ALG_SHA256, &signature_hash); - if (r < 0) - return r; - - TPMT_SIGNATURE policy_signature = { - .sigAlg = TPM2_ALG_RSASSA, - .signature.rsassa = { - .hash = TPM2_ALG_SHA256, - .sig.size = signature_size, - }, - }; - if (signature_size > sizeof(policy_signature.signature.rsassa.sig.buffer)) - return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Signature larger than buffer."); - memcpy(policy_signature.signature.rsassa.sig.buffer, signature_raw, signature_size); - - rc = sym_Esys_VerifySignature( - c->esys_context, - pubkey_handle->esys_handle, - ESYS_TR_NONE, - ESYS_TR_NONE, - ESYS_TR_NONE, - &signature_hash, - &policy_signature, - &check_ticket_buffer); - if (rc != TSS2_RC_SUCCESS) - return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), - "Failed to validate signature in TPM: %s", sym_Tss2_RC_Decode(rc)); - - check_ticket = check_ticket_buffer; - } else { - /* When enrolling, we pass a NULL ticket */ - static const TPMT_TK_VERIFIED check_ticket_null = { - .tag = TPM2_ST_VERIFIED, - .hierarchy = TPM2_RH_OWNER, - }; - - check_ticket = &check_ticket_null; - } - - rc = sym_Esys_PolicyAuthorize( - c->esys_context, - session->esys_handle, - ESYS_TR_NONE, - ESYS_TR_NONE, - ESYS_TR_NONE, - approved_policy, - /* policyRef= */ &(const TPM2B_NONCE) {}, - pubkey_name, - check_ticket); - 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)); } if (hash_pcr_mask != 0) { @@ -2527,6 +2409,16 @@ int tpm2_seal(const char *device, return r; } + TPM2B_PUBLIC pubkey_tpm2, *authorize_key = NULL; + _cleanup_free_ void *fp = NULL; + size_t fp_size = 0; + if (pubkey) { + r = openssl_pubkey_to_tpm2_pubkey(pubkey, pubkey_size, &pubkey_tpm2, &fp, &fp_size); + if (r < 0) + return r; + authorize_key = &pubkey_tpm2; + } + _cleanup_tpm2_handle_ Tpm2Handle *primary = NULL; r = tpm2_make_primary(c, /* alg = */0, !!ret_srk_buf, &primary_alg, &primary); if (r < 0) @@ -2565,7 +2457,8 @@ int tpm2_seal(const char *device, policy_session, hash_pcr_mask, pcr_bank, - pubkey, pubkey_size, + authorize_key, + fp, fp_size, pubkey_pcr_mask, /* signature_json= */ NULL, !!pin, @@ -2831,6 +2724,16 @@ int tpm2_unseal(const char *device, sym_Tss2_RC_Decode(rc)); } + TPM2B_PUBLIC pubkey_tpm2, *authorize_key = NULL; + _cleanup_free_ void *fp = NULL; + size_t fp_size = 0; + if (pubkey) { + r = openssl_pubkey_to_tpm2_pubkey(pubkey, pubkey_size, &pubkey_tpm2, &fp, &fp_size); + if (r < 0) + return r; + authorize_key = &pubkey_tpm2; + } + /* * if a pin is set for the seal object, use it to bind the session * key to that object. This prevents active bus interposers from @@ -2864,7 +2767,8 @@ int tpm2_unseal(const char *device, policy_session, hash_pcr_mask, pcr_bank, - pubkey, pubkey_size, + authorize_key, + fp, fp_size, pubkey_pcr_mask, signature, !!pin,