Compare commits

...

2 Commits

Author SHA1 Message Date
Luca Boccassi ef2943e462
Merge 33319701ca into a526b9ddfc 2024-11-19 22:26:43 -08:00
Luca Boccassi 33319701ca 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.
2024-09-15 12:02:15 +02:00
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 <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 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> <xi:include href="version-info.xml" xpointer="v248"/></listitem>
</varlistentry> </varlistentry>

View File

@ -5,12 +5,16 @@
#include <sys/stat.h> #include <sys/stat.h>
#include "alloc-util.h" #include "alloc-util.h"
#include "blockdev-util.h"
#include "cryptsetup-util.h" #include "cryptsetup-util.h"
#include "dissect-image.h"
#include "fileio.h" #include "fileio.h"
#include "fstab-util.h" #include "fstab-util.h"
#include "hexdecoct.h" #include "hexdecoct.h"
#include "log.h" #include "log.h"
#include "loop-util.h"
#include "main-func.h" #include "main-func.h"
#include "missing_loop.h"
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h" #include "path-util.h"
#include "pretty-print.h" #include "pretty-print.h"
@ -274,6 +278,79 @@ static int parse_options(const char *options) {
return r; 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[]) { static int run(int argc, char *argv[]) {
_cleanup_(crypt_freep) struct crypt_device *cd = NULL; _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
const char *verb; const char *verb;
@ -371,6 +448,13 @@ static int run(int argc, char *argv[]) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to configure data device: %m"); 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 (arg_root_hash_signature) {
#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY #if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
_cleanup_free_ char *hash_sig = NULL; _cleanup_free_ char *hash_sig = NULL;