diff options
author | Lennart Poettering <lennart@poettering.net> | 2022-09-22 16:19:58 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2022-09-22 16:55:56 +0200 |
commit | a434e25f52dea1af4f256794102003fd002be34b (patch) | |
tree | ba924bab634723f2ccfa955a462f970a458b4cb5 | |
parent | measure: allow pre-calculating PCR values for multiple boot phases (diff) | |
download | systemd-a434e25f52dea1af4f256794102003fd002be34b.tar.xz systemd-a434e25f52dea1af4f256794102003fd002be34b.zip |
measure: make --public-key= optional if "sign" is called
We can derive the public key from the private key, so let's do that, to
make things a bit easier.
-rw-r--r-- | man/systemd-measure.xml | 5 | ||||
-rw-r--r-- | src/boot/measure.c | 41 |
2 files changed, 35 insertions, 11 deletions
diff --git a/man/systemd-measure.xml b/man/systemd-measure.xml index 4e37d000e2..459ed6592f 100644 --- a/man/systemd-measure.xml +++ b/man/systemd-measure.xml @@ -143,7 +143,10 @@ unified kernel image, the latter picks the public key of the key pair used to sign the resulting PCR 11 values. The former is the key that the booted system will likely use to lock disk and credential encryption to, the latter is the key used for unlocking such resources again. Hence, typically the - same PEM key should be supplied in both cases.</para></listitem> + same PEM key should be supplied in both cases.</para> + + <para>If the <option>--public-key=</option> is not specified but <option>--private-key=</option> is + specified the public key is automatically derived from the private key.</para></listitem> </varlistentry> <varlistentry> diff --git a/src/boot/measure.c b/src/boot/measure.c index fd83cd8ba5..05100cf541 100644 --- a/src/boot/measure.c +++ b/src/boot/measure.c @@ -708,7 +708,7 @@ static int verb_sign(int argc, char *argv[], void *userdata) { _cleanup_(pcr_state_free_all) PcrState *pcr_states = NULL; _cleanup_(EVP_PKEY_freep) EVP_PKEY *privkey = NULL, *pubkey = NULL; _cleanup_(tpm2_context_destroy) struct tpm2_context c = {}; - _cleanup_fclose_ FILE *privkeyf = NULL , *pubkeyf = NULL; + _cleanup_fclose_ FILE *privkeyf = NULL; ESYS_TR session_handle = ESYS_TR_NONE; TSS2_RC rc; size_t n; @@ -719,8 +719,6 @@ static int verb_sign(int argc, char *argv[], void *userdata) { if (!arg_private_key) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No private key specified, use --private-key=."); - if (!arg_public_key) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No public key specified, use --public-key=."); /* When signing we only support JSON output */ arg_json_format_flags &= ~JSON_FORMAT_OFF; @@ -729,17 +727,40 @@ static int verb_sign(int argc, char *argv[], void *userdata) { if (!privkeyf) return log_error_errno(errno, "Failed to open private key file '%s': %m", arg_private_key); - pubkeyf = fopen(arg_public_key, "re"); - if (!pubkeyf) - return log_error_errno(errno, "Failed to open public key file '%s': %m", arg_public_key); - privkey = PEM_read_PrivateKey(privkeyf, NULL, NULL, NULL); if (!privkey) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse private key '%s'.", arg_private_key); - pubkey = PEM_read_PUBKEY(pubkeyf, NULL, NULL, NULL); - if (!pubkey) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse public key '%s'.", arg_public_key); + if (arg_public_key) { + _cleanup_fclose_ FILE *pubkeyf = NULL; + + pubkeyf = fopen(arg_public_key, "re"); + if (!pubkeyf) + return log_error_errno(errno, "Failed to open public key file '%s': %m", arg_public_key); + + pubkey = PEM_read_PUBKEY(pubkeyf, NULL, NULL, NULL); + if (!pubkey) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse public key '%s'.", arg_public_key); + } else { + _cleanup_free_ char *data = NULL; + _cleanup_fclose_ FILE *tf = NULL; + size_t sz; + + /* No public key was specified, let's derive it automatically, if we can */ + + tf = open_memstream_unlocked(&data, &sz); + if (!tf) + return log_oom(); + + if (i2d_PUBKEY_fp(tf, privkey) != 1) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to extract public key from private key file '%s'.", arg_private_key); + + fflush(tf); + rewind(tf); + + if (!d2i_PUBKEY_fp(tf, &pubkey)) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse extracted public key of private key file '%s'.", arg_private_key); + } r = pcr_states_allocate(&pcr_states); if (r < 0) |