imds: add TPM measurements to imds tool
This automatically measures the IMDS 'userdata' into PCR 12, i.e. where we measure the other owner-supplied configuration, such as confexts and credentials and similar. (Why 12? It's really about who owns the data and what it is for. PCRs/NvPCRs are scarce hence there's a strong incentive to not go overboard with new allocations, and IMDS userdata in purpose and owner is very very similar to confexts and credentials, hence let's reuse the PCR for this purpose.)
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
#include "log.h"
|
||||
#include "main-func.h"
|
||||
#include "parse-argument.h"
|
||||
#include "pcrextend-util.h"
|
||||
#include "pretty-print.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
@@ -822,6 +823,9 @@ static int action_import(sd_varlink *link) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Measure the userdata before we use it */
|
||||
(void) pcrextend_imds_userdata_now(&data);
|
||||
|
||||
/* Keep a pristine copy of the userdata we actually applied. (Note that this data is typically also
|
||||
* kept as cached item on systemd-imdsd, but that one is possibly subject to cache invalidation,
|
||||
* while this one is supposed to pin the data actually in effect.) */
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
#include "mountpoint-util.h"
|
||||
#include "pcrextend-util.h"
|
||||
#include "pkcs7-util.h"
|
||||
#include "sha256.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "tpm2-pcr.h"
|
||||
|
||||
static int device_get_file_system_word(
|
||||
sd_device *d,
|
||||
@@ -291,3 +293,70 @@ int pcrextend_verity_now(
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support disabled, not measuring Verity root hashes and signatures.");
|
||||
#endif
|
||||
}
|
||||
|
||||
#define IMDS_USERDATA_TRUNCATED_MAX 256U
|
||||
|
||||
int pcrextend_imds_userdata_word(const struct iovec *data, char **ret) {
|
||||
assert(iovec_is_set(data));
|
||||
assert(ret);
|
||||
|
||||
/* We include both a hash of the complete user data, and a truncated version of the data in the word
|
||||
* we measure. The former protects the actual data, the latter is useful for debugging. */
|
||||
|
||||
_cleanup_free_ char *hash = hexmem(SHA256_DIRECT(data->iov_base, data->iov_len), SHA256_DIGEST_SIZE);
|
||||
if (!hash)
|
||||
return log_oom();
|
||||
|
||||
_cleanup_free_ char *data_encoded = NULL;
|
||||
if (base64mem_full(data->iov_base, MIN(data->iov_len, IMDS_USERDATA_TRUNCATED_MAX), /* line_break= */ SIZE_MAX, &data_encoded) < 0)
|
||||
return log_oom();
|
||||
|
||||
_cleanup_free_ char *word = strjoin("imds-userdata:", hash, ":", data_encoded);
|
||||
if (!word)
|
||||
return log_oom();
|
||||
|
||||
*ret = TAKE_PTR(word);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcrextend_imds_userdata_now(const struct iovec *data) {
|
||||
|
||||
#if HAVE_TPM2
|
||||
int r;
|
||||
|
||||
_cleanup_free_ char *word = NULL;
|
||||
r = pcrextend_imds_userdata_word(data, &word);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL;
|
||||
r = sd_varlink_connect_address(&vl, "/run/systemd/io.systemd.PCRExtend");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *reply = NULL;
|
||||
const char *error_id = NULL;
|
||||
r = sd_varlink_callbo(
|
||||
vl,
|
||||
"io.systemd.PCRExtend.Extend",
|
||||
/* ret_reply= */ NULL,
|
||||
&error_id,
|
||||
SD_JSON_BUILD_PAIR_INTEGER("pcr", TPM2_PCR_KERNEL_CONFIG),
|
||||
SD_JSON_BUILD_PAIR_STRING("text", word),
|
||||
SD_JSON_BUILD_PAIR_STRING("eventType", "imds_userdata"));
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to issue io.systemd.PCRExtend.Extend() varlink call: %m");
|
||||
if (error_id) {
|
||||
r = sd_varlink_error_to_errno(error_id, reply);
|
||||
if (r != -EBADR)
|
||||
return log_debug_errno(r, "Failed to issue io.systemd.PCRExtend.Extend() varlink call: %m");
|
||||
|
||||
return log_debug_errno(r, "Failed to issue io.systemd.PCRExtend.Extend() varlink call: %s", error_id);
|
||||
}
|
||||
|
||||
log_debug("Measurement of '%s' into PCR 12 completed.", word);
|
||||
return 1;
|
||||
#else
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support disabled, not measuring IMDS userdata.");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <sys/uio.h>
|
||||
|
||||
int pcrextend_file_system_word(const char *path, char **ret, char **ret_normalized_path);
|
||||
int pcrextend_machine_id_word(char **ret);
|
||||
int pcrextend_product_id_word(char **ret);
|
||||
int pcrextend_verity_word(const char *name, const struct iovec *root_hash, const struct iovec *root_hash_sig, char **ret);
|
||||
int pcrextend_imds_userdata_word(const struct iovec *data, char **ret);
|
||||
|
||||
int pcrextend_verity_now(const char *name, const struct iovec *root_hash,const struct iovec *root_hash_sig);
|
||||
int pcrextend_verity_now(const char *name, const struct iovec *root_hash, const struct iovec *root_hash_sig);
|
||||
int pcrextend_imds_userdata_now(const struct iovec *data);
|
||||
|
||||
@@ -6675,6 +6675,7 @@ static const char* tpm2_userspace_event_type_table[_TPM2_USERSPACE_EVENT_TYPE_MA
|
||||
[TPM2_EVENT_NVPCR_INIT] = "nvpcr-init",
|
||||
[TPM2_EVENT_NVPCR_SEPARATOR] = "nvpcr-separator",
|
||||
[TPM2_EVENT_DM_VERITY] = "dm-verity",
|
||||
[TPM2_EVENT_IMDS_USERDATA] = "imds-userdata",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(tpm2_userspace_event_type, Tpm2UserspaceEventType);
|
||||
|
||||
@@ -148,6 +148,7 @@ typedef enum Tpm2UserspaceEventType {
|
||||
TPM2_EVENT_NVPCR_INIT,
|
||||
TPM2_EVENT_NVPCR_SEPARATOR,
|
||||
TPM2_EVENT_DM_VERITY,
|
||||
TPM2_EVENT_IMDS_USERDATA,
|
||||
_TPM2_USERSPACE_EVENT_TYPE_MAX,
|
||||
_TPM2_USERSPACE_EVENT_TYPE_INVALID = -EINVAL,
|
||||
} Tpm2UserspaceEventType;
|
||||
|
||||
@@ -12,7 +12,8 @@ static SD_VARLINK_DEFINE_ENUM_TYPE(
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(keyslot),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(nvpcr_init),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(nvpcr_separator),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(dm_verity));
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(dm_verity),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(imds_userdata));
|
||||
|
||||
static SD_VARLINK_DEFINE_METHOD(
|
||||
Extend,
|
||||
|
||||
Reference in New Issue
Block a user