Merge pull request #26180 from ddstreet/tpm2_cleanup

Add struct tpm2_handle and use _cleanup_ instead of goto
This commit is contained in:
Luca Boccassi
2023-02-01 23:40:52 +00:00
committed by GitHub
5 changed files with 333 additions and 359 deletions
+50 -79
View File
@@ -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
View File
@@ -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;
+4 -4
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+29 -12
View File
@@ -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);