1
0
mirror of https://github.com/systemd/systemd synced 2026-04-23 07:24:51 +02:00

Compare commits

..

No commits in common. "da29de23ef200b17bb780e5a0efb6cff28c72287" and "06fb09cf40e75b04e75ea502ddeee96ca29269fc" have entirely different histories.

15 changed files with 100 additions and 265 deletions

13
NEWS
View File

@ -120,19 +120,6 @@ CHANGES WITH 251:
250. For newer kernels, non-x86 systems, or older x86 systems,
there should be no visible changes.
* sd-boot will now measure the kernel command line into TPM PCR 12
rather than PCR 8. This improves usefulness of the measurements on
sytems where sd-boot is chainloaded from Grub. Grub measures all
commands its executes into PCR 8, which makes it very hard to use
reasonably, hence separate ourselves from that and use PCR 12
instead, which is already what certain Ubuntu editions use it for. To
retain compatibility with systems running older systemd systems a new
Meson option 'efi-tpm-pcr-compat' has been added (which defaults to
false). If enabled, the measurement is done twice: into the new-style
PCR 12 *and* the old-style PCR 8. It's strongly advised to migrate
all users to PCR 12 for this purpose in the long run, as we intend to
remove this compatibility feature again in two year's time.
CHANGES WITH 250:
* Support for encrypted and authenticated credentials has been added.

View File

@ -253,13 +253,6 @@ So, if you want to do your own raw cgroups kernel level access, then allocate a
scope unit, or a service unit (or just use the service unit you already have
for your service code), and turn on delegation for it.
The service manager sets the `user.delegate` extended attribute (readable via
`getxattr(2)` and related calls) to the character `1` on cgroup directories
where delegation is enabled (and removes it on those cgroups where it is
not). This may be used by service programs to determine whether a cgroup tree
was delegated to them. Note that this is only supported on kernels 5.6 and
newer in combination with systemd 251 and newer.
(OK, here's one caveat: if you turn on delegation for a service, and that
service has `ExecStartPost=`, `ExecReload=`, `ExecStop=` or `ExecStopPost=`
set, then these commands will be executed within the `.control/` sub-cgroup of

View File

@ -214,8 +214,6 @@
<!-- See: https://github.com/rhboot/shim/blob/main/README.tpm -->
<!-- See: https://www.gnu.org/software/grub/manual/grub/html_node/Measured-Boot.html -->
<!-- See: https://sourceforge.net/p/linux-ima/wiki/Home/ -->
<!-- See: https://github.com/tianocore-docs/edk2-TrustedBootChain/blob/main/4_Other_Trusted_Boot_Chains.md -->
<!-- See: https://wiki.archlinux.org/title/Trusted_Platform_Module#Accessing_PCR_registers -->
<tgroup cols='2' align='left' colsep='1' rowsep='1'>
<colspec colname="pcr" />
@ -269,14 +267,14 @@
<entry>Secure boot state; changes when UEFI SecureBoot mode is enabled/disabled, or firmware certificates (PK, KEK, db, dbx, …) changes. The shim project will measure most of its (non-MOK) certificates and SBAT data into this PCR.</entry>
</row>
<!-- Grub measures all its commands and the kernel command line into PCR 8… -->
<!-- Grub measures all files it reads (including kernel image, initrd, …) into PCR 9… -->
<row>
<entry>12</entry>
<entry>8</entry>
<entry><citerefentry><refentrytitle>sd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures the kernel command line into this PCR.</entry>
<!-- Grub measures all its commands and the kernel command line into PCR 8 too… -->
</row>
<!-- Grub measures all files it reads (including kernel image, initrd, …) into PCR 9… -->
<row>
<entry>10</entry>
<entry>The IMA project measures its runtime state into this PCR.</entry>

View File

@ -426,8 +426,6 @@ option('efi-libdir', type : 'string',
description : 'path to the EFI lib directory')
option('efi-includedir', type : 'string', value : '/usr/include/efi',
description : 'path to the EFI header directory')
option('efi-tpm-pcr-compat', type : 'boolean', value : 'false',
description : 'Measure kernel command line also into TPM PCR 8 (in addition to 12)')
option('sbat-distro', type : 'string', value : 'auto',
description : 'SBAT distribution ID, e.g. fedora, or auto for autodetection')
option('sbat-distro-generation', type : 'integer', value : 1,

View File

@ -311,8 +311,7 @@ EFI_STATUS pack_cpio(
const CHAR8 *target_dir_prefix,
UINT32 dir_mode,
UINT32 access_mode,
const UINT32 tpm_pcr[],
UINTN n_tpm_pcr,
UINTN tpm_pcr,
const CHAR16 *tpm_description,
void **ret_buffer,
UINTN *ret_buffer_size) {
@ -329,7 +328,6 @@ EFI_STATUS pack_cpio(
assert(loaded_image);
assert(target_dir_prefix);
assert(tpm_pcr || n_tpm_pcr == 0);
assert(ret_buffer);
assert(ret_buffer_size);
@ -451,15 +449,13 @@ EFI_STATUS pack_cpio(
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Failed to pack cpio trailer: %r");
for (UINTN i = 0; i < n_tpm_pcr; i++) {
err = tpm_log_event(
tpm_pcr[i],
POINTER_TO_PHYSICAL_ADDRESS(buffer),
buffer_size,
tpm_description);
if (EFI_ERROR(err))
log_error_stall(L"Unable to add initrd TPM measurement for PCR %u (%s), ignoring: %r", tpm_pcr[i], tpm_description, err);
}
err = tpm_log_event(
tpm_pcr,
POINTER_TO_PHYSICAL_ADDRESS(buffer),
buffer_size,
tpm_description);
if (EFI_ERROR(err))
log_error_stall(L"Unable to add initrd TPM measurement for PCR %u (%s), ignoring: %r", tpm_pcr, tpm_description, err);
*ret_buffer = TAKE_PTR(buffer);
*ret_buffer_size = buffer_size;

View File

@ -10,8 +10,8 @@ EFI_STATUS pack_cpio(
const CHAR8 *target_dir_prefix,
UINT32 dir_mode,
UINT32 access_mode,
const UINT32 tpm_pcr[],
UINTN n_tpm_pcr,
UINTN tpm_pcr,
const CHAR16 *tpm_description,
void **ret_buffer,
UINTN *ret_buffer_size);

View File

@ -139,16 +139,12 @@ BOOLEAN tpm_present(void) {
return tcg2_interface_check() || tcg1_interface_check();
}
EFI_STATUS tpm_log_event(UINT32 pcrindex, EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const CHAR16 *description) {
EFI_STATUS tpm_log_event(UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const CHAR16 *description) {
EFI_TCG *tpm1;
EFI_TCG2 *tpm2;
assert(description);
/* PCR disabled */
if (pcrindex == UINT32_MAX)
return EFI_SUCCESS;
tpm2 = tcg2_interface_check();
if (tpm2)
return tpm2_measure_to_pcr_and_event_log(tpm2, pcrindex, buffer, buffer_size, description);
@ -166,15 +162,11 @@ EFI_STATUS tpm_log_load_options(const CHAR16 *load_options) {
/* Measures a load options string into the TPM2, i.e. the kernel command line */
for (UINTN i = 0; i < 2; i++) {
UINT32 pcr = i == 0 ? TPM_PCR_INDEX_KERNEL_PARAMETERS : TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT;
err = tpm_log_event(pcr,
POINTER_TO_PHYSICAL_ADDRESS(load_options),
StrSize(load_options), load_options);
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Unable to add load options (i.e. kernel command) line measurement to PCR %u: %r", pcr, err);
}
err = tpm_log_event(TPM_PCR_INDEX_KERNEL_PARAMETERS,
POINTER_TO_PHYSICAL_ADDRESS(load_options),
StrSize(load_options), load_options);
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Unable to add load options (i.e. kernel command) line measurement: %r", err);
return EFI_SUCCESS;
}

View File

@ -3,24 +3,10 @@
#include <efi.h>
/* This TPM PCR is where we extend the kernel command line and any passed credentials here. */
#define TPM_PCR_INDEX_KERNEL_PARAMETERS 12U
/* We used to write the the kernel command line/credentials into PCR 8, in systemd <= 250. Let's provide for
* some compatibility. (Remove in 2023!) */
#if EFI_TPM_PCR_COMPAT
#define TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT 8U
#else
#define TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT UINT32_MAX
#endif
/* This TPM PCR is where most Linux infrastructure extends the initrd binary images into, and so do we. */
#define TPM_PCR_INDEX_INITRD 4U
#if ENABLE_TPM
BOOLEAN tpm_present(void);
EFI_STATUS tpm_log_event(UINT32 pcrindex, EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const CHAR16 *description);
EFI_STATUS tpm_log_event(UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const CHAR16 *description);
EFI_STATUS tpm_log_load_options(const CHAR16 *cmdline);
#else
@ -28,11 +14,9 @@ EFI_STATUS tpm_log_load_options(const CHAR16 *cmdline);
static inline BOOLEAN tpm_present(void) {
return FALSE;
}
static inline EFI_STATUS tpm_log_event(UINT32 pcrindex, EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const CHAR16 *description) {
static inline EFI_STATUS tpm_log_event(UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const CHAR16 *description) {
return EFI_SUCCESS;
}
static inline EFI_STATUS tpm_log_load_options(const CHAR16 *cmdline) {
return EFI_SUCCESS;
}

View File

@ -104,7 +104,6 @@ conf.set_quoted('EFI_MACHINE_TYPE_NAME', efi_arch[0])
efi_conf = configuration_data()
efi_conf.set_quoted('EFI_MACHINE_TYPE_NAME', efi_arch[0])
efi_conf.set10('ENABLE_TPM', get_option('tpm'))
efi_conf.set10('EFI_TPM_PCR_COMPAT', get_option('efi-tpm-pcr-compat'))
foreach ctype : ['color-normal', 'color-entry', 'color-highlight', 'color-edit']
c = get_option('efi-' + ctype).split(',')

View File

@ -234,8 +234,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
(const CHAR8*) ".extra/credentials",
/* dir_mode= */ 0500,
/* access_mode= */ 0400,
/* tpm_pcr= */ (UINT32[]) { TPM_PCR_INDEX_KERNEL_PARAMETERS, TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT },
/* n_tpm_pcr= */ 2,
/* tpm_pcr= */ TPM_PCR_INDEX_KERNEL_PARAMETERS,
L"Credentials initrd",
&credential_initrd,
&credential_initrd_size);
@ -246,8 +245,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
(const CHAR8*) ".extra/global_credentials",
/* dir_mode= */ 0500,
/* access_mode= */ 0400,
/* tpm_pcr= */ (UINT32[]) { TPM_PCR_INDEX_KERNEL_PARAMETERS, TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT },
/* n_tpm_pcr= */ 2,
/* tpm_pcr= */ TPM_PCR_INDEX_KERNEL_PARAMETERS,
L"Global credentials initrd",
&global_credential_initrd,
&global_credential_initrd_size);
@ -258,8 +256,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
(const CHAR8*) ".extra/sysext",
/* dir_mode= */ 0555,
/* access_mode= */ 0444,
/* tpm_pcr= */ (UINT32[]) { TPM_PCR_INDEX_INITRD },
/* n_tpm_pcr= */ 1,
/* tpm_pcr= */ TPM_PCR_INDEX_INITRD,
L"System extension initrd",
&sysext_initrd,
&sysext_initrd_size);

View File

@ -6,6 +6,13 @@
#include "string-util-fundamental.h"
/* This TPM PCR is where most Linux infrastructure extends the kernel command line into, and so do we. We also extend
* any passed credentials here. */
#define TPM_PCR_INDEX_KERNEL_PARAMETERS 8
/* This TPM PCR is where most Linux infrastructure extends the initrd binary images into, and so do we. */
#define TPM_PCR_INDEX_INITRD 4
#define offsetof(type, member) __builtin_offsetof(type, member)
#define UINTN_MAX (~(UINTN)0)

View File

@ -736,44 +736,9 @@ int cgroup_add_bpf_foreign_program(CGroupContext *c, uint32_t attach_type, const
UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(memory_low);
UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(memory_min);
static void unit_set_xattr_graceful(Unit *u, const char *cgroup_path, const char *name, const void *data, size_t size) {
int r;
assert(u);
assert(name);
if (!cgroup_path) {
if (!u->cgroup_path)
return;
cgroup_path = u->cgroup_path;
}
r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, name, data, size, 0);
if (r < 0)
log_unit_debug_errno(u, r, "Failed to set '%s' xattr on control group %s, ignoring: %m", name, empty_to_root(cgroup_path));
}
static void unit_remove_xattr_graceful(Unit *u, const char *cgroup_path, const char *name) {
int r;
assert(u);
assert(name);
if (!cgroup_path) {
if (!u->cgroup_path)
return;
cgroup_path = u->cgroup_path;
}
r = cg_remove_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, name);
if (r < 0 && r != -ENODATA)
log_unit_debug_errno(u, r, "Failed to remove '%s' xattr flag on control group %s, ignoring: %m", name, empty_to_root(cgroup_path));
}
void cgroup_oomd_xattr_apply(Unit *u, const char *cgroup_path) {
CGroupContext *c;
int r;
assert(u);
@ -781,50 +746,59 @@ void cgroup_oomd_xattr_apply(Unit *u, const char *cgroup_path) {
if (!c)
return;
if (c->moom_preference == MANAGED_OOM_PREFERENCE_OMIT)
unit_set_xattr_graceful(u, cgroup_path, "user.oomd_omit", "1", 1);
if (c->moom_preference == MANAGED_OOM_PREFERENCE_OMIT) {
r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, "user.oomd_omit", "1", 1, 0);
if (r < 0)
log_unit_debug_errno(u, r, "Failed to set oomd_omit flag on control group %s, ignoring: %m", empty_to_root(cgroup_path));
}
if (c->moom_preference == MANAGED_OOM_PREFERENCE_AVOID)
unit_set_xattr_graceful(u, cgroup_path, "user.oomd_avoid", "1", 1);
if (c->moom_preference == MANAGED_OOM_PREFERENCE_AVOID) {
r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, "user.oomd_avoid", "1", 1, 0);
if (r < 0)
log_unit_debug_errno(u, r, "Failed to set oomd_avoid flag on control group %s, ignoring: %m", empty_to_root(cgroup_path));
}
if (c->moom_preference != MANAGED_OOM_PREFERENCE_AVOID)
unit_remove_xattr_graceful(u, cgroup_path, "user.oomd_avoid");
if (c->moom_preference != MANAGED_OOM_PREFERENCE_AVOID) {
r = cg_remove_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, "user.oomd_avoid");
if (r < 0 && r != -ENODATA)
log_unit_debug_errno(u, r, "Failed to remove oomd_avoid flag on control group %s, ignoring: %m", empty_to_root(cgroup_path));
}
if (c->moom_preference != MANAGED_OOM_PREFERENCE_OMIT)
unit_remove_xattr_graceful(u, cgroup_path, "user.oomd_omit");
if (c->moom_preference != MANAGED_OOM_PREFERENCE_OMIT) {
r = cg_remove_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, "user.oomd_omit");
if (r < 0 && r != -ENODATA)
log_unit_debug_errno(u, r, "Failed to remove oomd_omit flag on control group %s, ignoring: %m", empty_to_root(cgroup_path));
}
}
static void cgroup_xattr_apply(Unit *u) {
const char *xn;
bool b;
int r;
assert(u);
if (!MANAGER_IS_SYSTEM(u->manager))
return;
b = !sd_id128_is_null(u->invocation_id);
FOREACH_STRING(xn, "trusted.invocation_id", "user.invocation_id") {
if (b)
unit_set_xattr_graceful(u, NULL, xn, SD_ID128_TO_STRING(u->invocation_id), 32);
else
unit_remove_xattr_graceful(u, NULL, xn);
if (!sd_id128_is_null(u->invocation_id)) {
r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path,
"trusted.invocation_id",
SD_ID128_TO_STRING(u->invocation_id), 32,
0);
if (r < 0)
log_unit_debug_errno(u, r, "Failed to set invocation ID on control group %s, ignoring: %m", empty_to_root(u->cgroup_path));
}
/* Indicate on the cgroup whether delegation is on, via an xattr. This is best-effort, as old kernels
* didn't support xattrs on cgroups at all. Later they got support for setting 'trusted.*' xattrs,
* and even later 'user.*' xattrs. We started setting this field when 'trusted.*' was added, and
* given this is now pretty much API, let's continue to support that. But also set 'user.*' as well,
* since it is readable by any user, not just CAP_SYS_ADMIN. This hence comes with slightly weaker
* security (as users who got delegated cgroups could turn it off if they like), but this shouldn't
* be a big problem given this communicates delegation state to clients, but the manager never reads
* it. */
b = unit_cgroup_delegate(u);
FOREACH_STRING(xn, "trusted.delegate", "user.delegate") {
if (b)
unit_set_xattr_graceful(u, NULL, xn, "1", 1);
else
unit_remove_xattr_graceful(u, NULL, xn);
if (unit_cgroup_delegate(u)) {
r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path,
"trusted.delegate",
"1", 1,
0);
if (r < 0)
log_unit_debug_errno(u, r, "Failed to set delegate flag on control group %s, ignoring: %m", empty_to_root(u->cgroup_path));
} else {
r = cg_remove_xattr(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "trusted.delegate");
if (r < 0 && r != -ENODATA)
log_unit_debug_errno(u, r, "Failed to remove delegate flag on control group %s, ignoring: %m", empty_to_root(u->cgroup_path));
}
cgroup_oomd_xattr_apply(u, u->cgroup_path);

View File

@ -128,31 +128,6 @@ static int show_cgroup_one_by_path(
return 0;
}
static int is_delegated(int cgfd, const char *path) {
_cleanup_free_ char *b = NULL;
int r;
assert(cgfd >= 0 || path);
r = getxattr_malloc(cgfd < 0 ? path : FORMAT_PROC_FD_PATH(cgfd), "trusted.delegate", &b);
if (r == -ENODATA) {
/* If the trusted xattr isn't set (preferred), then check the untrusted one. Under the
* assumption that whoever is trusted enough to own the cgroup, is also trusted enough to
* decide if it is delegated or not this should be safe. */
r = getxattr_malloc(cgfd < 0 ? path : FORMAT_PROC_FD_PATH(cgfd), "user.delegate", &b);
if (r == -ENODATA)
return false;
}
if (r < 0)
return log_debug_errno(r, "Failed to read delegate xattr, ignoring: %m");
r = parse_boolean(b);
if (r < 0)
return log_debug_errno(r, "Failed to parse delegate xattr boolean value, ignoring: %m");
return r;
}
static int show_cgroup_name(
const char *path,
const char *prefix,
@ -162,7 +137,7 @@ static int show_cgroup_name(
uint64_t cgroupid = UINT64_MAX;
_cleanup_free_ char *b = NULL;
_cleanup_close_ int fd = -1;
bool delegate;
bool delegate = false;
int r;
if (FLAGS_SET(flags, OUTPUT_CGROUP_XATTRS) || FLAGS_SET(flags, OUTPUT_CGROUP_ID)) {
@ -171,7 +146,19 @@ static int show_cgroup_name(
log_debug_errno(errno, "Failed to open cgroup '%s', ignoring: %m", path);
}
delegate = is_delegated(fd, path) > 0;
r = getxattr_malloc(fd < 0 ? path : FORMAT_PROC_FD_PATH(fd), "trusted.delegate", &b);
if (r < 0) {
if (r != -ENODATA)
log_debug_errno(r, "Failed to read trusted.delegate extended attribute, ignoring: %m");
} else {
r = parse_boolean(b);
if (r < 0)
log_debug_errno(r, "Failed to parse trusted.delegate extended attribute boolean value, ignoring: %m");
else
delegate = r > 0;
b = mfree(b);
}
if (FLAGS_SET(flags, OUTPUT_CGROUP_ID)) {
cg_file_handle fh = CG_FILE_HANDLE_INIT;

View File

@ -36,7 +36,6 @@ TSS2_RC (*sym_Esys_PolicyGetDigest)(ESYS_CONTEXT *esysContext, ESYS_TR policySes
TSS2_RC (*sym_Esys_PolicyPCR)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *pcrDigest, const TPML_PCR_SELECTION *pcrs) = NULL;
TSS2_RC (*sym_Esys_StartAuthSession)(ESYS_CONTEXT *esysContext, ESYS_TR tpmKey, ESYS_TR bind, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_NONCE *nonceCaller, TPM2_SE sessionType, const TPMT_SYM_DEF *symmetric, TPMI_ALG_HASH authHash, ESYS_TR *sessionHandle) = NULL;
TSS2_RC (*sym_Esys_Startup)(ESYS_CONTEXT *esysContext, TPM2_SU startupType) = NULL;
TSS2_RC (*sym_Esys_TRSess_SetAttributes)(ESYS_CONTEXT *esysContext, ESYS_TR session, TPMA_SESSION flags, TPMA_SESSION mask);
TSS2_RC (*sym_Esys_TR_SetAuth)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_AUTH const *authValue) = NULL;
TSS2_RC (*sym_Esys_Unseal)(ESYS_CONTEXT *esysContext, ESYS_TR itemHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_SENSITIVE_DATA **outData) = NULL;
@ -67,7 +66,6 @@ int dlopen_tpm2(void) {
DLSYM_ARG(Esys_PolicyPCR),
DLSYM_ARG(Esys_StartAuthSession),
DLSYM_ARG(Esys_Startup),
DLSYM_ARG(Esys_TRSess_SetAttributes),
DLSYM_ARG(Esys_TR_SetAuth),
DLSYM_ARG(Esys_Unseal));
if (r < 0)
@ -597,71 +595,8 @@ static int tpm2_get_best_pcr_bank(
return 0;
}
static int tpm2_make_encryption_session(
ESYS_CONTEXT *c,
ESYS_TR tpmKey,
ESYS_TR *ret_session) {
static const TPMT_SYM_DEF symmetric = {
.algorithm = TPM2_ALG_AES,
.keyBits = {
.aes = 128,
},
.mode = {
.aes = TPM2_ALG_CFB,
},
};
const TPMA_SESSION sessionAttributes = TPMA_SESSION_DECRYPT | TPMA_SESSION_ENCRYPT |
TPMA_SESSION_CONTINUESESSION;
ESYS_TR session = ESYS_TR_NONE;
TSS2_RC rc;
assert(c);
log_debug("Starting HMAC encryption session.");
/* Start a salted, unbound HMAC session with a well-known key (e.g. primary key) as tpmKey, which
* means that the random salt will be encrypted with the well-known key. That way, only the TPM can
* recover the salt, which is then used for key derivation. */
rc = sym_Esys_StartAuthSession(
c,
tpmKey,
ESYS_TR_NONE,
ESYS_TR_NONE,
ESYS_TR_NONE,
ESYS_TR_NONE,
NULL,
TPM2_SE_HMAC,
&symmetric,
TPM2_ALG_SHA256,
&session);
if (rc != TSS2_RC_SUCCESS)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
/* Enable parameter encryption/decryption with AES in CFB mode. Together with HMAC digests (which are
* always used for sessions), this provides confidentiality, integrity and replay protection for
* operations that use this session. */
rc = sym_Esys_TRSess_SetAttributes(c, session, sessionAttributes, 0xff);
if (rc != TSS2_RC_SUCCESS)
return log_error_errno(
SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Failed to configure TPM session: %s",
sym_Tss2_RC_Decode(rc));
if (ret_session) {
*ret_session = session;
session = ESYS_TR_NONE;
}
session = flush_context_verbose(c, session);
return 0;
}
static int tpm2_make_pcr_session(
ESYS_CONTEXT *c,
ESYS_TR tpmKey,
ESYS_TR parent_session,
uint32_t pcr_mask,
uint16_t pcr_bank, /* If UINT16_MAX, pick best bank automatically, otherwise specify bank explicitly. */
bool use_pin,
@ -710,9 +645,9 @@ static int tpm2_make_pcr_session(
rc = sym_Esys_StartAuthSession(
c,
tpmKey,
ESYS_TR_NONE,
parent_session,
ESYS_TR_NONE,
ESYS_TR_NONE,
ESYS_TR_NONE,
ESYS_TR_NONE,
NULL,
@ -836,7 +771,7 @@ int tpm2_seal(
_cleanup_(erase_and_freep) void *secret = NULL;
_cleanup_free_ void *blob = NULL, *hash = NULL;
TPM2B_SENSITIVE_CREATE hmac_sensitive;
ESYS_TR primary = ESYS_TR_NONE, session = ESYS_TR_NONE;
ESYS_TR primary = ESYS_TR_NONE;
TPMI_ALG_PUBLIC primary_alg;
TPM2B_PUBLIC hmac_template;
TPMI_ALG_HASH pcr_bank;
@ -881,12 +816,8 @@ int tpm2_seal(
if (r < 0)
return r;
r = tpm2_make_encryption_session(c.esys_context, primary, &session);
if (r < 0)
goto finish;
r = tpm2_make_pcr_session(c.esys_context, primary, session, pcr_mask, UINT16_MAX, !!pin, NULL,
&policy_digest, &pcr_bank);
r = tpm2_make_pcr_session(c.esys_context, pcr_mask, UINT16_MAX, !!pin, NULL, &policy_digest,
&pcr_bank);
if (r < 0)
goto finish;
@ -938,7 +869,7 @@ int tpm2_seal(
rc = sym_Esys_Create(
c.esys_context,
primary,
session, /* use HMAC session to enable parameter encryption */
ESYS_TR_PASSWORD,
ESYS_TR_NONE,
ESYS_TR_NONE,
&hmac_sensitive,
@ -1020,7 +951,6 @@ int tpm2_seal(
finish:
explicit_bzero_safe(&hmac_sensitive, sizeof(hmac_sensitive));
primary = flush_context_verbose(c.esys_context, primary);
session = flush_context_verbose(c.esys_context, session);
return r;
}
@ -1038,8 +968,7 @@ int tpm2_unseal(
size_t *ret_secret_size) {
_cleanup_(tpm2_context_destroy) struct tpm2_context c = {};
ESYS_TR primary = ESYS_TR_NONE, session = ESYS_TR_NONE, hmac_session = ESYS_TR_NONE,
hmac_key = ESYS_TR_NONE;
ESYS_TR primary = ESYS_TR_NONE, session = ESYS_TR_NONE, hmac_key = ESYS_TR_NONE;
_cleanup_(Esys_Freep) TPM2B_SENSITIVE_DATA* unsealed = NULL;
_cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
_cleanup_(erase_and_freep) char *secret = NULL;
@ -1090,16 +1019,7 @@ int tpm2_unseal(
if (r < 0)
return r;
r = tpm2_make_primary(c.esys_context, &primary, primary_alg, NULL);
if (r < 0)
return r;
r = tpm2_make_encryption_session(c.esys_context, primary, &hmac_session);
if (r < 0)
goto finish;
r = tpm2_make_pcr_session(c.esys_context, primary, hmac_session, pcr_mask, pcr_bank, !!pin, &session,
&policy_digest, NULL);
r = tpm2_make_pcr_session(c.esys_context, pcr_mask, pcr_bank, !!pin, &session, &policy_digest, NULL);
if (r < 0)
goto finish;
@ -1110,12 +1030,16 @@ int tpm2_unseal(
return log_error_errno(SYNTHETIC_ERRNO(EPERM),
"Current policy digest does not match stored policy digest, cancelling TPM2 authentication attempt.");
r = tpm2_make_primary(c.esys_context, &primary, primary_alg, NULL);
if (r < 0)
return r;
log_debug("Loading HMAC key into TPM.");
rc = sym_Esys_Load(
c.esys_context,
primary,
hmac_session, /* use HMAC session to enable parameter encryption */
ESYS_TR_PASSWORD,
ESYS_TR_NONE,
ESYS_TR_NONE,
&private,
@ -1160,7 +1084,7 @@ int tpm2_unseal(
c.esys_context,
hmac_key,
session,
hmac_session, /* use HMAC session to enable parameter encryption */
ESYS_TR_NONE,
ESYS_TR_NONE,
&unsealed);
if (rc != TSS2_RC_SUCCESS) {

View File

@ -31,7 +31,6 @@ extern TSS2_RC (*sym_Esys_PolicyGetDigest)(ESYS_CONTEXT *esysContext, ESYS_TR po
extern TSS2_RC (*sym_Esys_PolicyPCR)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *pcrDigest, const TPML_PCR_SELECTION *pcrs);
extern TSS2_RC (*sym_Esys_StartAuthSession)(ESYS_CONTEXT *esysContext, ESYS_TR tpmKey, ESYS_TR bind, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_NONCE *nonceCaller, TPM2_SE sessionType, const TPMT_SYM_DEF *symmetric, TPMI_ALG_HASH authHash, ESYS_TR *sessionHandle);
extern TSS2_RC (*sym_Esys_Startup)(ESYS_CONTEXT *esysContext, TPM2_SU startupType);
extern TSS2_RC (*sym_Esys_TRSess_SetAttributes)(ESYS_CONTEXT *esysContext, ESYS_TR session, TPMA_SESSION flags, TPMA_SESSION mask);
extern TSS2_RC (*sym_Esys_TR_SetAuth)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_AUTH const *authValue);
extern TSS2_RC (*sym_Esys_Unseal)(ESYS_CONTEXT *esysContext, ESYS_TR itemHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_SENSITIVE_DATA **outData);