diff --git a/man/crypttab.xml b/man/crypttab.xml index 8f0ed5b77d..c048cd64c2 100644 --- a/man/crypttab.xml +++ b/man/crypttab.xml @@ -659,9 +659,9 @@ - Takes a comma separated list of numeric TPM2 PCR (i.e. "Platform Configuration - Register") indexes to bind the TPM2 volume unlocking to. This option is only useful when TPM2 - enrollment metadata is not available in the LUKS2 JSON token header already, the way + Takes a + separated list of numeric TPM2 PCR (i.e. "Platform + Configuration Register") indexes to bind the TPM2 volume unlocking to. This option is only useful + when TPM2 enrollment metadata is not available in the LUKS2 JSON token header already, the way systemd-cryptenroll writes it there. If not used (and no metadata in the LUKS2 JSON token header defines it), defaults to a list of a single entry: PCR 7. Assign an empty string to encode a policy that binds the key to no PCRs, making the key accessible to local programs regardless diff --git a/man/systemd-cryptenroll.xml b/man/systemd-cryptenroll.xml index c7f4e63f60..097cf7518b 100644 --- a/man/systemd-cryptenroll.xml +++ b/man/systemd-cryptenroll.xml @@ -176,11 +176,11 @@ PCR Configures the TPM2 PCRs (Platform Configuration Registers) to bind the enrollment - requested via to. Takes a comma separated list of numeric PCR indexes - in the range 0…23. If not used, defaults to PCR 7 only. If an empty string is specified, binds the - enrollment to no PCRs at all. PCRs allow binding the enrollment to specific software versions and - system state, so that the enrolled unlocking key is only accessible (may be "unsealed") if specific - trusted software and/or configuration is used. + requested via to. Takes a + separated list of + numeric PCR indexes in the range 0…23. If not used, defaults to PCR 7 only. If an empty string is + specified, binds the enrollment to no PCRs at all. PCRs allow binding the enrollment to specific + software versions and system state, so that the enrolled unlocking key is only accessible (may be + "unsealed") if specific trusted software and/or configuration is used. Well-known PCR Definitions diff --git a/src/cryptenroll/cryptenroll.c b/src/cryptenroll/cryptenroll.c index 559a346804..83b0b42ff2 100644 --- a/src/cryptenroll/cryptenroll.c +++ b/src/cryptenroll/cryptenroll.c @@ -97,7 +97,7 @@ static int help(void) { " Whether to require user verification to unlock the volume\n" " --tpm2-device=PATH\n" " Enroll a TPM2 device\n" - " --tpm2-pcrs=PCR1,PCR2,PCR3,…\n" + " --tpm2-pcrs=PCR1+PCR2+PCR3,…\n" " Specify TPM2 PCRs to seal against\n" " --wipe-slot=SLOT1,SLOT2,…\n" " Wipe specified slots\n" diff --git a/src/partition/repart.c b/src/partition/repart.c index 341cae33a6..877d2a091d 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -4070,7 +4070,7 @@ static int help(void) { " --definitions=DIR Find partition definitions in specified directory\n" " --key-file=PATH Key to use when encrypting partitions\n" " --tpm2-device=PATH Path to TPM2 device node to use\n" - " --tpm2-pcrs=PCR1,PCR2,…\n" + " --tpm2-pcrs=PCR1+PCR2+PCR3+…\n" " TPM2 PCR indexes to use for TPM2 enrollment\n" " --seed=UUID 128bit seed UUID to derive all UUIDs from\n" " --size=BYTES Grow loopback file to specified size\n" diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index 4d17f3c96a..b2540c62fe 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -920,13 +920,23 @@ int tpm2_parse_pcrs(const char *s, uint32_t *ret) { uint32_t mask = 0; int r; - /* Parses a comma-separated list of PCR indexes */ + assert(s); + + if (isempty(s)) { + *ret = 0; + return 0; + } + + /* Parses a "," or "+" separated list of PCR indexes. We support "," since this is a list after all, + * and most other tools expect comma separated PCR specifications. We also support "+" since in + * /etc/crypttab the "," is already used to separate options, hence a different separator is nice to + * avoid escaping. */ for (;;) { _cleanup_free_ char *pcr = NULL; unsigned n; - r = extract_first_word(&p, &pcr, ",", EXTRACT_DONT_COALESCE_SEPARATORS); + r = extract_first_word(&p, &pcr, ",+", EXTRACT_DONT_COALESCE_SEPARATORS); if (r == 0) break; if (r < 0) diff --git a/src/test/meson.build b/src/test/meson.build index e02eaf78ff..c7b2bbfedc 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -422,6 +422,8 @@ tests += [ [['src/test/test-sleep.c']], + [['src/test/test-tpm2.c']], + [['src/test/test-replace-var.c']], [['src/test/test-calendarspec.c']], diff --git a/src/test/test-tpm2.c b/src/test/test-tpm2.c new file mode 100644 index 0000000000..a1fd0aa03b --- /dev/null +++ b/src/test/test-tpm2.c @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "tpm2-util.h" +#include "tests.h" + +static void test_tpm2_parse_pcrs(const char *s, uint32_t mask, int ret) { + uint32_t m; + + assert_se(tpm2_parse_pcrs(s, &m) == ret); + + if (ret >= 0) + assert_se(m == mask); +} + +int main(int argc, char *argv[]) { + + test_setup_logging(LOG_DEBUG); + + test_tpm2_parse_pcrs("", 0, 0); + test_tpm2_parse_pcrs("0", 1, 0); + test_tpm2_parse_pcrs("1", 2, 0); + test_tpm2_parse_pcrs("0,1", 3, 0); + test_tpm2_parse_pcrs("0+1", 3, 0); + test_tpm2_parse_pcrs("0-1", 0, -EINVAL); + test_tpm2_parse_pcrs("0,1,2", 7, 0); + test_tpm2_parse_pcrs("0+1+2", 7, 0); + test_tpm2_parse_pcrs("0+1,2", 7, 0); + test_tpm2_parse_pcrs("0,1+2", 7, 0); + test_tpm2_parse_pcrs("0,2", 5, 0); + test_tpm2_parse_pcrs("0+2", 5, 0); + test_tpm2_parse_pcrs("foo", 0, -EINVAL); + + return 0; +}