mirror of
https://github.com/systemd/systemd.git
synced 2024-12-21 13:34:21 +03:00
veritysetup: parse signature from DPS partition
If the signature is not specified manually, and sd-veritysetup is running on a device, try to find the parent and if it's a DPS-compliant GPT image with a signature partition, parse it and use it. This allows automatically using the signature on boot, which allows setting an IPE policy that enforces a validated signature on the rootfs too.
This commit is contained in:
parent
faa79a78c8
commit
33319701ca
@ -217,7 +217,10 @@ This is based on crypttab(5).
|
||||
|
||||
<listitem><para>A base64 string encoding the root hash signature prefixed by <literal>base64:</literal> or a
|
||||
path to roothash signature file used to verify the root hash (in kernel). This feature requires Linux kernel
|
||||
version 5.4 or more recent.</para>
|
||||
version 5.4 or more recent. Since version 257, if not specified and the data device is in a GPT image with a
|
||||
<ulink url="https://uapi-group.org/specifications/specs/discoverable_partitions_specification">
|
||||
Discoverable Partitions Specification</ulink> compliant matching signature partition, it will be
|
||||
automatically loaded and used.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v248"/></listitem>
|
||||
</varlistentry>
|
||||
|
@ -5,12 +5,16 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "blockdev-util.h"
|
||||
#include "cryptsetup-util.h"
|
||||
#include "dissect-image.h"
|
||||
#include "fileio.h"
|
||||
#include "fstab-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "log.h"
|
||||
#include "loop-util.h"
|
||||
#include "main-func.h"
|
||||
#include "missing_loop.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "pretty-print.h"
|
||||
@ -274,6 +278,79 @@ static int parse_options(const char *options) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static int find_dps_signature(
|
||||
const char *data_device,
|
||||
void *root_hash,
|
||||
size_t root_hash_size,
|
||||
char **ret_root_hash_signature) {
|
||||
|
||||
_cleanup_(verity_settings_done) VeritySettings verity = VERITY_SETTINGS_DEFAULT;
|
||||
_cleanup_free_ char *base64_signature = NULL, *string_signature = NULL;
|
||||
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
|
||||
_cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
|
||||
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
|
||||
DissectImageFlags dissect_image_flags =
|
||||
DISSECT_IMAGE_GPT_ONLY |
|
||||
DISSECT_IMAGE_USR_NO_ROOT |
|
||||
DISSECT_IMAGE_ADD_PARTITION_DEVICES |
|
||||
DISSECT_IMAGE_DEVICE_READ_ONLY;
|
||||
ssize_t len;
|
||||
int r;
|
||||
|
||||
assert(data_device);
|
||||
assert(root_hash);
|
||||
assert(root_hash_size > 0);
|
||||
assert(ret_root_hash_signature);
|
||||
|
||||
if (!startswith(data_device, "/dev/"))
|
||||
return -EINVAL;
|
||||
|
||||
verity.root_hash_size = root_hash_size;
|
||||
verity.root_hash = malloc(root_hash_size);
|
||||
if (!verity.root_hash)
|
||||
return log_oom_debug();
|
||||
memcpy(verity.root_hash, root_hash, root_hash_size);
|
||||
|
||||
r = block_device_new_from_path(data_device, BLOCK_DEVICE_LOOKUP_WHOLE_DISK, &device);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to get udev device for data device: %m");
|
||||
|
||||
r = loop_device_open(device, O_RDONLY, LOCK_SH, &loop_device);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to create loop device for root image: %m");
|
||||
|
||||
r = dissect_loop_device(
|
||||
loop_device,
|
||||
&verity,
|
||||
/* mount_options= */ NULL,
|
||||
/* image_policy= */ NULL,
|
||||
dissect_image_flags,
|
||||
&dissected_image);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to dissect image: %m");
|
||||
|
||||
r = dissected_image_load_verity_sig_partition(
|
||||
dissected_image,
|
||||
loop_device->fd,
|
||||
&verity);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to load verity signature partition: %m");
|
||||
if (r == 0)
|
||||
return -ENOENT;
|
||||
|
||||
len = base64mem(verity.root_hash_sig, verity.root_hash_sig_size, &base64_signature);
|
||||
if (len < 0)
|
||||
return log_debug_errno(len, "Failed to encode root hash signature: %m");
|
||||
|
||||
string_signature = strjoin("base64:", base64_signature);
|
||||
if (!string_signature)
|
||||
return log_oom_debug();
|
||||
|
||||
*ret_root_hash_signature = TAKE_PTR(string_signature);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
|
||||
const char *verb;
|
||||
@ -371,6 +448,13 @@ static int run(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to configure data device: %m");
|
||||
|
||||
#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
|
||||
/* If we can support signature checks but we weren't given one, try to find it following the
|
||||
* DPS on the same GPT device */
|
||||
if (!arg_root_hash_signature)
|
||||
(void) find_dps_signature(data_device, m, l, &arg_root_hash_signature);
|
||||
#endif
|
||||
|
||||
if (arg_root_hash_signature) {
|
||||
#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
|
||||
_cleanup_free_ char *hash_sig = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user