Files
systemd/src/shared/cryptsetup-tpm2.h
Lennart Poettering 8e6587679b cryptenroll/cryptsetup: allow combined signed TPM2 PCR policy + pcrlock policy
So far you had to pick:

1. Use a signed PCR TPM2 policy to lock your disk to (i.e. UKI vendor
   blesses your setup via signature)
or
2. Use a pcrlock policy (i.e. local system blesses your setup via
   dynamic local policy stored in NV index)

It was not possible combine these two, because TPM2 access policies do
not allow the combination of PolicyAuthorize (used to implement #1
above) and PolicyAuthorizeNV (used to implement #2) in a single policy,
unless one is "further upstream" (and can simply remove the other from
the policy freely).

This is quite limiting of course, since we actually do want to enforce
on each TPM object that both the OS vendor policy and the local policy
must be fulfilled, without the chance for the vendor or the local system
to disable the other.

This patch addresses this: instead of trying to find a way to come up
with some adventurous scheme to combine both policy into one TPM2
policy, we simply shard the symmetric LUKS decryption key: one half we
protect via the signed PCR policy, and the other we protect via the
pcrlock policy. Only if both halves can be acquired the disk can be
decrypted.

This means:

1. we simply double the unlock key in length in case both policies shall
   be used.
2. We store two resulting TPM policy hashes in the LUKS token JSON, one
   for each policy
3. We store two sealed TPM policy key blobs in the LUKS token JSON, for
   both halves of the LUKS unlock key.

This patch keeps the "sharding" logic relatively generic (i.e. the low
level logic is actually fine with more than 2 shards), because I figure
sooner or later we might have to encode more shards, for example if we
add further TPM2-based access policies, for example when combining FIDO2
with TPM2, or implementing TOTP for this.
2024-09-06 15:55:28 +02:00

117 lines
4.0 KiB
C

/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <sys/types.h>
#include "ask-password-api.h"
#include "cryptsetup-util.h"
#include "log.h"
#include "time-util.h"
#include "tpm2-util.h"
#if HAVE_TPM2
int acquire_tpm2_key(
const char *volume_name,
const char *device,
uint32_t hash_pcr_mask,
uint16_t pcr_bank,
const struct iovec *pubkey,
uint32_t pubkey_pcr_mask,
const char *signature_path,
const char *pcrlock_path,
uint16_t primary_alg,
const char *key_file,
size_t key_file_size,
uint64_t key_file_offset,
const struct iovec blobs[],
size_t n_blobs,
const struct iovec policy_hash[],
size_t n_policy_hash,
const struct iovec *salt,
const struct iovec *srk,
const struct iovec *pcrlock_nv,
TPM2Flags flags,
usec_t until,
const char *askpw_credential,
AskPasswordFlags askpw_flags,
struct iovec *ret_decrypted_key);
int find_tpm2_auto_data(
struct crypt_device *cd,
uint32_t search_pcr_mask,
int start_token,
uint32_t *ret_hash_pcr_mask,
uint16_t *ret_pcr_bank,
struct iovec *ret_pubkey,
uint32_t *ret_pubkey_pcr_mask,
uint16_t *ret_primary_alg,
struct iovec **ret_blobs,
size_t *ret_n_blobs,
struct iovec **ret_policy_hash,
size_t *ret_n_policy_hash,
struct iovec *ret_salt,
struct iovec *ret_srk,
struct iovec *ret_pcrlock_nv,
TPM2Flags *ret_flags,
int *ret_keyslot,
int *ret_token);
#else
static inline int acquire_tpm2_key(
const char *volume_name,
const char *device,
uint32_t hash_pcr_mask,
uint16_t pcr_bank,
const struct iovec *pubkey,
uint32_t pubkey_pcr_mask,
const char *signature_path,
const char *pcrlock_path,
uint16_t primary_alg,
const char *key_file,
size_t key_file_size,
uint64_t key_file_offset,
const struct iovec blobs[],
size_t n_blobs,
const struct iovec policy_hash[],
size_t n_policy_hash,
const struct iovec *salt,
const struct iovec *srk,
const struct iovec *pcrlock_nv,
TPM2Flags flags,
usec_t until,
const char *askpw_credential,
AskPasswordFlags askpw_flags,
struct iovec *ret_decrypted_key) {
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"TPM2 support not available.");
}
static inline int find_tpm2_auto_data(
struct crypt_device *cd,
uint32_t search_pcr_mask,
int start_token,
uint32_t *ret_hash_pcr_mask,
uint16_t *ret_pcr_bank,
struct iovec *ret_pubkey,
uint32_t *ret_pubkey_pcr_mask,
uint16_t *ret_primary_alg,
struct iovec **ret_blobs,
size_t *ret_n_blobs,
struct iovec **ret_policy_hash,
size_t *ret_n_policy_hash,
struct iovec *ret_salt,
struct iovec *ret_srk,
struct iovec *ret_pcrlock_nv,
TPM2Flags *ret_flags,
int *ret_keyslot,
int *ret_token) {
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"TPM2 support not available.");
}
#endif