tpm2: move policy calculation out of tpm2_seal()
Move the calculation of the sealed object policy hash out of the tpm2_seal() function. Instead, callers of tpm2_seal() can directly call tpm2_calculate_sealing_policy() and then provide the policy hash to tpm2_seal().
This commit is contained in:
@@ -133,7 +133,8 @@ int enroll_tpm2(struct crypt_device *cd,
|
||||
const void *volume_key,
|
||||
size_t volume_key_size,
|
||||
const char *device,
|
||||
uint32_t hash_pcr_mask,
|
||||
Tpm2PCRValue *hash_pcr_values,
|
||||
size_t n_hash_pcr_values,
|
||||
const char *pubkey_path,
|
||||
uint32_t pubkey_pcr_mask,
|
||||
const char *signature_path,
|
||||
@@ -143,9 +144,8 @@ int enroll_tpm2(struct crypt_device *cd,
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *signature_json = NULL;
|
||||
_cleanup_(erase_and_freep) char *base64_encoded = NULL;
|
||||
_cleanup_free_ void *srk_buf = NULL;
|
||||
size_t secret_size, blob_size, hash_size, pubkey_size = 0, srk_buf_size = 0;
|
||||
_cleanup_free_ void *blob = NULL, *hash = NULL, *pubkey = NULL;
|
||||
uint16_t pcr_bank, primary_alg;
|
||||
size_t secret_size, blob_size, pubkey_size = 0, srk_buf_size = 0;
|
||||
_cleanup_free_ void *blob = NULL, *pubkey = NULL;
|
||||
const char *node;
|
||||
_cleanup_(erase_and_freep) char *pin_str = NULL;
|
||||
ssize_t base64_encoded_size;
|
||||
@@ -163,7 +163,7 @@ int enroll_tpm2(struct crypt_device *cd,
|
||||
assert(cd);
|
||||
assert(volume_key);
|
||||
assert(volume_key_size > 0);
|
||||
assert(TPM2_PCR_MASK_VALID(hash_pcr_mask));
|
||||
assert(TPM2_PCR_VALUES_VALID(hash_pcr_values, n_hash_pcr_values));
|
||||
assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
|
||||
|
||||
assert_se(node = crypt_get_device_name(cd));
|
||||
@@ -206,23 +206,69 @@ int enroll_tpm2(struct crypt_device *cd,
|
||||
return log_debug_errno(r, "Failed to read TPM PCR signature: %m");
|
||||
}
|
||||
|
||||
r = tpm2_seal(device,
|
||||
hash_pcr_mask,
|
||||
pubkey, pubkey_size,
|
||||
pubkey_pcr_mask,
|
||||
_cleanup_(tpm2_context_unrefp) Tpm2Context *tpm2_context = NULL;
|
||||
r = tpm2_context_new(device, &tpm2_context);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
bool pcr_value_specified = false;
|
||||
for (size_t i = 0; i < n_hash_pcr_values; i++)
|
||||
if (hash_pcr_values[i].value.size > 0) {
|
||||
pcr_value_specified = true;
|
||||
break;
|
||||
}
|
||||
|
||||
r = tpm2_pcr_read_missing_values(tpm2_context, hash_pcr_values, n_hash_pcr_values);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
uint16_t hash_pcr_bank = 0;
|
||||
uint32_t hash_pcr_mask = 0;
|
||||
if (n_hash_pcr_values > 0) {
|
||||
size_t hash_count;
|
||||
r = tpm2_pcr_values_hash_count(hash_pcr_values, n_hash_pcr_values, &hash_count);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not get hash count: %m");
|
||||
|
||||
if (hash_count > 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Multiple PCR banks selected.");
|
||||
|
||||
hash_pcr_bank = hash_pcr_values[0].hash;
|
||||
r = tpm2_pcr_values_to_mask(hash_pcr_values, n_hash_pcr_values, hash_pcr_bank, &hash_pcr_mask);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not get hash mask: %m");
|
||||
}
|
||||
|
||||
TPM2B_PUBLIC public;
|
||||
if (pubkey) {
|
||||
r = tpm2_tpm2b_public_from_pem(pubkey, pubkey_size, &public);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not convert public key to TPM2B_PUBLIC: %m");
|
||||
}
|
||||
|
||||
TPM2B_DIGEST policy = TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE);
|
||||
r = tpm2_calculate_sealing_policy(
|
||||
hash_pcr_values,
|
||||
n_hash_pcr_values,
|
||||
pubkey ? &public : NULL,
|
||||
use_pin,
|
||||
&policy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = tpm2_seal(tpm2_context,
|
||||
&policy,
|
||||
pin_str,
|
||||
&secret, &secret_size,
|
||||
&blob, &blob_size,
|
||||
&hash, &hash_size,
|
||||
&pcr_bank,
|
||||
&primary_alg,
|
||||
/* ret_primary_alg= */ NULL,
|
||||
&srk_buf,
|
||||
&srk_buf_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Let's see if we already have this specific PCR policy hash enrolled, if so, exit early. */
|
||||
r = search_policy_hash(cd, hash, hash_size);
|
||||
r = search_policy_hash(cd, policy.buffer, policy.size);
|
||||
if (r == -ENOENT)
|
||||
log_debug_errno(r, "PCR policy hash not yet enrolled, enrolling now.");
|
||||
else if (r < 0)
|
||||
@@ -233,21 +279,21 @@ int enroll_tpm2(struct crypt_device *cd,
|
||||
}
|
||||
|
||||
/* Quick verification that everything is in order, we are not in a hurry after all. */
|
||||
if (!pubkey || signature_json) {
|
||||
if ((!pubkey || signature_json) && !pcr_value_specified) {
|
||||
_cleanup_(erase_and_freep) void *secret2 = NULL;
|
||||
size_t secret2_size;
|
||||
|
||||
log_debug("Unsealing for verification...");
|
||||
r = tpm2_unseal(device,
|
||||
hash_pcr_mask,
|
||||
pcr_bank,
|
||||
hash_pcr_bank,
|
||||
pubkey, pubkey_size,
|
||||
pubkey_pcr_mask,
|
||||
signature_json,
|
||||
pin_str,
|
||||
primary_alg,
|
||||
/* primary_alg= */ 0,
|
||||
blob, blob_size,
|
||||
hash, hash_size,
|
||||
policy.buffer, policy.size,
|
||||
srk_buf, srk_buf_size,
|
||||
&secret2, &secret2_size);
|
||||
if (r < 0)
|
||||
@@ -279,12 +325,12 @@ int enroll_tpm2(struct crypt_device *cd,
|
||||
r = tpm2_make_luks2_json(
|
||||
keyslot,
|
||||
hash_pcr_mask,
|
||||
pcr_bank,
|
||||
hash_pcr_bank,
|
||||
pubkey, pubkey_size,
|
||||
pubkey_pcr_mask,
|
||||
primary_alg,
|
||||
/* primary_alg= */ 0,
|
||||
blob, blob_size,
|
||||
hash, hash_size,
|
||||
policy.buffer, policy.size,
|
||||
use_pin ? binary_salt : NULL,
|
||||
use_pin ? sizeof(binary_salt) : 0,
|
||||
srk_buf, srk_buf_size,
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
|
||||
#include "cryptsetup-util.h"
|
||||
#include "log.h"
|
||||
#include "tpm2-util.h"
|
||||
|
||||
#if HAVE_TPM2
|
||||
int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, uint32_t hash_pcr_mask, const char *pubkey_path, uint32_t pubkey_pcr_mask, const char *signature_path, bool use_pin);
|
||||
int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, Tpm2PCRValue *hash_pcrs, size_t n_hash_pcrs, const char *pubkey_path, uint32_t pubkey_pcr_mask, const char *signature_path, bool use_pin);
|
||||
#else
|
||||
static inline int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, uint32_t hash_pcr_mask, const char *pubkey_path, uint32_t pubkey_pcr_mask, const char *signature_path, bool use_pin) {
|
||||
static inline int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, Tpm2PCRValue *hash_pcrs, size_t n_hash_pcrs, const char *pubkey_path, uint32_t pubkey_pcr_mask, const char *signature_path, bool use_pin) {
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"TPM2 key enrollment not supported.");
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
#include "tpm-pcr.h"
|
||||
#include "tpm2-util.h"
|
||||
|
||||
static EnrollType arg_enroll_type = _ENROLL_TYPE_INVALID;
|
||||
static char *arg_unlock_keyfile = NULL;
|
||||
@@ -37,10 +36,13 @@ static char *arg_unlock_fido2_device = NULL;
|
||||
static char *arg_pkcs11_token_uri = NULL;
|
||||
static char *arg_fido2_device = NULL;
|
||||
static char *arg_tpm2_device = NULL;
|
||||
static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
|
||||
static Tpm2PCRValue *arg_tpm2_hash_pcr_values = NULL;
|
||||
static size_t arg_tpm2_n_hash_pcr_values = 0;
|
||||
static bool arg_tpm2_hash_pcr_values_use_default = true;
|
||||
static bool arg_tpm2_pin = false;
|
||||
static char *arg_tpm2_public_key = NULL;
|
||||
static uint32_t arg_tpm2_public_key_pcr_mask = UINT32_MAX;
|
||||
static uint32_t arg_tpm2_public_key_pcr_mask = 0;
|
||||
static bool arg_tpm2_public_key_pcr_mask_use_default = true;
|
||||
static char *arg_tpm2_signature = NULL;
|
||||
static char *arg_node = NULL;
|
||||
static int *arg_wipe_slots = NULL;
|
||||
@@ -61,6 +63,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_unlock_fido2_device, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_pkcs11_token_uri, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_fido2_device, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_hash_pcr_values, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_public_key, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_signature, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_node, freep);
|
||||
@@ -356,7 +359,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
case ARG_TPM2_PCRS:
|
||||
r = tpm2_parse_pcr_argument_to_mask(optarg, &arg_tpm2_pcr_mask);
|
||||
arg_tpm2_hash_pcr_values_use_default = false;
|
||||
r = tpm2_parse_pcr_argument_append(optarg, &arg_tpm2_hash_pcr_values, &arg_tpm2_n_hash_pcr_values);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -377,6 +381,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_TPM2_PUBLIC_KEY_PCRS:
|
||||
arg_tpm2_public_key_pcr_mask_use_default = false;
|
||||
r = tpm2_parse_pcr_argument_to_mask(optarg, &arg_tpm2_public_key_pcr_mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -476,10 +481,15 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (arg_tpm2_pcr_mask == UINT32_MAX)
|
||||
arg_tpm2_pcr_mask = TPM2_PCR_MASK_DEFAULT;
|
||||
if (arg_tpm2_public_key_pcr_mask == UINT32_MAX)
|
||||
arg_tpm2_public_key_pcr_mask = UINT32_C(1) << TPM_PCR_INDEX_KERNEL_IMAGE;
|
||||
if (arg_tpm2_public_key_pcr_mask_use_default && arg_tpm2_public_key)
|
||||
arg_tpm2_public_key_pcr_mask = INDEX_TO_MASK(uint32_t, TPM_PCR_INDEX_KERNEL_IMAGE);
|
||||
|
||||
if (arg_tpm2_hash_pcr_values_use_default && !GREEDY_REALLOC_APPEND(
|
||||
arg_tpm2_hash_pcr_values,
|
||||
arg_tpm2_n_hash_pcr_values,
|
||||
&TPM2_PCR_VALUE_MAKE(TPM2_PCR_INDEX_DEFAULT, /* hash= */ 0, /* value= */ {}),
|
||||
1))
|
||||
return log_oom();
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -655,7 +665,7 @@ static int run(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ENROLL_TPM2:
|
||||
slot = enroll_tpm2(cd, vk, vks, arg_tpm2_device, arg_tpm2_pcr_mask, arg_tpm2_public_key, arg_tpm2_public_key_pcr_mask, arg_tpm2_signature, arg_tpm2_pin);
|
||||
slot = enroll_tpm2(cd, vk, vks, arg_tpm2_device, arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values, arg_tpm2_public_key, arg_tpm2_public_key_pcr_mask, arg_tpm2_signature, arg_tpm2_pin);
|
||||
break;
|
||||
|
||||
case _ENROLL_TYPE_INVALID:
|
||||
|
||||
Reference in New Issue
Block a user