1
0
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:
Luca Boccassi 2024-09-14 00:19:48 +02:00
parent faa79a78c8
commit 33319701ca
2 changed files with 88 additions and 1 deletions

View File

@ -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>

View File

@ -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;