mirror of
https://github.com/systemd/systemd
synced 2024-07-21 02:05:05 +00:00
repart: add --private-key-source and drop --private-key-uri
It turns out it's mostly PKCS11 that supports the URI format,
and other engines just take files. For example the tpm2-tss-openssl
engine just takes a sealed private key file path as the key input,
and the engine needs to be specified separately.
Add --private-key-source=file|engine:foo|provider:bar to
manually specify how to use the private key parameter.
Follow-up for 0a8264080a
This commit is contained in:
parent
793ceda177
commit
a73144bbdf
|
@ -129,14 +129,6 @@ All tools:
|
|||
* `$SYSTEMD_VERITY_SHARING=0` — if set, sharing dm-verity devices by
|
||||
using a stable `<ROOTHASH>-verity` device mapper name will be disabled.
|
||||
|
||||
* `$SYSTEMD_OPENSSL_KEY_LOADER`— when using OpenSSL to load a key via an engine
|
||||
or a provider, can be used to force the usage of one or the other interface.
|
||||
Set to 'engine' to force the usage of the old engine API, and to 'provider'
|
||||
force the usage of the new provider API. If unset, the provider will be tried
|
||||
first and the engine as a fallback if that fails. Providers are the new OpenSSL
|
||||
3 API, but there are very few if any in a production-ready state, so engines
|
||||
are still needed.
|
||||
|
||||
`systemctl`:
|
||||
|
||||
* `$SYSTEMCTL_FORCE_BUS=1` — if set, do not connect to PID 1's private D-Bus
|
||||
|
|
|
@ -355,11 +355,13 @@
|
|||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--private-key-uri=</option></term>
|
||||
<term><option>--private-key-source=</option></term>
|
||||
|
||||
<listitem><para>Takes a URI-like string referring to a private key, that will be passed to OpenSSL's
|
||||
"engine" or "provider" logic. Configures the signing key to use when creating verity signature
|
||||
partitions with the <varname>Verity=signature</varname> setting in partition files.</para>
|
||||
<listitem><para>Takes one of <literal>file</literal>, <literal>engine</literal> or
|
||||
<literal>provider</literal>. In the latter two cases, it is followed by the name of a provider or
|
||||
engine, separated by colon, that will be passed to OpenSSL's "engine" or "provider" logic.
|
||||
Configures the signing mechanism to use when creating verity signature partitions with the
|
||||
<varname>Verity=signature</varname> setting in partition files.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||
</varlistentry>
|
||||
|
@ -662,7 +664,7 @@ VERSION_ID=38
|
|||
IMAGE_ID=my-foo
|
||||
IMAGE_VERSION=7
|
||||
EOF
|
||||
systemd-repart --make-ddi=sysext --private-key-uri="pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=0123456789abcdef;token=Some%20Cert" --certificate=cert.crt -s tree/ /var/lib/extensions/my-foo.sysext.raw
|
||||
systemd-repart --make-ddi=sysext --private-key-source=engine:pkcs11 --private-key="pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=0123456789abcdef;token=Some%20Cert" --certificate=cert.crt -s tree/ /var/lib/extensions/my-foo.sysext.raw
|
||||
systemd-sysext refresh</programlisting>
|
||||
|
||||
<para>The DDI generated that way may be applied to the system with
|
||||
|
|
|
@ -146,6 +146,8 @@ static bool arg_legend = true;
|
|||
static void *arg_key = NULL;
|
||||
static size_t arg_key_size = 0;
|
||||
static EVP_PKEY *arg_private_key = NULL;
|
||||
static KeySourceType arg_private_key_source_type = OPENSSL_KEY_SOURCE_FILE;
|
||||
static char *arg_private_key_source = NULL;
|
||||
static X509 *arg_certificate = NULL;
|
||||
static char *arg_tpm2_device = NULL;
|
||||
static uint32_t arg_tpm2_seal_key_handle = 0;
|
||||
|
@ -177,6 +179,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
|
|||
STATIC_DESTRUCTOR_REGISTER(arg_definitions, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_key, erase_and_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_private_key, EVP_PKEY_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_private_key_source, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_certificate, X509_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device_key, freep);
|
||||
|
@ -6806,8 +6809,14 @@ static int help(void) {
|
|||
" Specify disk image dissection policy\n"
|
||||
" --definitions=DIR Find partition definitions in specified directory\n"
|
||||
" --key-file=PATH Key to use when encrypting partitions\n"
|
||||
" --private-key=PATH Private key to use when generating verity roothash\n"
|
||||
" signatures\n"
|
||||
" --private-key=PATH|URI\n"
|
||||
" Private key to use when generating verity roothash\n"
|
||||
" signatures, or an engine or provider specific\n"
|
||||
" designation if --private-key-source= is used.\n"
|
||||
" --private-key-source=file|provider:PROVIDER|engine:ENGINE\n"
|
||||
" Specify how to use the --private-key=. Allows to use\n"
|
||||
" an OpenSSL engine/provider when generating verity\n"
|
||||
" roothash signatures\n"
|
||||
" --certificate=PATH PEM certificate to use when generating verity\n"
|
||||
" roothash signatures\n"
|
||||
" --tpm2-device=PATH Path to TPM2 device node to use\n"
|
||||
|
@ -6857,7 +6866,7 @@ static int help(void) {
|
|||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
_cleanup_free_ char *private_key = NULL, *private_key_uri = NULL;
|
||||
_cleanup_free_ char *private_key = NULL;
|
||||
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
|
@ -6878,7 +6887,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
ARG_JSON,
|
||||
ARG_KEY_FILE,
|
||||
ARG_PRIVATE_KEY,
|
||||
ARG_PRIVATE_KEY_URI,
|
||||
ARG_PRIVATE_KEY_SOURCE,
|
||||
ARG_CERTIFICATE,
|
||||
ARG_TPM2_DEVICE,
|
||||
ARG_TPM2_DEVICE_KEY,
|
||||
|
@ -6921,7 +6930,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
{ "json", required_argument, NULL, ARG_JSON },
|
||||
{ "key-file", required_argument, NULL, ARG_KEY_FILE },
|
||||
{ "private-key", required_argument, NULL, ARG_PRIVATE_KEY },
|
||||
{ "private-key-uri", required_argument, NULL, ARG_PRIVATE_KEY_URI },
|
||||
{ "private-key-source", required_argument, NULL, ARG_PRIVATE_KEY_SOURCE },
|
||||
{ "certificate", required_argument, NULL, ARG_CERTIFICATE },
|
||||
{ "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE },
|
||||
{ "tpm2-device-key", required_argument, NULL, ARG_TPM2_DEVICE_KEY },
|
||||
|
@ -7115,12 +7124,14 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
break;
|
||||
}
|
||||
|
||||
case ARG_PRIVATE_KEY_URI: {
|
||||
r = free_and_strdup_warn(&private_key_uri, optarg);
|
||||
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: {
|
||||
_cleanup_free_ char *cert = NULL;
|
||||
|
@ -7465,12 +7476,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
*p = gpt_partition_type_override_architecture(*p, arg_architecture);
|
||||
}
|
||||
|
||||
if (private_key && private_key_uri)
|
||||
return log_error_errno(
|
||||
SYNTHETIC_ERRNO(EINVAL),
|
||||
"Cannot specify both --private-key= and --private-key-uri=.");
|
||||
|
||||
if (private_key) {
|
||||
if (private_key && arg_private_key_source_type == OPENSSL_KEY_SOURCE_FILE) {
|
||||
_cleanup_(erase_and_freep) char *k = NULL;
|
||||
size_t n = 0;
|
||||
|
||||
|
@ -7485,16 +7491,22 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
r = parse_private_key(k, n, &arg_private_key);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (private_key_uri) {
|
||||
} else if (private_key &&
|
||||
IN_SET(arg_private_key_source_type, OPENSSL_KEY_SOURCE_ENGINE, OPENSSL_KEY_SOURCE_PROVIDER)) {
|
||||
/* This must happen after parse_x509_certificate() is called above, otherwise
|
||||
* signing later will get stuck as the parsed private key won't have the
|
||||
* certificate, so this block cannot be inline in ARG_PRIVATE_KEY. */
|
||||
r = openssl_load_key_from_token(private_key_uri, &arg_private_key);
|
||||
r = openssl_load_key_from_token(
|
||||
arg_private_key_source_type,
|
||||
arg_private_key_source,
|
||||
private_key,
|
||||
&arg_private_key);
|
||||
if (r < 0)
|
||||
return log_error_errno(
|
||||
r,
|
||||
"Failed to load key '%s' from OpenSSL provider: %m",
|
||||
private_key);
|
||||
"Failed to load key '%s' from OpenSSL private key source %s: %m",
|
||||
private_key,
|
||||
arg_private_key_source);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -1366,38 +1366,25 @@ static int load_key_from_engine(const char *engine, const char *private_key_uri,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int openssl_load_key_from_token(const char *private_key_uri, EVP_PKEY **ret) {
|
||||
_cleanup_free_ char *provider = NULL;
|
||||
const char *colon, *e;
|
||||
int r;
|
||||
int openssl_load_key_from_token(
|
||||
KeySourceType private_key_source_type,
|
||||
const char *private_key_source,
|
||||
const char *private_key,
|
||||
EVP_PKEY **ret) {
|
||||
|
||||
assert(private_key_uri);
|
||||
assert(IN_SET(private_key_source_type, OPENSSL_KEY_SOURCE_ENGINE, OPENSSL_KEY_SOURCE_PROVIDER));
|
||||
assert(private_key_source);
|
||||
assert(private_key);
|
||||
|
||||
colon = strchr(private_key_uri, ':');
|
||||
if (!colon)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid URI '%s'", private_key_uri);
|
||||
switch (private_key_source_type) {
|
||||
|
||||
provider = strndup(private_key_uri, colon - private_key_uri);
|
||||
if (!provider)
|
||||
return log_oom_debug();
|
||||
|
||||
e = secure_getenv("SYSTEMD_OPENSSL_KEY_LOADER");
|
||||
if (e) {
|
||||
if (streq(e, "provider"))
|
||||
r = load_key_from_provider(provider, private_key_uri, ret);
|
||||
else if (streq(e, "engine"))
|
||||
r = load_key_from_engine(provider, private_key_uri, ret);
|
||||
else
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid value for SYSTEMD_OPENSSL_KEY_LOADER: %s", e);
|
||||
} else {
|
||||
r = load_key_from_provider(provider, private_key_uri, ret);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to load key from provider '%s', falling back to engine", provider);
|
||||
r = load_key_from_engine(provider, private_key_uri, ret);
|
||||
}
|
||||
case OPENSSL_KEY_SOURCE_ENGINE:
|
||||
return load_key_from_engine(private_key_source, private_key, ret);
|
||||
case OPENSSL_KEY_SOURCE_PROVIDER:
|
||||
return load_key_from_provider(private_key_source, private_key, ret);
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1418,3 +1405,34 @@ int x509_fingerprint(X509 *cert, uint8_t buffer[static SHA256_DIGEST_SIZE]) {
|
|||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL is not supported, cannot calculate X509 fingerprint: %m");
|
||||
#endif
|
||||
}
|
||||
|
||||
int parse_openssl_key_source_argument(
|
||||
const char *argument,
|
||||
char **private_key_source,
|
||||
KeySourceType *private_key_source_type) {
|
||||
|
||||
KeySourceType type;
|
||||
const char *e = NULL;
|
||||
int r;
|
||||
|
||||
assert(argument);
|
||||
assert(private_key_source);
|
||||
assert(private_key_source_type);
|
||||
|
||||
if (streq(argument, "file"))
|
||||
type = OPENSSL_KEY_SOURCE_FILE;
|
||||
else if ((e = startswith(argument, "engine:")))
|
||||
type = OPENSSL_KEY_SOURCE_ENGINE;
|
||||
else if ((e = startswith(argument, "provider:")))
|
||||
type = OPENSSL_KEY_SOURCE_PROVIDER;
|
||||
else
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid private key source '%s'", argument);
|
||||
|
||||
r = free_and_strdup_warn(private_key_source, e);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*private_key_source_type = type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,16 @@
|
|||
#include "macro.h"
|
||||
#include "sha256.h"
|
||||
|
||||
typedef enum KeySourceType {
|
||||
OPENSSL_KEY_SOURCE_FILE,
|
||||
OPENSSL_KEY_SOURCE_ENGINE,
|
||||
OPENSSL_KEY_SOURCE_PROVIDER,
|
||||
_OPENSSL_KEY_SOURCE_MAX,
|
||||
_OPENSSL_KEY_SOURCE_INVALID = -EINVAL,
|
||||
} KeySourceType;
|
||||
|
||||
int parse_openssl_key_source_argument(const char *argument, char **private_key_source, KeySourceType *private_key_source_type);
|
||||
|
||||
#define X509_FINGERPRINT_SIZE SHA256_DIGEST_SIZE
|
||||
|
||||
#if HAVE_OPENSSL
|
||||
|
@ -123,7 +133,7 @@ int pubkey_fingerprint(EVP_PKEY *pk, const EVP_MD *md, void **ret, size_t *ret_s
|
|||
|
||||
int digest_and_sign(const EVP_MD *md, EVP_PKEY *privkey, const void *data, size_t size, void **ret, size_t *ret_size);
|
||||
|
||||
int openssl_load_key_from_token(const char *private_key_uri, EVP_PKEY **ret);
|
||||
int openssl_load_key_from_token(KeySourceType private_key_source_type, const char *private_key_source, const char *private_key, EVP_PKEY **ret);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -140,7 +150,12 @@ static inline void *EVP_PKEY_free(EVP_PKEY *p) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static inline int openssl_load_key_from_token(const char *private_key_uri, EVP_PKEY **ret) {
|
||||
static inline int openssl_load_key_from_token(
|
||||
KeySourceType private_key_source_type,
|
||||
const char *private_key_source,
|
||||
const char *private_key,
|
||||
EVP_PKEY **ret) {
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue