]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
measure: make --public-key= optional if "sign" is called
authorLennart Poettering <lennart@poettering.net>
Thu, 22 Sep 2022 14:19:58 +0000 (16:19 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 22 Sep 2022 14:55:56 +0000 (16:55 +0200)
We can derive the public key from the private key, so let's do that, to
make things a bit easier.

man/systemd-measure.xml
src/boot/measure.c

index 4e37d000e200a764f3abf4ebbb1e43fbe2445474..459ed6592fc24faf806c489ac72c9e75446985dd 100644 (file)
         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>
index fd83cd8ba505652b396d3dbb14c58b54ac24110a..05100cf54130c130c44ee8afa7447b2f1a8362d0 100644 (file)
@@ -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)