mirror of
https://github.com/systemd/systemd.git
synced 2026-08-09 09:32:04 +00:00
pcrextend: add secret parameter to varlink interface
Add an optional 'secret' input to io.systemd.PCRExtend.Extend. When set,
the HMAC of the measured data keyed by the secret is extended instead of
a plain hash, matching the existing tpm2_{pcr,nvpcr}_extend_bytes()
secret parameter. This lets callers measure a secret (e.g. a volume key)
without leaking a hash of it.
Signed-off-by: Paul Meyer <katexochen0@gmail.com>
This commit is contained in:
@@ -302,6 +302,7 @@ static int tpm2_context_new_for_measurement(Tpm2Context **ret) {
|
||||
static int extend_pcr_now(
|
||||
uint32_t pcr_mask,
|
||||
const struct iovec *data,
|
||||
const struct iovec *secret,
|
||||
Tpm2UserspaceEventType event) {
|
||||
|
||||
_cleanup_(tpm2_context_unrefp) Tpm2Context *c = NULL;
|
||||
@@ -331,7 +332,7 @@ static int extend_pcr_now(
|
||||
BIT_FOREACH(pcr, pcr_mask) {
|
||||
log_debug("Measuring '%s' into PCR index %i, banks %s.", safe, pcr, joined_banks);
|
||||
|
||||
r = tpm2_pcr_extend_bytes(c, arg_banks, pcr, data, /* secret= */ NULL, event, safe);
|
||||
r = tpm2_pcr_extend_bytes(c, arg_banks, pcr, data, secret, event, safe);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not extend PCR: %m");
|
||||
|
||||
@@ -349,6 +350,7 @@ static int extend_pcr_now(
|
||||
static int extend_nvpcr_now(
|
||||
const char *name,
|
||||
const struct iovec *data,
|
||||
const struct iovec *secret,
|
||||
Tpm2UserspaceEventType event) {
|
||||
|
||||
_cleanup_(tpm2_context_unrefp) Tpm2Context *c = NULL;
|
||||
@@ -371,7 +373,7 @@ static int extend_nvpcr_now(
|
||||
/* session= */ NULL,
|
||||
name,
|
||||
data,
|
||||
/* secret= */ NULL,
|
||||
secret,
|
||||
event,
|
||||
safe);
|
||||
if (r == -ENOBUFS)
|
||||
@@ -393,6 +395,7 @@ typedef struct MethodExtendParameters {
|
||||
const char *nvpcr;
|
||||
const char *text;
|
||||
struct iovec data;
|
||||
struct iovec secret;
|
||||
Tpm2UserspaceEventType event_type;
|
||||
} MethodExtendParameters;
|
||||
|
||||
@@ -400,6 +403,7 @@ static void method_extend_parameters_done(MethodExtendParameters *p) {
|
||||
assert(p);
|
||||
|
||||
iovec_done(&p->data);
|
||||
iovec_done_erase(&p->secret);
|
||||
}
|
||||
|
||||
static JSON_DISPATCH_ENUM_DEFINE(json_dispatch_tpm2_userspace_event_type, Tpm2UserspaceEventType, tpm2_userspace_event_type_from_string);
|
||||
@@ -407,10 +411,11 @@ static JSON_DISPATCH_ENUM_DEFINE(json_dispatch_tpm2_userspace_event_type, Tpm2Us
|
||||
static int vl_method_extend(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||
|
||||
static const sd_json_dispatch_field dispatch_table[] = {
|
||||
{ "pcr", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint, offsetof(MethodExtendParameters, pcr), 0 },
|
||||
{ "nvpcr", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(MethodExtendParameters, nvpcr), 0 },
|
||||
{ "text", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(MethodExtendParameters, text), 0 },
|
||||
{ "data", SD_JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(MethodExtendParameters, data), 0 },
|
||||
{ "pcr", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint, offsetof(MethodExtendParameters, pcr), 0 },
|
||||
{ "nvpcr", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(MethodExtendParameters, nvpcr), 0 },
|
||||
{ "text", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(MethodExtendParameters, text), 0 },
|
||||
{ "data", SD_JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(MethodExtendParameters, data), 0 },
|
||||
{ "secret", SD_JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(MethodExtendParameters, secret), 0 },
|
||||
{ "eventType", SD_JSON_VARIANT_STRING, json_dispatch_tpm2_userspace_event_type, offsetof(MethodExtendParameters, event_type), 0 },
|
||||
{}
|
||||
};
|
||||
@@ -456,13 +461,13 @@ static int vl_method_extend(sd_varlink *link, sd_json_variant *parameters, sd_va
|
||||
return sd_varlink_error_invalid_parameter_name(link, p.text ? "text" : "data");
|
||||
|
||||
if (p.nvpcr) {
|
||||
r = extend_nvpcr_now(p.nvpcr, extend_iovec, p.event_type);
|
||||
r = extend_nvpcr_now(p.nvpcr, extend_iovec, &p.secret, p.event_type);
|
||||
if (IN_SET(r, -ENOENT, -ENODEV))
|
||||
return sd_varlink_error(link, "io.systemd.PCRExtend.NoSuchNvPCR", NULL);
|
||||
if (r == -ENOBUFS)
|
||||
return sd_varlink_error(link, "io.systemd.PCRExtend.NvPCRSpaceExhausted", NULL);
|
||||
} else
|
||||
r = extend_pcr_now(INDEX_TO_MASK(uint32_t, p.pcr), extend_iovec, p.event_type);
|
||||
r = extend_pcr_now(INDEX_TO_MASK(uint32_t, p.pcr), extend_iovec, &p.secret, p.event_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -474,7 +479,7 @@ static int vl_server(void) {
|
||||
int r;
|
||||
|
||||
r = varlink_server_new(&varlink_server,
|
||||
SD_VARLINK_SERVER_ROOT_ONLY | SD_VARLINK_SERVER_MYSELF_ONLY,
|
||||
SD_VARLINK_SERVER_ROOT_ONLY | SD_VARLINK_SERVER_MYSELF_ONLY | SD_VARLINK_SERVER_INPUT_SENSITIVE,
|
||||
/* userdata= */ NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate Varlink server: %m");
|
||||
@@ -593,9 +598,9 @@ static int run(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
if (arg_nvpcr_name)
|
||||
r = extend_nvpcr_now(arg_nvpcr_name, &IOVEC_MAKE(word, strlen(word)), event);
|
||||
r = extend_nvpcr_now(arg_nvpcr_name, &IOVEC_MAKE(word, strlen(word)), NULL, event);
|
||||
else
|
||||
r = extend_pcr_now(arg_pcr_mask, &IOVEC_MAKE(word, strlen(word)), event);
|
||||
r = extend_pcr_now(arg_pcr_mask, &IOVEC_MAKE(word, strlen(word)), NULL, event);
|
||||
/* Both extend paths report "TPM cannot be used for this measurement" (no PCR bank, missing crypto,
|
||||
* no TPM device — see tpm2_context_new_for_measurement()) as -EOPNOTSUPP. Under --graceful we skip
|
||||
* those rather than fail and block boot. Genuine faults keep their own errno and are never
|
||||
|
||||
@@ -25,6 +25,8 @@ static SD_VARLINK_DEFINE_METHOD(
|
||||
SD_VARLINK_DEFINE_INPUT(text, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Binary data to measure, encoded in Base64. (Specify either this, or the 'text' field above, not both)"),
|
||||
SD_VARLINK_DEFINE_INPUT(data, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("HMAC key, encoded in Base64. When set, the HMAC of the measured data keyed by this secret is extended rather than a plain hash."),
|
||||
SD_VARLINK_DEFINE_INPUT(secret, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Event type to include in the (userspace) event log). This is optional, and mostly for debugging."),
|
||||
SD_VARLINK_DEFINE_INPUT_BY_TYPE(eventType, EventType, SD_VARLINK_NULLABLE));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user