summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--man/rules/meson.build1
-rw-r--r--man/systemd-keyutil.xml105
-rw-r--r--man/systemd-measure.xml10
-rw-r--r--man/systemd-sbsign.xml16
-rw-r--r--meson.build3
-rw-r--r--src/keyutil/keyutil.c292
-rw-r--r--src/keyutil/meson.build12
-rw-r--r--src/measure/measure.c89
-rw-r--r--src/sbsign/sbsign.c54
-rwxr-xr-xsrc/ukify/ukify.py12
-rwxr-xr-xtest/units/TEST-74-AUX-UTILS.keyutil.sh50
-rwxr-xr-xtest/units/TEST-74-AUX-UTILS.sbsign.sh4
12 files changed, 468 insertions, 180 deletions
diff --git a/man/rules/meson.build b/man/rules/meson.build
index 7d2c62f574..e76cb0223b 100644
--- a/man/rules/meson.build
+++ b/man/rules/meson.build
@@ -992,6 +992,7 @@ manpages = [
'systemd-journald@.service',
'systemd-journald@.socket'],
''],
+ ['systemd-keyutil', '1', [], ''],
['systemd-localed.service', '8', ['systemd-localed'], 'ENABLE_LOCALED'],
['systemd-logind.service', '8', ['systemd-logind'], 'ENABLE_LOGIND'],
['systemd-machine-id-commit.service', '8', [], ''],
diff --git a/man/systemd-keyutil.xml b/man/systemd-keyutil.xml
new file mode 100644
index 0000000000..99d4d903b4
--- /dev/null
+++ b/man/systemd-keyutil.xml
@@ -0,0 +1,105 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+ "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
+
+<refentry id="systemd-keyutil"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <refentryinfo>
+ <title>systemd-keyutil</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd-keyutil</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd-keyutil</refname>
+ <refpurpose>Perform various operations on private keys and X.509 certificates</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>systemd-keyutil</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="req">COMMAND</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><command>systemd-keyutil</command> can be used to perform various operations on private keys and
+ X.509 certificates.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Commands</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>validate</option></term>
+
+ <listitem><para>Checks that we can load the private key and certificate specified with
+ <option>--private-key=</option> and <option>--certificate=</option> respectively.</para>
+
+ <para>As a side effect, if the private key is loaded from a PIN-protected hardware token, this
+ command can be used to cache the PIN in the kernel keyring. The
+ <varname>$SYSTEMD_ASK_PASSWORD_KEYRING_TIMEOUT_SEC</varname> and
+ <varname>$SYSTEMD_ASK_PASSWORD_KEYRING_TYPE</varname> environment variables can be used to control
+ how long and in which kernel keyring the PIN is cached.</para>
+
+ <xi:include href="version-info.xml" xpointer="v257"/>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>public</command></term>
+
+ <listitem><para>This commands prints the public key in PEM format extracted from either the
+ certificate given with <option>--certificate=</option> or the private key given with
+ <option>--private-key=</option>.</para>
+
+ <xi:include href="version-info.xml" xpointer="v257"/></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Options</title>
+ <para>The following options are understood:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>--private-key=<replaceable>PATH/URI</replaceable></option></term>
+ <term><option>--private-key-source=<replaceable>TYPE</replaceable>[:<replaceable>NAME</replaceable>]</option></term>
+ <term><option>--certificate=<replaceable>PATH</replaceable></option></term>
+ <term><option>--certificate-source=<replaceable>TYPE</replaceable>[:<replaceable>NAME</replaceable>]</option></term>
+
+ <listitem><para>Set the private key and certificate to use. The <option>--certificate=</option>
+ option takes a path to a PEM encoded X.509 certificate or a URI that's passed to the OpenSSL provider
+ configured with <option>--certificate-source</option>. The <option>--certificate-source</option>
+ takes one of <literal>file</literal> or <literal>provider</literal>, with the latter being followed
+ by a specific provider identifier, separated with a colon, e.g. <literal>provider:pkcs11</literal>.
+ The <option>--private-key=</option> option can take a path or a URI that will be passed to the
+ OpenSSL engine or provider, as specified by <option>--private-key-source=</option> as a
+ <literal>type:name</literal> tuple, such as <literal>engine:pkcs11</literal></para>.
+
+ <xi:include href="version-info.xml" xpointer="v257"/></listitem>
+ </varlistentry>
+
+ <xi:include href="standard-options.xml" xpointer="help"/>
+ <xi:include href="standard-options.xml" xpointer="version"/>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para><simplelist type="inline">
+ <member><citerefentry><refentrytitle>systemd-sbsign</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
+ <member><citerefentry><refentrytitle>systemd-measure</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
+ </simplelist></para>
+ </refsect1>
+</refentry>
diff --git a/man/systemd-measure.xml b/man/systemd-measure.xml
index 5ca373f181..c7e5a5e9e2 100644
--- a/man/systemd-measure.xml
+++ b/man/systemd-measure.xml
@@ -104,16 +104,6 @@
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
</varlistentry>
-
- <varlistentry>
- <term><command>pcrpkey</command></term>
-
- <listitem><para>This commands prints the public key either given with <option>--public-key=</option>,
- or extracted from the certificate given with <option>--certificate=</option> or the private key given
- with <option>--private-key=</option>.</para>
-
- <xi:include href="version-info.xml" xpointer="v257"/></listitem>
- </varlistentry>
</variablelist>
</refsect1>
diff --git a/man/systemd-sbsign.xml b/man/systemd-sbsign.xml
index 1248377845..57b685f8c3 100644
--- a/man/systemd-sbsign.xml
+++ b/man/systemd-sbsign.xml
@@ -49,22 +49,6 @@
<xi:include href="version-info.xml" xpointer="v257"/>
</listitem>
</varlistentry>
-
- <varlistentry>
- <term><option>validate-key</option></term>
-
- <listitem><para>Checks that we can load the private key specified with
- <option>--private-key=</option>. </para>
-
- <para>As a side effect, if the private key is loaded from a PIN-protected hardware token, this
- command can be used to cache the PIN in the kernel keyring. The
- <varname>$SYSTEMD_ASK_PASSWORD_KEYRING_TIMEOUT_SEC</varname> and
- <varname>$SYSTEMD_ASK_PASSWORD_KEYRING_TYPE</varname> environment variables can be used to control
- how long and in which kernel keyring the PIN is cached.</para>
-
- <xi:include href="version-info.xml" xpointer="v257"/>
- </listitem>
- </varlistentry>
</variablelist>
</refsect1>
diff --git a/meson.build b/meson.build
index 6b62dfa052..fbab9300c5 100644
--- a/meson.build
+++ b/meson.build
@@ -2377,6 +2377,7 @@ subdir('src/integritysetup')
subdir('src/journal')
subdir('src/journal-remote')
subdir('src/kernel-install')
+subdir('src/keyutil')
subdir('src/locale')
subdir('src/login')
subdir('src/machine')
@@ -2698,7 +2699,7 @@ endif
mkosi_depends = public_programs
-foreach executable : ['systemd-journal-remote', 'systemd-measure']
+foreach executable : ['systemd-journal-remote', 'systemd-measure', 'systemd-sbsign', 'systemd-keyutil']
if executable in executables_by_name
mkosi_depends += [executables_by_name[executable]]
endif
diff --git a/src/keyutil/keyutil.c b/src/keyutil/keyutil.c
new file mode 100644
index 0000000000..70176c76c7
--- /dev/null
+++ b/src/keyutil/keyutil.c
@@ -0,0 +1,292 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <getopt.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "ask-password-api.h"
+#include "build.h"
+#include "fd-util.h"
+#include "main-func.h"
+#include "memstream-util.h"
+#include "openssl-util.h"
+#include "parse-argument.h"
+#include "pretty-print.h"
+#include "verbs.h"
+
+static char *arg_private_key = NULL;
+static KeySourceType arg_private_key_source_type = OPENSSL_KEY_SOURCE_FILE;
+static char *arg_private_key_source = NULL;
+static char *arg_certificate = NULL;
+static char *arg_certificate_source = NULL;
+static CertificateSourceType arg_certificate_source_type = OPENSSL_CERTIFICATE_SOURCE_FILE;
+
+STATIC_DESTRUCTOR_REGISTER(arg_private_key, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_private_key_source, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_certificate, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_certificate_source, freep);
+
+static int help(int argc, char *argv[], void *userdata) {
+ _cleanup_free_ char *link = NULL;
+ int r;
+
+ r = terminal_urlify_man("systemd-keyutil", "1", &link);
+ if (r < 0)
+ return log_oom();
+
+ printf("%1$s [OPTIONS...] COMMAND ...\n"
+ "\n%5$sPerform various operations on private keys and certificates.%6$s\n"
+ "\n%3$sCommands:%4$s\n"
+ " validate Load and validate the given certificate and private key\n"
+ " public Extract a public key\n"
+ "\n%3$sOptions:%4$s\n"
+ " -h --help Show this help\n"
+ " --version Print version\n"
+ " --private-key=KEY Private key in PEM format\n"
+ " --private-key-source=file|provider:PROVIDER|engine:ENGINE\n"
+ " Specify how to use KEY for --private-key=. Allows\n"
+ " an OpenSSL engine/provider to be used for signing\n"
+ " --certificate=PATH|URI\n"
+ " PEM certificate to use for signing, or a provider\n"
+ " specific designation if --certificate-source= is used\n"
+ " --certificate-source=file|provider:PROVIDER\n"
+ " Specify how to interpret the certificate from\n"
+ " --certificate=. Allows the certificate to be loaded\n"
+ " from an OpenSSL provider\n"
+ "\nSee the %2$s for details.\n",
+ program_invocation_short_name,
+ link,
+ ansi_underline(),
+ ansi_normal(),
+ ansi_highlight(),
+ ansi_normal());
+
+ return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+ enum {
+ ARG_VERSION = 0x100,
+ ARG_PRIVATE_KEY,
+ ARG_PRIVATE_KEY_SOURCE,
+ ARG_CERTIFICATE,
+ ARG_CERTIFICATE_SOURCE,
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "private-key", required_argument, NULL, ARG_PRIVATE_KEY },
+ { "private-key-source", required_argument, NULL, ARG_PRIVATE_KEY_SOURCE },
+ { "certificate", required_argument, NULL, ARG_CERTIFICATE },
+ { "certificate-source", required_argument, NULL, ARG_CERTIFICATE_SOURCE },
+ {}
+ };
+
+ int c, r;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+ switch (c) {
+
+ case 'h':
+ help(0, NULL, NULL);
+ return 0;
+
+ case ARG_VERSION:
+ return version();
+
+ case ARG_PRIVATE_KEY:
+ r = free_and_strdup_warn(&arg_private_key, optarg);
+ if (r < 0)
+ return r;
+
+ break;
+
+ case ARG_PRIVATE_KEY_SOURCE:
+ r = parse_openssl_key_source_argument(
+ optarg,
+ &arg_private_key_source,
+ &arg_private_key_source_type);
+ if (r < 0)
+ return r;
+
+ break;
+
+ case ARG_CERTIFICATE:
+ r = free_and_strdup_warn(&arg_certificate, optarg);
+ if (r < 0)
+ return r;
+ break;
+
+ case ARG_CERTIFICATE_SOURCE:
+ r = parse_openssl_certificate_source_argument(
+ optarg,
+ &arg_certificate_source,
+ &arg_certificate_source_type);
+ if (r < 0)
+ return r;
+ break;
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ assert_not_reached();
+ }
+
+ if (arg_private_key_source && !arg_certificate)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "When using --private-key-source=, --certificate= must be specified.");
+
+ return 1;
+}
+
+static int verb_validate(int argc, char *argv[], void *userdata) {
+ _cleanup_(X509_freep) X509 *certificate = NULL;
+ _cleanup_(openssl_ask_password_ui_freep) OpenSSLAskPasswordUI *ui = NULL;
+ _cleanup_(EVP_PKEY_freep) EVP_PKEY *private_key = NULL;
+ int r;
+
+ if (!arg_certificate)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "No certificate specified, use --certificate=");
+
+ if (!arg_private_key)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "No private key specified, use --private-key=.");
+
+ if (arg_certificate_source_type == OPENSSL_CERTIFICATE_SOURCE_FILE) {
+ r = parse_path_argument(arg_certificate, /*suppress_root=*/ false, &arg_certificate);
+ if (r < 0)
+ return r;
+ }
+
+ r = openssl_load_x509_certificate(
+ arg_certificate_source_type,
+ arg_certificate_source,
+ arg_certificate,
+ &certificate);
+ if (r < 0)
+ return log_error_errno(r, "Failed to load X.509 certificate from %s: %m", arg_certificate);
+
+ if (arg_private_key_source_type == OPENSSL_KEY_SOURCE_FILE) {
+ r = parse_path_argument(arg_private_key, /* suppress_root= */ false, &arg_private_key);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse private key path %s: %m", arg_private_key);
+ }
+
+ r = openssl_load_private_key(
+ arg_private_key_source_type,
+ arg_private_key_source,
+ arg_private_key,
+ &(AskPasswordRequest) {
+ .id = "keyutil-private-key-pin",
+ .keyring = arg_private_key,
+ .credential = "keyutil.private-key-pin",
+ },
+ &private_key,
+ &ui);
+ if (r < 0)
+ return log_error_errno(r, "Failed to load private key from %s: %m", arg_private_key);
+
+ puts("OK");
+ return 0;
+}
+
+static int verb_public(int argc, char *argv[], void *userdata) {
+ _cleanup_(EVP_PKEY_freep) EVP_PKEY *public_key = NULL;
+ int r;
+
+ if (arg_certificate) {
+ _cleanup_(X509_freep) X509 *certificate = NULL;
+
+ if (arg_certificate_source_type == OPENSSL_CERTIFICATE_SOURCE_FILE) {
+ r = parse_path_argument(arg_certificate, /*suppress_root=*/ false, &arg_certificate);
+ if (r < 0)
+ return r;
+ }
+
+ r = openssl_load_x509_certificate(
+ arg_certificate_source_type,
+ arg_certificate_source,
+ arg_certificate,
+ &certificate);
+ if (r < 0)
+ return log_error_errno(r, "Failed to load X.509 certificate from %s: %m", arg_certificate);
+
+ public_key = X509_get_pubkey(certificate);
+ if (!public_key)
+ return log_error_errno(
+ SYNTHETIC_ERRNO(EIO),
+ "Failed to extract public key from certificate %s.",
+ arg_certificate);
+
+ } else if (arg_private_key) {
+ _cleanup_(openssl_ask_password_ui_freep) OpenSSLAskPasswordUI *ui = NULL;
+ _cleanup_(EVP_PKEY_freep) EVP_PKEY *private_key = NULL;
+
+ if (arg_private_key_source_type == OPENSSL_KEY_SOURCE_FILE) {
+ r = parse_path_argument(arg_private_key, /* suppress_root= */ false, &arg_private_key);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse private key path %s: %m", arg_private_key);
+ }
+
+ r = openssl_load_private_key(
+ arg_private_key_source_type,
+ arg_private_key_source,
+ arg_private_key,
+ &(AskPasswordRequest) {
+ .id = "keyutil-private-key-pin",
+ .keyring = arg_private_key,
+ .credential = "keyutil.private-key-pin",
+ },
+ &private_key,
+ &ui);
+ if (r < 0)
+ return log_error_errno(r, "Failed to load private key from %s: %m", arg_private_key);
+
+ _cleanup_(memstream_done) MemStream m = {};
+ FILE *tf = memstream_init(&m);
+ if (!tf)
+ return log_oom();
+
+ if (i2d_PUBKEY_fp(tf, private_key) != 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, &public_key))
+ return log_error_errno(SYNTHETIC_ERRNO(EIO),
+ "Failed to parse extracted public key of private key file '%s'.", arg_private_key);
+ } else
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "One of --certificate=, or --private-key= must be specified");
+
+ if (PEM_write_PUBKEY(stdout, public_key) == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write public key to stdout");
+
+ return 0;
+}
+
+static int run(int argc, char *argv[]) {
+ static const Verb verbs[] = {
+ { "help", VERB_ANY, VERB_ANY, 0, help },
+ { "validate", VERB_ANY, 1, 0, verb_validate },
+ { "public", VERB_ANY, 1, 0, verb_public },
+ {}
+ };
+ int r;
+
+ log_setup();
+
+ r = parse_argv(argc, argv);
+ if (r <= 0)
+ return r;
+
+ return dispatch_verb(argc, argv, verbs, NULL);
+}
+
+DEFINE_MAIN_FUNCTION(run);
diff --git a/src/keyutil/meson.build b/src/keyutil/meson.build
new file mode 100644
index 0000000000..956f603989
--- /dev/null
+++ b/src/keyutil/meson.build
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+executables += [
+ libexec_template + {
+ 'name' : 'systemd-keyutil',
+ 'conditions' : [
+ 'HAVE_OPENSSL',
+ ],
+ 'sources' : files('keyutil.c'),
+ 'dependencies' : libopenssl,
+ },
+]
diff --git a/src/measure/measure.c b/src/measure/measure.c
index ac294d28b3..979426c18f 100644
--- a/src/measure/measure.c
+++ b/src/measure/measure.c
@@ -77,7 +77,6 @@ static int help(int argc, char *argv[], void *userdata) {
" status Show current PCR values\n"
" calculate Calculate expected PCR values\n"
" sign Calculate and sign expected PCR values\n"
- " pcrpkey Extract the PCR public key\n"
"\n%3$sOptions:%4$s\n"
" -h --help Show this help\n"
" --version Print version\n"
@@ -1174,100 +1173,12 @@ static int verb_status(int argc, char *argv[], void *userdata) {
return 0;
}
-static int verb_pcrpkey(int argc, char *argv[], void *userdata) {
- _cleanup_(EVP_PKEY_freep) EVP_PKEY *public_key = NULL;
- int r;
-
- if (arg_public_key) {
- _cleanup_fclose_ FILE *public_keyf = NULL;
-
- public_keyf = fopen(arg_public_key, "re");
- if (!public_keyf)
- return log_error_errno(errno, "Failed to open public key file '%s': %m", arg_public_key);
-
- public_key = PEM_read_PUBKEY(public_keyf, NULL, NULL, NULL);
- if (!public_key)
- return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse public key '%s'.", arg_public_key);
-
- } else if (arg_certificate) {
- _cleanup_(X509_freep) X509 *certificate = NULL;
-
- if (arg_certificate_source_type == OPENSSL_CERTIFICATE_SOURCE_FILE) {
- r = parse_path_argument(arg_certificate, /*suppress_root=*/ false, &arg_certificate);
- if (r < 0)
- return r;
- }
-
- r = openssl_load_x509_certificate(
- arg_certificate_source_type,
- arg_certificate_source,
- arg_certificate,
- &certificate);
- if (r < 0)
- return log_error_errno(r, "Failed to load X.509 certificate from %s: %m", arg_certificate);
-
- public_key = X509_get_pubkey(certificate);
- if (!public_key)
- return log_error_errno(
- SYNTHETIC_ERRNO(EIO),
- "Failed to extract public key from certificate %s.",
- arg_certificate);
-
- } else if (arg_private_key) {
- _cleanup_(openssl_ask_password_ui_freep) OpenSSLAskPasswordUI *ui = NULL;
- _cleanup_(EVP_PKEY_freep) EVP_PKEY *private_key = NULL;
-
- if (arg_private_key_source_type == OPENSSL_KEY_SOURCE_FILE) {
- r = parse_path_argument(arg_private_key, /* suppress_root= */ false, &arg_private_key);
- if (r < 0)
- return log_error_errno(r, "Failed to parse private key path %s: %m", arg_private_key);
- }
-
- r = openssl_load_private_key(
- arg_private_key_source_type,
- arg_private_key_source,
- arg_private_key,
- &(AskPasswordRequest) {
- .id = "measure-private-key-pin",
- .keyring = arg_private_key,
- .credential = "measure.private-key-pin",
- },
- &private_key,
- &ui);
- if (r < 0)
- return log_error_errno(r, "Failed to load private key from %s: %m", arg_private_key);
-
- _cleanup_(memstream_done) MemStream m = {};
- FILE *tf = memstream_init(&m);
- if (!tf)
- return log_oom();
-
- if (i2d_PUBKEY_fp(tf, private_key) != 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, &public_key))
- return log_error_errno(SYNTHETIC_ERRNO(EIO),
- "Failed to parse extracted public key of private key file '%s'.", arg_private_key);
- } else
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "One of --public-key=, --certificate=, or --private-key= must be specified");
-
- if (PEM_write_PUBKEY(stdout, public_key) == 0)
- return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write public key to stdout");
-
- return 0;
-}
-
static int measure_main(int argc, char *argv[]) {
static const Verb verbs[] = {
{ "help", VERB_ANY, VERB_ANY, 0, help },
{ "status", VERB_ANY, 1, VERB_DEFAULT, verb_status },
{ "calculate", VERB_ANY, 1, 0, verb_calculate },
{ "sign", VERB_ANY, 1, 0, verb_sign },
- { "pcrpkey", VERB_ANY, 1, 0, verb_pcrpkey },
{}
};
diff --git a/src/sbsign/sbsign.c b/src/sbsign/sbsign.c
index d65f28b4c4..81970a7302 100644
--- a/src/sbsign/sbsign.c
+++ b/src/sbsign/sbsign.c
@@ -45,7 +45,6 @@ static int help(int argc, char *argv[], void *userdata) {
"\n%5$sSign binaries for EFI Secure Boot%6$s\n"
"\n%3$sCommands:%4$s\n"
" sign EXEFILE Sign the given binary for EFI Secure Boot\n"
- " validate-key Load and validate the given certificate and private key\n"
"\n%3$sOptions:%4$s\n"
" -h --help Show this help\n"
" --version Print version\n"
@@ -498,63 +497,10 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
return 0;
}
-static int verb_validate_key(int argc, char *argv[], void *userdata) {
- _cleanup_(X509_freep) X509 *certificate = NULL;
- _cleanup_(openssl_ask_password_ui_freep) OpenSSLAskPasswordUI *ui = NULL;
- _cleanup_(EVP_PKEY_freep) EVP_PKEY *private_key = NULL;
- int r;
-
- if (!arg_certificate)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "No certificate specified, use --certificate=");
-
- if (!arg_private_key)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "No private key specified, use --private-key=.");
-
- if (arg_certificate_source_type == OPENSSL_CERTIFICATE_SOURCE_FILE) {
- r = parse_path_argument(arg_certificate, /*suppress_root=*/ false, &arg_certificate);
- if (r < 0)
- return r;
- }
-
- r = openssl_load_x509_certificate(
- arg_certificate_source_type,
- arg_certificate_source,
- arg_certificate,
- &certificate);
- if (r < 0)
- return log_error_errno(r, "Failed to load X.509 certificate from %s: %m", arg_certificate);
-
- if (arg_private_key_source_type == OPENSSL_KEY_SOURCE_FILE) {
- r = parse_path_argument(arg_private_key, /* suppress_root= */ false, &arg_private_key);
- if (r < 0)
- return log_error_errno(r, "Failed to parse private key path %s: %m", arg_private_key);
- }
-
- r = openssl_load_private_key(
- arg_private_key_source_type,
- arg_private_key_source,
- arg_private_key,
- &(AskPasswordRequest) {
- .id = "sbsign-private-key-pin",
- .keyring = arg_private_key,
- .credential = "sbsign.private-key-pin",
- },
- &private_key,
- &ui);
- if (r < 0)
- return log_error_errno(r, "Failed to load private key from %s: %m", arg_private_key);
-
- puts("OK");
- return 0;
-}
-
static int run(int argc, char *argv[]) {
static const Verb verbs[] = {
{ "help", VERB_ANY, VERB_ANY, 0, help },
{ "sign", 2, 2, 0, verb_sign },
- { "validate-key", VERB_ANY, 1, 0, verb_validate_key },
{}
};
int r;
diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py
index 355e3f99f4..ae3e1d03b4 100755
--- a/src/ukify/ukify.py
+++ b/src/ukify/ukify.py
@@ -1017,8 +1017,8 @@ def make_uki(opts: UkifyConfig) -> None:
pcrpkey: Union[bytes, Path, None] = opts.pcrpkey
if pcrpkey is None:
- measure_tool = find_tool('systemd-measure', '/usr/lib/systemd/systemd-measure')
- cmd = [measure_tool, 'pcrpkey']
+ measure_tool = find_tool('systemd-keyutil', '/usr/lib/systemd/systemd-keyutil')
+ cmd = [measure_tool, 'public']
if opts.pcr_public_keys and len(opts.pcr_public_keys) == 1:
# If we're using an engine or provider, the public key will be an X.509 certificate.
@@ -1026,11 +1026,11 @@ def make_uki(opts: UkifyConfig) -> None:
cmd += ['--certificate', opts.pcr_public_keys[0]]
if opts.certificate_provider:
cmd += ['--certificate-source', f'provider:{opts.certificate_provider}']
- else:
- cmd += ['--public-key', opts.pcr_public_keys[0]]
- print('+', shell_join(cmd))
- pcrpkey = subprocess.check_output(cmd)
+ print('+', shell_join(cmd))
+ pcrpkey = subprocess.check_output(cmd)
+ else:
+ pcrpkey = Path(opts.pcr_public_keys[0])
elif opts.pcr_private_keys and len(opts.pcr_private_keys) == 1:
cmd += ['--private-key', Path(opts.pcr_private_keys[0])]
diff --git a/test/units/TEST-74-AUX-UTILS.keyutil.sh b/test/units/TEST-74-AUX-UTILS.keyutil.sh
new file mode 100755
index 0000000000..bbbbf9fd67
--- /dev/null
+++ b/test/units/TEST-74-AUX-UTILS.keyutil.sh
@@ -0,0 +1,50 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+# shellcheck disable=SC2016
+set -eux
+set -o pipefail
+
+# shellcheck source=test/units/test-control.sh
+. "$(dirname "$0")"/test-control.sh
+# shellcheck source=test/units/util.sh
+. "$(dirname "$0")"/util.sh
+
+if ! command -v /usr/lib/systemd/systemd-keyutil >/dev/null; then
+ echo "systemd-keyutil not found, skipping."
+ exit 0
+fi
+
+cat >/tmp/openssl.conf <<EOF
+[ req ]
+prompt = no
+distinguished_name = req_distinguished_name
+
+[ req_distinguished_name ]
+C = DE
+ST = Test State
+L = Test Locality
+O = Org Name
+OU = Org Unit Name
+CN = Common Name
+emailAddress = test@email.com
+EOF
+
+openssl req -config /tmp/openssl.conf -subj="/CN=waldo" \
+ -x509 -sha256 -nodes -days 365 -newkey rsa:4096 \
+ -keyout /tmp/test.key -out /tmp/test.crt
+
+testcase_validate() {
+ /usr/lib/systemd/systemd-keyutil validate --certificate /tmp/test.crt --private-key /tmp/test.key
+}
+
+testcase_public() {
+ PUBLIC="$(/usr/lib/systemd/systemd-keyutil public --certificate /tmp/test.crt)"
+ assert_eq "$PUBLIC" "$(openssl x509 -in /tmp/test.crt -pubkey -noout)"
+
+ PUBLIC="$(/usr/lib/systemd/systemd-keyutil public --private-key /tmp/test.key)"
+ assert_eq "$PUBLIC" "$(openssl x509 -in /tmp/test.crt -pubkey -noout)"
+
+ (! /usr/lib/systemd/systemd-keyutil public)
+}
+
+run_testcases
diff --git a/test/units/TEST-74-AUX-UTILS.sbsign.sh b/test/units/TEST-74-AUX-UTILS.sbsign.sh
index 891a2ae8af..fc186517d1 100755
--- a/test/units/TEST-74-AUX-UTILS.sbsign.sh
+++ b/test/units/TEST-74-AUX-UTILS.sbsign.sh
@@ -53,8 +53,4 @@ testcase_sign_systemd_boot() {
sbverify --cert /tmp/sb.crt /tmp/sdboot
}
-testcase_validate_key() {
- /usr/lib/systemd/systemd-sbsign validate-key --certificate /tmp/sb.crt --private-key /tmp/sb.key
-}
-
run_testcases