1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

creds-tool: expose new signed PCR policies in creds tool, too

This commit is contained in:
Lennart Poettering 2022-08-17 17:28:49 +02:00
parent 6a0779cbf9
commit 75ddec9301
2 changed files with 104 additions and 23 deletions

View File

@ -333,6 +333,40 @@
<citerefentry><refentrytitle>systemd-cryptenroll</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--tpm2-public-key=</option><arg>PATH</arg></term>
<term><option>--tpm2-public-key-pcrs=</option><arg rep="repeat">PCR</arg></term>
<listitem><para>Configures a TPM2 signed PCR policy to bind encryption to, for use with the
<command>encrypt</command> command. The <option>--tpm2-public-key=</option> option accepts a path to
a PEM encoded RSA public key, to bind the encryption to. If this is not specified explicitly, but a
file <filename>tpm2-pcr-public-key.pem</filename> exists in one of the directories
<filename>/etc/systemd/</filename>, <filename>/run/systemd/</filename>,
<filename>/usr/lib/systemd/</filename> (searched in this order), it is automatically used. The
<option>--tpm2-public-key-pcrs=</option> option takes a list of TPM2 PCR indexes to bind to (same
syntax as <option>--tpm2-pcrs=</option> described above). If not specified defaults to 11 (i.e. this
binds the policy to any unified kernel image for which a PCR signature can be provided).</para>
<para>Note the difference between <option>--tpm2-pcrs=</option> and
<option>--tpm2-public-key-pcrs=</option>: the former binds decryption to the current, specific PCR
values; the latter binds decryption to any set of PCR values for which a signature by the specified
public key can be provided. The latter is hence more useful in scenarios where software updates shall
be possible without losing access to all previously encrypted secrets.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--tpm2-signature=</option><arg>PATH</arg></term>
<listitem><para>Takes a path to a TPM2 PCR signature file as generated by the
<citerefentry><refentrytitle>systemd-measure</refentrytitle><manvolnum>1</manvolnum></citerefentry>
tool and that may be used to allow the <command>decrypt</command> command to decrypt credentials that
are bound to specific signed PCR values. If this this is not specified explicitly, and a credential
with a signed PCR policy is attempted to be decrypted, a suitable signature file
<filename>tpm2-pcr-signature.json</filename> is searched for in <filename>/etc/systemd/</filename>,
<filename>/run/systemd/</filename>, <filename>/usr/lib/systemd/</filename> (in this order) and
used.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--quiet</option></term>
<term><option>-q</option></term>
@ -413,7 +447,8 @@ SetCredentialEncrypted=mysql-password: \
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-measure</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>

View File

@ -21,6 +21,7 @@
#include "stat-util.h"
#include "string-table.h"
#include "terminal-util.h"
#include "tpm-pcr.h"
#include "tpm2-util.h"
#include "verbs.h"
@ -43,6 +44,9 @@ static int arg_newline = -1;
static sd_id128_t arg_with_key = _CRED_AUTO;
static const char *arg_tpm2_device = NULL;
static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
static char *arg_tpm2_public_key = NULL;
static uint32_t arg_tpm2_public_key_pcr_mask = UINT32_MAX;
static char *arg_tpm2_signature = NULL;
static const char *arg_name = NULL;
static bool arg_name_any = false;
static usec_t arg_timestamp = USEC_INFINITY;
@ -50,6 +54,9 @@ static usec_t arg_not_after = USEC_INFINITY;
static bool arg_pretty = false;
static bool arg_quiet = false;
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_public_key, freep);
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_signature, freep);
static const char* transcode_mode_table[_TRANSCODE_MAX] = {
[TRANSCODE_OFF] = "off",
[TRANSCODE_BASE64] = "base64",
@ -418,7 +425,7 @@ static int verb_cat(int argc, char **argv, void *userdata) {
*cn,
timestamp,
arg_tpm2_device,
/* tpm2_signature_path= */ NULL,
arg_tpm2_signature,
data, size,
&plaintext, &plaintext_size);
if (r < 0)
@ -491,8 +498,8 @@ static int verb_encrypt(int argc, char **argv, void *userdata) {
arg_not_after,
arg_tpm2_device,
arg_tpm2_pcr_mask,
/* tpm2_pubkey_path= */ NULL,
/* tpm2_pubkey_pcr_mask= */ 0,
arg_tpm2_public_key,
arg_tpm2_public_key_pcr_mask,
plaintext, plaintext_size,
&output, &output_size);
if (r < 0)
@ -580,7 +587,7 @@ static int verb_decrypt(int argc, char **argv, void *userdata) {
name,
timestamp,
arg_tpm2_device,
/* tpm2_signature_path= */ NULL,
arg_tpm2_signature,
input, input_size,
&plaintext, &plaintext_size);
if (r < 0)
@ -686,7 +693,13 @@ static int verb_help(int argc, char **argv, void *userdata) {
" --tpm2-device=PATH\n"
" Pick TPM2 device\n"
" --tpm2-pcrs=PCR1+PCR2+PCR3+…\n"
" Specify TPM2 PCRs to seal against\n"
" Specify TPM2 PCRs to seal against (fixed hash)\n"
" --tpm2-public-key=PATH\n"
" Specify PEM certificate to seal against\n"
" --tpm2-public-key-pcrs=PCR1+PCR2+PCR3+…\n"
" Specify TPM2 PCRs to seal against (public key)\n"
" --tpm2-signature=PATH\n"
" Specify signature for public key PCR policy\n"
" -q --quiet Suppress output for 'has-tpm2' verb\n"
"\nSee the %2$s for details.\n"
, program_invocation_short_name
@ -711,28 +724,34 @@ static int parse_argv(int argc, char *argv[]) {
ARG_WITH_KEY,
ARG_TPM2_DEVICE,
ARG_TPM2_PCRS,
ARG_TPM2_PUBLIC_KEY,
ARG_TPM2_PUBLIC_KEY_PCRS,
ARG_TPM2_SIGNATURE,
ARG_NAME,
ARG_TIMESTAMP,
ARG_NOT_AFTER,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
{ "json", required_argument, NULL, ARG_JSON },
{ "system", no_argument, NULL, ARG_SYSTEM },
{ "transcode", required_argument, NULL, ARG_TRANSCODE },
{ "newline", required_argument, NULL, ARG_NEWLINE },
{ "pretty", no_argument, NULL, 'p' },
{ "with-key", required_argument, NULL, ARG_WITH_KEY },
{ "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE },
{ "tpm2-pcrs", required_argument, NULL, ARG_TPM2_PCRS },
{ "name", required_argument, NULL, ARG_NAME },
{ "timestamp", required_argument, NULL, ARG_TIMESTAMP },
{ "not-after", required_argument, NULL, ARG_NOT_AFTER },
{ "quiet", no_argument, NULL, 'q' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
{ "json", required_argument, NULL, ARG_JSON },
{ "system", no_argument, NULL, ARG_SYSTEM },
{ "transcode", required_argument, NULL, ARG_TRANSCODE },
{ "newline", required_argument, NULL, ARG_NEWLINE },
{ "pretty", no_argument, NULL, 'p' },
{ "with-key", required_argument, NULL, ARG_WITH_KEY },
{ "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE },
{ "tpm2-pcrs", required_argument, NULL, ARG_TPM2_PCRS },
{ "tpm2-public-key", required_argument, NULL, ARG_TPM2_PUBLIC_KEY },
{ "tpm2-public-key-pcrs", required_argument, NULL, ARG_TPM2_PUBLIC_KEY_PCRS },
{ "tpm2-signature", required_argument, NULL, ARG_TPM2_SIGNATURE },
{ "name", required_argument, NULL, ARG_NAME },
{ "timestamp", required_argument, NULL, ARG_TIMESTAMP },
{ "not-after", required_argument, NULL, ARG_NOT_AFTER },
{ "quiet", no_argument, NULL, 'q' },
{}
};
@ -812,8 +831,12 @@ static int parse_argv(int argc, char *argv[]) {
arg_with_key = CRED_AES256_GCM_BY_HOST;
else if (streq(optarg, "tpm2"))
arg_with_key = CRED_AES256_GCM_BY_TPM2_HMAC;
else if (streq(optarg, "tpm2-with-public-key"))
arg_with_key = CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK;
else if (STR_IN_SET(optarg, "host+tpm2", "tpm2+host"))
arg_with_key = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC;
else if (STR_IN_SET(optarg, "host+tpm2-with-public-key", "tpm2-with-public-key+host"))
arg_with_key = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK;
else if (streq(optarg, "tpm2-absent"))
arg_with_key = CRED_AES256_GCM_BY_TPM2_ABSENT;
else
@ -836,13 +859,34 @@ static int parse_argv(int argc, char *argv[]) {
arg_tpm2_device = streq(optarg, "auto") ? NULL : optarg;
break;
case ARG_TPM2_PCRS:
case ARG_TPM2_PCRS: /* For fixed hash PCR policies only */
r = tpm2_parse_pcr_argument(optarg, &arg_tpm2_pcr_mask);
if (r < 0)
return r;
break;
case ARG_TPM2_PUBLIC_KEY:
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_public_key);
if (r < 0)
return r;
break;
case ARG_TPM2_PUBLIC_KEY_PCRS: /* For public key PCR policies only */
r = tpm2_parse_pcr_argument(optarg, &arg_tpm2_public_key_pcr_mask);
if (r < 0)
return r;
break;
case ARG_TPM2_SIGNATURE:
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_signature);
if (r < 0)
return r;
break;
case ARG_NAME:
if (isempty(optarg)) {
arg_name = NULL;
@ -885,6 +929,8 @@ static int parse_argv(int argc, char *argv[]) {
if (arg_tpm2_pcr_mask == UINT32_MAX)
arg_tpm2_pcr_mask = TPM2_PCR_MASK_DEFAULT;
if (arg_tpm2_public_key_pcr_mask == UINT32_MAX)
arg_tpm2_public_key_pcr_mask = UINT32_C(1) << TPM_PCR_INDEX_KERNEL_IMAGE;
return 1;
}