Merge pull request #26180 from ddstreet/tpm2_cleanup
Add struct tpm2_handle and use _cleanup_ instead of goto
This commit is contained in:
+50
-79
@@ -726,9 +726,7 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||
_cleanup_(pcr_state_free_all) PcrState *pcr_states = NULL;
|
||||
_cleanup_(EVP_PKEY_freep) EVP_PKEY *privkey = NULL, *pubkey = NULL;
|
||||
_cleanup_(tpm2_context_destroy) struct tpm2_context c = {};
|
||||
_cleanup_fclose_ FILE *privkeyf = NULL;
|
||||
ESYS_TR session_handle = ESYS_TR_NONE;
|
||||
TSS2_RC rc;
|
||||
size_t n;
|
||||
int r;
|
||||
@@ -811,7 +809,8 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = tpm2_context_init(arg_tpm2_device, &c);
|
||||
_cleanup_tpm2_context_ Tpm2Context *c = NULL;
|
||||
r = tpm2_context_new(arg_tpm2_device, &c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -829,8 +828,13 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
|
||||
};
|
||||
PcrState *p = pcr_states + i;
|
||||
|
||||
_cleanup_tpm2_handle_ Tpm2Handle *session = NULL;
|
||||
r = tpm2_handle_new(c, &session);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
rc = sym_Esys_StartAuthSession(
|
||||
c.esys_context,
|
||||
c->esys_context,
|
||||
ESYS_TR_NONE,
|
||||
ESYS_TR_NONE,
|
||||
ESYS_TR_NONE,
|
||||
@@ -840,12 +844,10 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
|
||||
TPM2_SE_TRIAL,
|
||||
&symmetric,
|
||||
TPM2_ALG_SHA256,
|
||||
&session_handle);
|
||||
if (rc != TSS2_RC_SUCCESS) {
|
||||
r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
|
||||
goto finish;
|
||||
}
|
||||
&session->esys_handle);
|
||||
if (rc != TSS2_RC_SUCCESS)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
|
||||
|
||||
/* Generate a single hash value from the PCRs included in our policy. Given that that's
|
||||
* exactly one, the calculation is trivial. */
|
||||
@@ -856,94 +858,72 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
|
||||
sha256_direct(p->value, p->value_size, intermediate_digest.buffer);
|
||||
|
||||
int tpmalg = tpm2_hash_alg_from_string(EVP_MD_name(p->md));
|
||||
if (tpmalg < 0) {
|
||||
log_error_errno(tpmalg, "Unsupported PCR bank");
|
||||
goto finish;
|
||||
}
|
||||
if (tpmalg < 0)
|
||||
return log_error_errno(tpmalg, "Unsupported PCR bank");
|
||||
|
||||
TPML_PCR_SELECTION pcr_selection;
|
||||
tpm2_pcr_mask_to_selection(1 << TPM_PCR_INDEX_KERNEL_IMAGE, tpmalg, &pcr_selection);
|
||||
|
||||
rc = sym_Esys_PolicyPCR(
|
||||
c.esys_context,
|
||||
session_handle,
|
||||
c->esys_context,
|
||||
session->esys_handle,
|
||||
ESYS_TR_NONE,
|
||||
ESYS_TR_NONE,
|
||||
ESYS_TR_NONE,
|
||||
&intermediate_digest,
|
||||
&pcr_selection);
|
||||
if (rc != TSS2_RC_SUCCESS) {
|
||||
r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to push PCR policy into TPM: %s", sym_Tss2_RC_Decode(rc));
|
||||
goto finish;
|
||||
}
|
||||
if (rc != TSS2_RC_SUCCESS)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to push PCR policy into TPM: %s", sym_Tss2_RC_Decode(rc));
|
||||
|
||||
_cleanup_(Esys_Freep) TPM2B_DIGEST *pcr_policy_digest = NULL;
|
||||
rc = sym_Esys_PolicyGetDigest(
|
||||
c.esys_context,
|
||||
session_handle,
|
||||
c->esys_context,
|
||||
session->esys_handle,
|
||||
ESYS_TR_NONE,
|
||||
ESYS_TR_NONE,
|
||||
ESYS_TR_NONE,
|
||||
&pcr_policy_digest);
|
||||
if (rc != TSS2_RC_SUCCESS) {
|
||||
r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
session_handle = tpm2_flush_context_verbose(c.esys_context, session_handle);
|
||||
if (rc != TSS2_RC_SUCCESS)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
|
||||
|
||||
_cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX* mdctx = NULL;
|
||||
mdctx = EVP_MD_CTX_new();
|
||||
if (!mdctx) {
|
||||
r = log_oom();
|
||||
goto finish;
|
||||
}
|
||||
if (!mdctx)
|
||||
return log_oom();
|
||||
|
||||
if (EVP_DigestSignInit(mdctx, NULL, p->md, NULL, privkey) != 1) {
|
||||
r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to initialize signature context.");
|
||||
goto finish;
|
||||
}
|
||||
if (EVP_DigestSignInit(mdctx, NULL, p->md, NULL, privkey) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to initialize signature context.");
|
||||
|
||||
if (EVP_DigestSignUpdate(mdctx, pcr_policy_digest->buffer, pcr_policy_digest->size) != 1) {
|
||||
r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to sign data.");
|
||||
goto finish;
|
||||
}
|
||||
if (EVP_DigestSignUpdate(mdctx, pcr_policy_digest->buffer, pcr_policy_digest->size) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to sign data.");
|
||||
|
||||
size_t ss;
|
||||
if (EVP_DigestSignFinal(mdctx, NULL, &ss) != 1) {
|
||||
r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to finalize signature");
|
||||
goto finish;
|
||||
}
|
||||
if (EVP_DigestSignFinal(mdctx, NULL, &ss) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to finalize signature");
|
||||
|
||||
_cleanup_free_ void *sig = malloc(ss);
|
||||
if (!sig) {
|
||||
r = log_oom();
|
||||
goto finish;
|
||||
}
|
||||
if (!sig)
|
||||
return log_oom();
|
||||
|
||||
if (EVP_DigestSignFinal(mdctx, sig, &ss) != 1) {
|
||||
r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to acquire signature data");
|
||||
goto finish;
|
||||
}
|
||||
if (EVP_DigestSignFinal(mdctx, sig, &ss) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to acquire signature data");
|
||||
|
||||
_cleanup_free_ void *pubkey_fp = NULL;
|
||||
size_t pubkey_fp_size = 0;
|
||||
r = pubkey_fingerprint(pubkey, EVP_sha256(), &pubkey_fp, &pubkey_fp_size);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
return r;
|
||||
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *a = NULL;
|
||||
r = tpm2_make_pcr_json_array(UINT64_C(1) << TPM_PCR_INDEX_KERNEL_IMAGE, &a);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to build JSON PCR mask array: %m");
|
||||
goto finish;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to build JSON PCR mask array: %m");
|
||||
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *bv = NULL;
|
||||
r = json_build(&bv, JSON_BUILD_OBJECT(
|
||||
@@ -951,25 +931,19 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
|
||||
JSON_BUILD_PAIR("pkfp", JSON_BUILD_HEX(pubkey_fp, pubkey_fp_size)), /* SHA256 fingerprint of public key (DER) used for the signature */
|
||||
JSON_BUILD_PAIR("pol", JSON_BUILD_HEX(pcr_policy_digest->buffer, pcr_policy_digest->size)), /* TPM2 policy hash that is signed */
|
||||
JSON_BUILD_PAIR("sig", JSON_BUILD_BASE64(sig, ss)))); /* signature data */
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to build JSON object: %m");
|
||||
goto finish;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to build JSON object: %m");
|
||||
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *av = NULL;
|
||||
av = json_variant_ref(json_variant_by_key(v, p->bank));
|
||||
|
||||
r = json_variant_append_array_nodup(&av, bv);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to append JSON object: %m");
|
||||
goto finish;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to append JSON object: %m");
|
||||
|
||||
r = json_variant_set_field(&v, p->bank, av);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to add JSON field: %m");
|
||||
goto finish;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add JSON field: %m");
|
||||
}
|
||||
|
||||
/* Return to the original kernel measurement for the next phase calculation */
|
||||
@@ -980,11 +954,8 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
|
||||
pager_open(arg_pager_flags);
|
||||
|
||||
json_variant_dump(v, arg_json_format_flags, stdout, NULL);
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
session_handle = tpm2_flush_context_verbose(c.esys_context, session_handle);
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compare_reported_pcr_nr(uint32_t pcr, const char *varname, const char *description) {
|
||||
|
||||
+6
-6
@@ -155,7 +155,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int determine_banks(struct tpm2_context *c, unsigned target_pcr_nr) {
|
||||
static int determine_banks(Tpm2Context *c, unsigned target_pcr_nr) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
int r;
|
||||
|
||||
@@ -164,7 +164,7 @@ static int determine_banks(struct tpm2_context *c, unsigned target_pcr_nr) {
|
||||
if (!strv_isempty(arg_banks)) /* Explicitly configured? Then use that */
|
||||
return 0;
|
||||
|
||||
r = tpm2_get_good_pcr_banks_strv(c->esys_context, UINT32_C(1) << target_pcr_nr, &l);
|
||||
r = tpm2_get_good_pcr_banks_strv(c, UINT32_C(1) << target_pcr_nr, &l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -240,7 +240,6 @@ static int get_file_system_word(
|
||||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(tpm2_context_destroy) struct tpm2_context c = {};
|
||||
_cleanup_free_ char *joined = NULL, *word = NULL;
|
||||
unsigned target_pcr_nr;
|
||||
size_t length;
|
||||
@@ -346,11 +345,12 @@ static int run(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to load TPM2 libraries: %m");
|
||||
|
||||
r = tpm2_context_init(arg_tpm2_device, &c);
|
||||
_cleanup_tpm2_context_ Tpm2Context *c = NULL;
|
||||
r = tpm2_context_new(arg_tpm2_device, &c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = determine_banks(&c, target_pcr_nr);
|
||||
r = determine_banks(c, target_pcr_nr);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (strv_isempty(arg_banks)) /* Still none? */
|
||||
@@ -362,7 +362,7 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
log_debug("Measuring '%s' into PCR index %u, banks %s.", word, target_pcr_nr, joined);
|
||||
|
||||
r = tpm2_extend_bytes(c.esys_context, arg_banks, target_pcr_nr, word, length, NULL, 0);
|
||||
r = tpm2_extend_bytes(c, arg_banks, target_pcr_nr, word, length, NULL, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -841,14 +841,14 @@ static int measure_volume_key(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to load TPM2 libraries: %m");
|
||||
|
||||
_cleanup_(tpm2_context_destroy) struct tpm2_context c = {};
|
||||
r = tpm2_context_init(arg_tpm2_device, &c);
|
||||
_cleanup_tpm2_context_ Tpm2Context *c = NULL;
|
||||
r = tpm2_context_new(arg_tpm2_device, &c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
if (strv_isempty(arg_tpm2_measure_banks)) {
|
||||
r = tpm2_get_good_pcr_banks_strv(c.esys_context, UINT32_C(1) << arg_tpm2_measure_pcr, &l);
|
||||
r = tpm2_get_good_pcr_banks_strv(c, UINT32_C(1) << arg_tpm2_measure_pcr, &l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@@ -871,7 +871,7 @@ static int measure_volume_key(
|
||||
if (!s)
|
||||
return log_oom();
|
||||
|
||||
r = tpm2_extend_bytes(c.esys_context, l ?: arg_tpm2_measure_banks, arg_tpm2_measure_pcr, s, SIZE_MAX, volume_key, volume_key_size);
|
||||
r = tpm2_extend_bytes(c, l ?: arg_tpm2_measure_banks, arg_tpm2_measure_pcr, s, SIZE_MAX, volume_key, volume_key_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
+244
-258
File diff suppressed because it is too large
Load Diff
+29
-12
@@ -53,13 +53,32 @@ int dlopen_tpm2(void);
|
||||
int tpm2_seal(const char *device, uint32_t hash_pcr_mask, const void *pubkey, size_t pubkey_size, uint32_t pubkey_pcr_mask, const char *pin, 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, uint16_t *ret_primary_alg);
|
||||
int tpm2_unseal(const char *device, uint32_t hash_pcr_mask, uint16_t pcr_bank, const void *pubkey, size_t pubkey_size, uint32_t pubkey_pcr_mask, JsonVariant *signature, const char *pin, uint16_t primary_alg, const void *blob, size_t blob_size, const void *policy_hash, size_t policy_hash_size, void **ret_secret, size_t *ret_secret_size);
|
||||
|
||||
struct tpm2_context {
|
||||
typedef struct {
|
||||
unsigned n_ref;
|
||||
|
||||
void *tcti_dl;
|
||||
TSS2_TCTI_CONTEXT *tcti_context;
|
||||
ESYS_CONTEXT *esys_context;
|
||||
};
|
||||
} Tpm2Context;
|
||||
|
||||
ESYS_TR tpm2_flush_context_verbose(ESYS_CONTEXT *c, ESYS_TR handle);
|
||||
int tpm2_context_new(const char *device, Tpm2Context **ret_context);
|
||||
Tpm2Context *tpm2_context_ref(Tpm2Context *context);
|
||||
Tpm2Context *tpm2_context_unref(Tpm2Context *context);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Tpm2Context*, tpm2_context_unref);
|
||||
#define _cleanup_tpm2_context_ _cleanup_(tpm2_context_unrefp)
|
||||
|
||||
typedef struct {
|
||||
Tpm2Context *tpm2_context;
|
||||
ESYS_TR esys_handle;
|
||||
} Tpm2Handle;
|
||||
|
||||
#define _tpm2_handle(c, h) { .tpm2_context = (c), .esys_handle = (h), }
|
||||
static const Tpm2Handle TPM2_HANDLE_NONE = _tpm2_handle(NULL, ESYS_TR_NONE);
|
||||
|
||||
int tpm2_handle_new(Tpm2Context *context, Tpm2Handle **ret_handle);
|
||||
Tpm2Handle *tpm2_handle_free(Tpm2Handle *handle);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Tpm2Handle*, tpm2_handle_free);
|
||||
#define _cleanup_tpm2_handle_ _cleanup_(tpm2_handle_freep)
|
||||
|
||||
void tpm2_pcr_mask_to_selection(uint32_t mask, uint16_t bank, TPML_PCR_SELECTION *ret);
|
||||
|
||||
@@ -68,17 +87,15 @@ static inline void Esys_Freep(void *p) {
|
||||
sym_Esys_Free(*(void**) p);
|
||||
}
|
||||
|
||||
int tpm2_get_good_pcr_banks(ESYS_CONTEXT *c, uint32_t pcr_mask, TPMI_ALG_HASH **ret_banks);
|
||||
int tpm2_get_good_pcr_banks_strv(ESYS_CONTEXT *c, uint32_t pcr_mask, char ***ret);
|
||||
int tpm2_get_good_pcr_banks(Tpm2Context *c, uint32_t pcr_mask, TPMI_ALG_HASH **ret_banks);
|
||||
int tpm2_get_good_pcr_banks_strv(Tpm2Context *c, uint32_t pcr_mask, char ***ret);
|
||||
|
||||
int tpm2_extend_bytes(ESYS_CONTEXT *c, char **banks, unsigned pcr_index, const void *data, size_t data_size, const void *secret, size_t secret_size);
|
||||
int tpm2_extend_bytes(Tpm2Context *c, char **banks, unsigned pcr_index, const void *data, size_t data_size, const void *secret, size_t secret_size);
|
||||
|
||||
#else
|
||||
struct tpm2_context;
|
||||
#endif
|
||||
|
||||
int tpm2_context_init(const char *device, struct tpm2_context *ret);
|
||||
void tpm2_context_destroy(struct tpm2_context *c);
|
||||
#else /* HAVE_TPM2 */
|
||||
typedef struct {} Tpm2Context;
|
||||
typedef struct {} Tpm2Handle;
|
||||
#endif /* HAVE_TPM2 */
|
||||
|
||||
int tpm2_list_devices(void);
|
||||
int tpm2_find_device_auto(int log_level, char **ret);
|
||||
|
||||
Reference in New Issue
Block a user