diff --git a/src/cryptenroll/cryptenroll-tpm2.c b/src/cryptenroll/cryptenroll-tpm2.c index 9c1478c474..697b4c2335 100644 --- a/src/cryptenroll/cryptenroll-tpm2.c +++ b/src/cryptenroll/cryptenroll-tpm2.c @@ -65,6 +65,7 @@ int enroll_tpm2(struct crypt_device *cd, _cleanup_(erase_and_freep) char *base64_encoded = NULL; size_t secret_size, secret2_size, blob_size, hash_size; _cleanup_free_ void *blob = NULL, *hash = NULL; + uint16_t pcr_bank; const char *node; int r, keyslot; @@ -75,7 +76,7 @@ int enroll_tpm2(struct crypt_device *cd, assert_se(node = crypt_get_device_name(cd)); - r = tpm2_seal(device, pcr_mask, &secret, &secret_size, &blob, &blob_size, &hash, &hash_size); + r = tpm2_seal(device, pcr_mask, &secret, &secret_size, &blob, &blob_size, &hash, &hash_size, &pcr_bank); if (r < 0) return r; @@ -92,7 +93,7 @@ int enroll_tpm2(struct crypt_device *cd, /* Quick verification that everything is in order, we are not in a hurry after all. */ log_debug("Unsealing for verification..."); - r = tpm2_unseal(device, pcr_mask, blob, blob_size, hash, hash_size, &secret2, &secret2_size); + r = tpm2_unseal(device, pcr_mask, pcr_bank, blob, blob_size, hash, hash_size, &secret2, &secret2_size); if (r < 0) return r; @@ -118,7 +119,7 @@ int enroll_tpm2(struct crypt_device *cd, if (keyslot < 0) return log_error_errno(keyslot, "Failed to add new TPM2 key to %s: %m", node); - r = tpm2_make_luks2_json(keyslot, pcr_mask, blob, blob_size, hash, hash_size, &v); + r = tpm2_make_luks2_json(keyslot, pcr_mask, pcr_bank, blob, blob_size, hash, hash_size, &v); if (r < 0) return log_error_errno(r, "Failed to prepare TPM2 JSON token object: %m"); diff --git a/src/cryptsetup/cryptsetup-tpm2.c b/src/cryptsetup/cryptsetup-tpm2.c index 4757c5882d..8da1880a35 100644 --- a/src/cryptsetup/cryptsetup-tpm2.c +++ b/src/cryptsetup/cryptsetup-tpm2.c @@ -13,6 +13,7 @@ int acquire_tpm2_key( const char *volume_name, const char *device, uint32_t pcr_mask, + uint16_t pcr_bank, const char *key_file, size_t key_file_size, uint64_t key_file_offset, @@ -62,7 +63,7 @@ int acquire_tpm2_key( blob = loaded_blob; } - return tpm2_unseal(device, pcr_mask, blob, blob_size, policy_hash, policy_hash_size, ret_decrypted_key, ret_decrypted_key_size); + return tpm2_unseal(device, pcr_mask, pcr_bank, blob, blob_size, policy_hash, policy_hash_size, ret_decrypted_key, ret_decrypted_key_size); } int find_tpm2_auto_data( @@ -70,6 +71,7 @@ int find_tpm2_auto_data( uint32_t search_pcr_mask, int start_token, uint32_t *ret_pcr_mask, + uint16_t *ret_pcr_bank, void **ret_blob, size_t *ret_blob_size, void **ret_policy_hash, @@ -81,6 +83,7 @@ int find_tpm2_auto_data( size_t blob_size = 0, policy_hash_size = 0; int r, keyslot = -1, token = -1; uint32_t pcr_mask = 0; + uint16_t pcr_bank = UINT16_MAX; /* default: pick automatically */ assert(cd); @@ -119,6 +122,23 @@ int find_tpm2_auto_data( search_pcr_mask != pcr_mask) /* PCR mask doesn't match what is configured, ignore this entry */ continue; + /* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded to SHA256 */ + assert(pcr_bank == UINT16_MAX); + w = json_variant_by_key(v, "tpm2-pcr-bank"); + if (w) { + /* The PCR bank field is optional */ + + if (!json_variant_is_string(w)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "TPM2 PCR bank is not a string."); + + r = tpm2_pcr_bank_from_string(json_variant_string(w)); + if (r < 0) + return log_error_errno(r, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w)); + + pcr_bank = r; + } + assert(!blob); w = json_variant_by_key(v, "tpm2-blob"); if (!w || !json_variant_is_string(w)) @@ -163,6 +183,7 @@ int find_tpm2_auto_data( *ret_policy_hash_size = policy_hash_size; *ret_keyslot = keyslot; *ret_token = token; + *ret_pcr_bank = pcr_bank; return 0; } diff --git a/src/cryptsetup/cryptsetup-tpm2.h b/src/cryptsetup/cryptsetup-tpm2.h index 8ddf301a63..a82ecb4594 100644 --- a/src/cryptsetup/cryptsetup-tpm2.h +++ b/src/cryptsetup/cryptsetup-tpm2.h @@ -13,6 +13,7 @@ int acquire_tpm2_key( const char *volume_name, const char *device, uint32_t pcr_mask, + uint16_t pcr_bank, const char *key_file, size_t key_file_size, uint64_t key_file_offset, @@ -28,6 +29,7 @@ int find_tpm2_auto_data( uint32_t search_pcr_mask, int start_token, uint32_t *ret_pcr_mask, + uint16_t *ret_pcr_bank, void **ret_blob, size_t *ret_blob_size, void **ret_policy_hash, @@ -41,6 +43,7 @@ static inline int acquire_tpm2_key( const char *volume_name, const char *device, uint32_t pcr_mask, + uint16_t pcr_bank, const char *key_file, size_t key_file_size, uint64_t key_file_offset, @@ -60,6 +63,7 @@ static inline int find_tpm2_auto_data( uint32_t search_pcr_mask, int start_token, uint32_t *ret_pcr_mask, + uint16_t *ret_pcr_bank, void **ret_blob, size_t *ret_blob_size, void **ret_policy_hash, diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 48621ef583..0d3ea9cda6 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -1103,6 +1103,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2( name, arg_tpm2_device, arg_tpm2_pcr_mask == UINT32_MAX ? TPM2_PCR_MASK_DEFAULT : arg_tpm2_pcr_mask, + UINT16_MAX, key_file, arg_keyfile_size, arg_keyfile_offset, key_data, key_data_size, NULL, 0, /* we don't know the policy hash */ @@ -1139,12 +1140,14 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2( for (;;) { uint32_t pcr_mask; + uint16_t pcr_bank; r = find_tpm2_auto_data( cd, arg_tpm2_pcr_mask, /* if != UINT32_MAX we'll only look for tokens with this PCR mask */ token, /* search for the token with this index, or any later index than this */ &pcr_mask, + &pcr_bank, &blob, &blob_size, &policy_hash, &policy_hash_size, &keyslot, @@ -1166,6 +1169,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2( name, arg_tpm2_device, pcr_mask, + pcr_bank, NULL, 0, 0, /* no key file */ blob, blob_size, policy_hash, policy_hash_size, diff --git a/src/partition/repart.c b/src/partition/repart.c index 6d535a3bab..42a8260c2e 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -2624,9 +2624,10 @@ static int partition_encrypt( _cleanup_(erase_and_freep) void *secret = NULL; _cleanup_free_ void *blob = NULL, *hash = NULL; size_t secret_size, blob_size, hash_size; + uint16_t pcr_bank; int keyslot; - r = tpm2_seal(arg_tpm2_device, arg_tpm2_pcr_mask, &secret, &secret_size, &blob, &blob_size, &hash, &hash_size); + r = tpm2_seal(arg_tpm2_device, arg_tpm2_pcr_mask, &secret, &secret_size, &blob, &blob_size, &hash, &hash_size, &pcr_bank); if (r < 0) return log_error_errno(r, "Failed to seal to TPM2: %m"); @@ -2648,7 +2649,7 @@ static int partition_encrypt( if (keyslot < 0) return log_error_errno(keyslot, "Failed to add new TPM2 key to %s: %m", node); - r = tpm2_make_luks2_json(keyslot, arg_tpm2_pcr_mask, blob, blob_size, hash, hash_size, &v); + r = tpm2_make_luks2_json(keyslot, arg_tpm2_pcr_mask, pcr_bank, blob, blob_size, hash, hash_size, &v); if (r < 0) return log_error_errno(r, "Failed to prepare TPM2 JSON token object: %m"); diff --git a/src/shared/creds-util.c b/src/shared/creds-util.c index 6c2d9dbc76..ee279e0c9c 100644 --- a/src/shared/creds-util.c +++ b/src/shared/creds-util.c @@ -369,7 +369,10 @@ struct _packed_ encrypted_credential_header { }; struct _packed_ tpm2_credential_header { - le64_t pcr_mask; + le64_t pcr_mask; /* Note that the spec for PC Clients only mandates 24 PCRs, and that's what systems + * generally have. But keep the door open for more. */ + le16_t pcr_bank; /* For now, either TPM2_ALG_SHA256 or TPM2_ALG_SHA1 */ + le16_t _zero; /* Filler to maintain 32bit alignment */ le32_t blob_size; le32_t policy_hash_size; uint8_t policy_hash_and_blob[]; @@ -439,6 +442,7 @@ int encrypt_credential_and_warn( struct encrypted_credential_header *h; int ksz, bsz, ivsz, tsz, added, r; uint8_t md[SHA256_DIGEST_LENGTH]; + uint16_t tpm2_pcr_bank = 0; const EVP_CIPHER *cc; #if HAVE_TPM2 bool try_tpm2 = false; @@ -505,7 +509,8 @@ int encrypt_credential_and_warn( &tpm2_blob, &tpm2_blob_size, &tpm2_policy_hash, - &tpm2_policy_hash_size); + &tpm2_policy_hash_size, + &tpm2_pcr_bank); if (r < 0) { if (!sd_id128_is_null(with_key)) return r; @@ -598,6 +603,7 @@ int encrypt_credential_and_warn( t = (struct tpm2_credential_header*) ((uint8_t*) output + p); t->pcr_mask = htole64(tpm2_pcr_mask); + t->pcr_bank = htole16(tpm2_pcr_bank); t->blob_size = htole32(tpm2_blob_size); t->policy_hash_size = htole32(tpm2_policy_hash_size); memcpy(t->policy_hash_and_blob, tpm2_blob, tpm2_blob_size); @@ -739,6 +745,10 @@ int decrypt_credential_and_warn( if (le64toh(t->pcr_mask) >= (UINT64_C(1) << TPM2_PCRS_MAX)) return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "TPM2 PCR mask out of range."); + if (!tpm2_pcr_bank_supported(le16toh(t->pcr_bank))) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "TPM2 PCR bank invalid or not supported"); + if (le16toh(t->_zero) != 0) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "TPM2 padding space not zero."); if (le32toh(t->blob_size) > CREDENTIAL_FIELD_SIZE_MAX) return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected TPM2 blob size."); if (le32toh(t->policy_hash_size) > CREDENTIAL_FIELD_SIZE_MAX) @@ -755,6 +765,7 @@ int decrypt_credential_and_warn( r = tpm2_unseal(tpm2_device, le64toh(t->pcr_mask), + le16toh(t->pcr_bank), t->policy_hash_and_blob, le32toh(t->blob_size), t->policy_hash_and_blob + le32toh(t->blob_size), diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index 79e879b482..5cb6563b43 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -25,6 +25,7 @@ TSS2_RC (*sym_Esys_CreatePrimary)(ESYS_CONTEXT *esysContext, ESYS_TR primaryHand void (*sym_Esys_Finalize)(ESYS_CONTEXT **context) = NULL; TSS2_RC (*sym_Esys_FlushContext)(ESYS_CONTEXT *esysContext, ESYS_TR flushHandle) = NULL; void (*sym_Esys_Free)(void *ptr) = NULL; +TSS2_RC (*sym_Esys_GetCapability)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2_CAP capability, UINT32 property, UINT32 propertyCount, TPMI_YES_NO *moreData, TPMS_CAPABILITY_DATA **capabilityData); TSS2_RC (*sym_Esys_GetRandom)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, UINT16 bytesRequested, TPM2B_DIGEST **randomBytes) = NULL; TSS2_RC (*sym_Esys_Initialize)(ESYS_CONTEXT **esys_context, TSS2_TCTI_CONTEXT *tcti, TSS2_ABI_VERSION *abiVersion) = NULL; TSS2_RC (*sym_Esys_Load)(ESYS_CONTEXT *esysContext, ESYS_TR parentHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_PRIVATE *inPrivate, const TPM2B_PUBLIC *inPublic, ESYS_TR *objectHandle) = NULL; @@ -51,6 +52,7 @@ int dlopen_tpm2(void) { DLSYM_ARG(Esys_Finalize), DLSYM_ARG(Esys_FlushContext), DLSYM_ARG(Esys_Free), + DLSYM_ARG(Esys_GetCapability), DLSYM_ARG(Esys_GetRandom), DLSYM_ARG(Esys_Initialize), DLSYM_ARG(Esys_Load), @@ -310,11 +312,93 @@ static int tpm2_make_primary( return 0; } +static int tpm2_get_best_pcr_bank( + ESYS_CONTEXT *c, + TPMI_ALG_HASH *ret) { + + _cleanup_(Esys_Freep) TPMS_CAPABILITY_DATA *pcap = NULL; + TPMI_ALG_HASH hash = TPM2_ALG_SHA1; + bool found = false; + TPMI_YES_NO more; + TSS2_RC rc; + + rc = sym_Esys_GetCapability( + c, + ESYS_TR_NONE, + ESYS_TR_NONE, + ESYS_TR_NONE, + TPM2_CAP_PCRS, + 0, + 1, + &more, + &pcap); + if (rc != TSS2_RC_SUCCESS) + return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), + "Failed to determine TPM2 PCR bank capabilities: %s", sym_Tss2_RC_Decode(rc)); + + assert(pcap->capability == TPM2_CAP_PCRS); + + for (size_t i = 0; i < pcap->data.assignedPCR.count; i++) { + bool valid = true; + + /* As per + * https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf a + * TPM2 on a Client PC must have at least 24 PCRs. If this TPM has less, just skip over + * it. */ + if (pcap->data.assignedPCR.pcrSelections[i].sizeofSelect < TPM2_PCRS_MAX/8) { + log_debug("Skipping TPM2 PCR bank %s with fewer than 24 PCRs.", + strna(tpm2_pcr_bank_to_string(pcap->data.assignedPCR.pcrSelections[i].hash))); + continue; + } + + assert_cc(TPM2_PCRS_MAX % 8 == 0); + + /* It's not enought to check how many PCRs there are, we also need to check that the 24 are + * enabled for this bank. Otherwise this TPM doesn't qualify. */ + for (size_t j = 0; j < TPM2_PCRS_MAX/8; j++) + if (pcap->data.assignedPCR.pcrSelections[i].pcrSelect[j] != 0xFF) { + valid = false; + break; + } + + if (!valid) { + log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.", + strna(tpm2_pcr_bank_to_string(pcap->data.assignedPCR.pcrSelections[i].hash))); + continue; + } + + if (pcap->data.assignedPCR.pcrSelections[i].hash == TPM2_ALG_SHA256) { + hash = TPM2_ALG_SHA256; + found = true; + break; + } + + if (pcap->data.assignedPCR.pcrSelections[i].hash == TPM2_ALG_SHA1) + found = true; + } + + if (!found) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate."); + + if (hash == TPM2_ALG_SHA256) + log_debug("TPM2 device supports SHA256 PCR banks, yay!"); + else { + assert(hash == TPM2_ALG_SHA1); + log_debug("TPM2 device lacks support for SHA256 PCR banks, falling back to SHA1 banks."); + } + + *ret = hash; + return 0; +} + static int tpm2_make_pcr_session( ESYS_CONTEXT *c, uint32_t pcr_mask, + uint16_t pcr_bank, /* If UINT16_MAX, pick best bank automatically, otherwise specify bank explicitly. */ ESYS_TR *ret_session, - TPM2B_DIGEST **ret_policy_digest) { + TPM2B_DIGEST **ret_policy_digest, + TPMI_ALG_HASH *ret_pcr_bank) { static const TPMT_SYM_DEF symmetric = { .algorithm = TPM2_ALG_AES, @@ -327,7 +411,7 @@ static int tpm2_make_pcr_session( }; TPML_PCR_SELECTION pcr_selection = { .count = 1, - .pcrSelections[0].hash = TPM2_ALG_SHA256, + .pcrSelections[0].hash = TPM2_ALG_SHA256, /* overriden below, depending on TPM2 capabilities */ .pcrSelections[0].sizeofSelect = 3, .pcrSelections[0].pcrSelect[0] = pcr_mask & 0xFF, .pcrSelections[0].pcrSelect[1] = (pcr_mask >> 8) & 0xFF, @@ -342,6 +426,16 @@ static int tpm2_make_pcr_session( log_debug("Starting authentication session."); + if (pcr_bank != UINT16_MAX) + pcr_selection.pcrSelections[0].hash = pcr_bank; + else { + /* No bank configured, pick automatically. Some TPM2 devices only can do SHA1. If we detect + * that use that, but preferably use SHA256 */ + r = tpm2_get_best_pcr_bank(c, &pcr_selection.pcrSelections[0].hash); + if (r < 0) + return r; + } + rc = sym_Esys_StartAuthSession( c, ESYS_TR_NONE, @@ -412,6 +506,9 @@ static int tpm2_make_pcr_session( if (ret_policy_digest) *ret_policy_digest = TAKE_PTR(policy_digest); + if (ret_pcr_bank) + *ret_pcr_bank = pcr_selection.pcrSelections[0].hash; + r = 0; finish: @@ -427,7 +524,8 @@ int tpm2_seal( void **ret_blob, size_t *ret_blob_size, void **ret_pcr_hash, - size_t *ret_pcr_hash_size) { + size_t *ret_pcr_hash_size, + uint16_t *ret_pcr_bank) { _cleanup_(tpm2_context_destroy) struct tpm2_context c = {}; _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL; @@ -439,6 +537,7 @@ int tpm2_seal( TPM2B_SENSITIVE_CREATE hmac_sensitive; ESYS_TR primary = ESYS_TR_NONE; TPM2B_PUBLIC hmac_template; + TPMI_ALG_HASH pcr_bank; size_t k, blob_size; usec_t start; TSS2_RC rc; @@ -450,6 +549,7 @@ int tpm2_seal( assert(ret_blob_size); assert(ret_pcr_hash); assert(ret_pcr_hash_size); + assert(ret_pcr_bank); assert(pcr_mask < (UINT32_C(1) << TPM2_PCRS_MAX)); /* Support 24 PCR banks */ @@ -478,7 +578,7 @@ int tpm2_seal( if (r < 0) return r; - r = tpm2_make_pcr_session(c.esys_context, pcr_mask, NULL, &policy_digest); + r = tpm2_make_pcr_session(c.esys_context, pcr_mask, UINT16_MAX, NULL, &policy_digest, &pcr_bank); if (r < 0) goto finish; @@ -600,6 +700,7 @@ int tpm2_seal( *ret_blob_size = blob_size; *ret_pcr_hash = TAKE_PTR(hash); *ret_pcr_hash_size = policy_digest->size; + *ret_pcr_bank = pcr_bank; r = 0; @@ -611,6 +712,7 @@ finish: int tpm2_unseal( const char *device, uint32_t pcr_mask, + uint16_t pcr_bank, const void *blob, size_t blob_size, const void *known_policy_hash, @@ -670,7 +772,7 @@ int tpm2_unseal( if (r < 0) return r; - r = tpm2_make_pcr_session(c.esys_context, pcr_mask, &session, &policy_digest); + r = tpm2_make_pcr_session(c.esys_context, pcr_mask, pcr_bank, &session, &policy_digest, NULL); if (r < 0) goto finish; @@ -909,6 +1011,7 @@ int tpm2_parse_pcrs(const char *s, uint32_t *ret) { int tpm2_make_luks2_json( int keyslot, uint32_t pcr_mask, + uint16_t pcr_bank, const void *blob, size_t blob_size, const void *policy_hash, @@ -951,6 +1054,7 @@ int tpm2_make_luks2_json( JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string))), JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_BASE64(blob, blob_size)), JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(a)), + JSON_BUILD_PAIR_CONDITION(!!tpm2_pcr_bank_to_string(pcr_bank), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_pcr_bank_to_string(pcr_bank))), JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_HEX(policy_hash, policy_hash_size)))); if (r < 0) return r; @@ -960,3 +1064,36 @@ int tpm2_make_luks2_json( return keyslot; } + +/* We want the helpers below to work also if TPM2 libs are not available, hence define these two defines if + * they are missing. */ +#ifndef TPM2_ALG_SHA256 +#define TPM2_ALG_SHA256 0xB +#endif + +#ifndef TPM2_ALG_SHA1 +#define TPM2_ALG_SHA1 0x4 +#endif + +int tpm2_pcr_bank_supported(uint16_t bank) { + /* For now, let's officially only support these two. We can extend this later on, should the need + * arise. */ + return IN_SET(bank, TPM2_ALG_SHA256, TPM2_ALG_SHA1); +} + +const char *tpm2_pcr_bank_to_string(uint16_t bank) { + /* Similar here, only support the two for now, we can always extend this later. */ + if (bank == TPM2_ALG_SHA256) + return "sha256"; + if (bank == TPM2_ALG_SHA1) + return "sha1"; + return NULL; +} + +int tpm2_pcr_bank_from_string(const char *bank) { + if (streq_ptr(bank, "sha256")) + return TPM2_ALG_SHA256; + if (streq_ptr(bank, "sha1")) + return TPM2_ALG_SHA1; + return -EINVAL; +} diff --git a/src/shared/tpm2-util.h b/src/shared/tpm2-util.h index 9f60fef083..8032afe7b0 100644 --- a/src/shared/tpm2-util.h +++ b/src/shared/tpm2-util.h @@ -15,6 +15,7 @@ extern TSS2_RC (*sym_Esys_CreatePrimary)(ESYS_CONTEXT *esysContext, ESYS_TR prim extern void (*sym_Esys_Finalize)(ESYS_CONTEXT **context); extern TSS2_RC (*sym_Esys_FlushContext)(ESYS_CONTEXT *esysContext, ESYS_TR flushHandle); extern void (*sym_Esys_Free)(void *ptr); +extern TSS2_RC (*sym_Esys_GetCapability)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2_CAP capability, UINT32 property, UINT32 propertyCount, TPMI_YES_NO *moreData, TPMS_CAPABILITY_DATA **capabilityData); extern TSS2_RC (*sym_Esys_GetRandom)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, UINT16 bytesRequested, TPM2B_DIGEST **randomBytes); extern TSS2_RC (*sym_Esys_Initialize)(ESYS_CONTEXT **esys_context, TSS2_TCTI_CONTEXT *tcti, TSS2_ABI_VERSION *abiVersion); extern TSS2_RC (*sym_Esys_Load)(ESYS_CONTEXT *esysContext, ESYS_TR parentHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_PRIVATE *inPrivate, const TPM2B_PUBLIC *inPublic, ESYS_TR *objectHandle); @@ -33,8 +34,8 @@ extern TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal)(uint8_t const buffer[], siz int dlopen_tpm2(void); -int tpm2_seal(const char *device, uint32_t pcr_mask, void **ret_secret, size_t *ret_secret_size, void **ret_blob, size_t *ret_blob_size, void **ret_pcr_hash, size_t *ret_pcr_hash_size); -int tpm2_unseal(const char *device, uint32_t pcr_mask, const void *blob, size_t blob_size, const void *pcr_hash, size_t pcr_hash_size, void **ret_secret, size_t *ret_secret_size); +int tpm2_seal(const char *device, uint32_t pcr_mask, void **ret_secret, size_t *ret_secret_size, void **ret_blob, size_t *ret_blob_size, void **ret_pcr_hash, size_t *ret_pcr_hash_size, uint16_t *ret_pcr_bank); +int tpm2_unseal(const char *device, uint32_t pcr_mask, uint16_t pcr_bank, const void *blob, size_t blob_size, const void *pcr_hash, size_t pcr_hash_size, void **ret_secret, size_t *ret_secret_size); #endif @@ -43,13 +44,17 @@ int tpm2_find_device_auto(int log_level, char **ret); int tpm2_parse_pcrs(const char *s, uint32_t *ret); -int tpm2_make_luks2_json(int keyslot, uint32_t pcr_mask, const void *blob, size_t blob_size, const void *policy_hash, size_t policy_hash_size, JsonVariant **ret); +int tpm2_make_luks2_json(int keyslot, uint32_t pcr_mask, uint16_t pcr_bank, const void *blob, size_t blob_size, const void *policy_hash, size_t policy_hash_size, JsonVariant **ret); #define TPM2_PCRS_MAX 24 /* Default to PCR 7 only */ #define TPM2_PCR_MASK_DEFAULT (UINT32_C(1) << 7) +int tpm2_pcr_bank_supported(uint16_t bank); +const char *tpm2_pcr_bank_to_string(uint16_t bank); +int tpm2_pcr_bank_from_string(const char *bank); + typedef struct { uint32_t search_pcr_mask; const char *device;