mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-21 18:03:41 +03:00
repart: Add support for generating verity sig partitions
This commit is contained in:
parent
8939d3351d
commit
b456191d3c
@ -583,17 +583,21 @@
|
||||
<varlistentry>
|
||||
<term><varname>Verity=</varname></term>
|
||||
|
||||
<listitem><para>Takes one of <literal>off</literal>, <literal>data</literal> or
|
||||
<literal>hash</literal>. Defaults to <literal>off</literal>. If set to <literal>off</literal> or
|
||||
<literal>data</literal>, the partition is populated with content as specified by
|
||||
<varname>CopyBlocks=</varname> or <varname>CopyFiles=</varname>. If set to <literal>hash</literal>,
|
||||
the partition will be populated with verity hashes from a matching verity data partition. A matching
|
||||
data partition is a partition with <varname>Verity=</varname> set to <literal>data</literal> and the
|
||||
same verity match key (as configured with <varname>VerityMatchKey=</varname>). If not explicitly
|
||||
configured, the data partition's UUID will be set to the first 128 bits of the verity root hash.
|
||||
Similarly, if not configured, the hash partition's UUID will be set to the final 128 bits of the
|
||||
verity root hash. The verity root hash itself will be included in the output of
|
||||
<command>systemd-repart</command>.</para>
|
||||
<listitem><para>Takes one of <literal>off</literal>, <literal>data</literal>,
|
||||
<literal>hash</literal> or <literal>signature</literal>. Defaults to <literal>off</literal>. If set
|
||||
to <literal>off</literal> or <literal>data</literal>, the partition is populated with content as
|
||||
specified by <varname>CopyBlocks=</varname> or <varname>CopyFiles=</varname>. If set to
|
||||
<literal>hash</literal>, the partition will be populated with verity hashes from the matching verity
|
||||
data partition. If set to <literal>signature</literal>, The partition will be populated with a JSON
|
||||
object containing a signature of the verity root hash of the matching verity hash partition.</para>
|
||||
|
||||
<para>A matching verity partition is a partition with the same verity match key (as configured with
|
||||
<varname>VerityMatchKey=</varname>).</para>
|
||||
|
||||
<para>If not explicitly configured, the data partition's UUID will be set to the first 128
|
||||
bits of the verity root hash. Similarly, if not configured, the hash partition's UUID will be set to
|
||||
the final 128 bits of the verity root hash. The verity root hash itself will be included in the
|
||||
output of <command>systemd-repart</command>.</para>
|
||||
|
||||
<para>This option has no effect if the partition already exists.</para>
|
||||
|
||||
|
@ -3682,7 +3682,8 @@ if conf.get('ENABLE_REPART') == 1
|
||||
link_with : [libshared],
|
||||
dependencies : [threads,
|
||||
libblkid,
|
||||
libfdisk],
|
||||
libfdisk,
|
||||
libopenssl],
|
||||
install_rpath : rootpkglibdir,
|
||||
install : true,
|
||||
install_dir : rootbindir)
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "hexdecoct.h"
|
||||
#include "hmac.h"
|
||||
#include "id128-util.h"
|
||||
#include "io-util.h"
|
||||
#include "json.h"
|
||||
#include "list.h"
|
||||
#include "loop-util.h"
|
||||
@ -48,6 +49,7 @@
|
||||
#include "mkfs-util.h"
|
||||
#include "mount-util.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "openssl-util.h"
|
||||
#include "parse-argument.h"
|
||||
#include "parse-helpers.h"
|
||||
#include "pretty-print.h"
|
||||
@ -76,6 +78,9 @@
|
||||
/* Hard lower limit for new partition sizes */
|
||||
#define HARD_MIN_SIZE 4096
|
||||
|
||||
/* We know up front we're never going to put more than this in a verity sig partition. */
|
||||
#define VERITY_SIG_SIZE (HARD_MIN_SIZE * 4)
|
||||
|
||||
/* libfdisk takes off slightly more than 1M of the disk size when creating a GPT disk label */
|
||||
#define GPT_METADATA_SIZE (1044*1024)
|
||||
|
||||
@ -113,6 +118,8 @@ static PagerFlags arg_pager_flags = 0;
|
||||
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 X509 *arg_certificate = NULL;
|
||||
static char *arg_tpm2_device = NULL;
|
||||
static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
|
||||
static char *arg_tpm2_public_key = NULL;
|
||||
@ -123,6 +130,8 @@ STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
|
||||
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_certificate, X509_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_public_key, freep);
|
||||
|
||||
@ -143,6 +152,7 @@ typedef enum VerityMode {
|
||||
VERITY_OFF,
|
||||
VERITY_DATA,
|
||||
VERITY_HASH,
|
||||
VERITY_SIG,
|
||||
_VERITY_MODE_MAX,
|
||||
_VERITY_MODE_INVALID = -EINVAL,
|
||||
} VerityMode;
|
||||
@ -240,6 +250,7 @@ static const char *verity_mode_table[_VERITY_MODE_MAX] = {
|
||||
[VERITY_OFF] = "off",
|
||||
[VERITY_DATA] = "data",
|
||||
[VERITY_HASH] = "hash",
|
||||
[VERITY_SIG] = "signature",
|
||||
};
|
||||
|
||||
#if HAVE_LIBCRYPTSETUP
|
||||
@ -515,6 +526,9 @@ static uint64_t partition_min_size(const Context *context, const Partition *p) {
|
||||
return p->current_size;
|
||||
}
|
||||
|
||||
if (p->verity == VERITY_SIG)
|
||||
return VERITY_SIG_SIZE;
|
||||
|
||||
sz = p->current_size != UINT64_MAX ? p->current_size : HARD_MIN_SIZE;
|
||||
|
||||
if (!PARTITION_EXISTS(p)) {
|
||||
@ -556,6 +570,9 @@ static uint64_t partition_max_size(const Context *context, const Partition *p) {
|
||||
return p->current_size;
|
||||
}
|
||||
|
||||
if (p->verity == VERITY_SIG)
|
||||
return VERITY_SIG_SIZE;
|
||||
|
||||
if (p->size_max == UINT64_MAX)
|
||||
return UINT64_MAX;
|
||||
|
||||
@ -1548,7 +1565,8 @@ static int partition_read_definition(Partition *p, const char *path, const char
|
||||
"VerityMatchKey= can only be set if Verity= is not \"%s\"",
|
||||
verity_mode_to_string(p->verity));
|
||||
|
||||
if (p->verity == VERITY_HASH && (p->copy_files || p->copy_blocks_path || p->copy_blocks_auto || p->format || p->make_directories))
|
||||
if (IN_SET(p->verity, VERITY_HASH, VERITY_SIG) &&
|
||||
(p->copy_files || p->copy_blocks_path || p->copy_blocks_auto || p->format || p->make_directories))
|
||||
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
|
||||
"CopyBlocks=/CopyFiles=/Format=/MakeDirectories= cannot be used with Verity=%s",
|
||||
verity_mode_to_string(p->verity));
|
||||
@ -1557,6 +1575,19 @@ static int partition_read_definition(Partition *p, const char *path, const char
|
||||
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Encrypting verity hash/data partitions is not supported");
|
||||
|
||||
if (p->verity == VERITY_SIG && !arg_private_key)
|
||||
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Verity signature partition requested but no private key provided (--private-key=)");
|
||||
|
||||
if (p->verity == VERITY_SIG && !arg_certificate)
|
||||
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Verity signature partition requested but no PEM certificate provided (--certificate-file=)");
|
||||
|
||||
if (p->verity == VERITY_SIG && (p->size_min != UINT64_MAX || p->size_max != UINT64_MAX))
|
||||
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
|
||||
"SizeMinBytes=/SizeMaxBytes= cannot be used with Verity=%s",
|
||||
verity_mode_to_string(p->verity));
|
||||
|
||||
/* Verity partitions are read only, let's imply the RO flag hence, unless explicitly configured otherwise. */
|
||||
if ((gpt_partition_type_is_root_verity(p->type_uuid) ||
|
||||
gpt_partition_type_is_usr_verity(p->type_uuid)) &&
|
||||
@ -1665,7 +1696,7 @@ static int context_read_definitions(
|
||||
continue;
|
||||
|
||||
for (VerityMode mode = VERITY_OFF + 1; mode < _VERITY_MODE_MAX; mode++) {
|
||||
Partition *q;
|
||||
Partition *q = NULL;
|
||||
|
||||
if (p->verity == mode)
|
||||
continue;
|
||||
@ -1674,7 +1705,7 @@ static int context_read_definitions(
|
||||
continue;
|
||||
|
||||
r = find_verity_sibling(context, p, mode, &q);
|
||||
if (r == -ENXIO)
|
||||
if (mode != VERITY_SIG && r == -ENXIO)
|
||||
return log_syntax(NULL, LOG_ERR, p->definition_path, 1, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Missing verity %s partition for verity %s partition with VerityMatchKey=%s",
|
||||
verity_mode_to_string(mode), verity_mode_to_string(p->verity), p->verity_match_key);
|
||||
@ -1685,12 +1716,14 @@ static int context_read_definitions(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (q->priority != p->priority)
|
||||
return log_syntax(NULL, LOG_ERR, p->definition_path, 1, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Priority mismatch (%i != %i) for verity sibling partitions with VerityMatchKey=%s",
|
||||
p->priority, q->priority, p->verity_match_key);
|
||||
if (q) {
|
||||
if (q->priority != p->priority)
|
||||
return log_syntax(NULL, LOG_ERR, p->definition_path, 1, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Priority mismatch (%i != %i) for verity sibling partitions with VerityMatchKey=%s",
|
||||
p->priority, q->priority, p->verity_match_key);
|
||||
|
||||
p->siblings[mode] = q;
|
||||
p->siblings[mode] = q;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3642,6 +3675,181 @@ static int context_verity_hash(Context *context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_x509_certificate(const char *certificate, size_t certificate_size, X509 **ret) {
|
||||
#if HAVE_OPENSSL
|
||||
_cleanup_(X509_freep) X509 *cert = NULL;
|
||||
_cleanup_(BIO_freep) BIO *cb = NULL;
|
||||
|
||||
assert(certificate);
|
||||
assert(certificate_size > 0);
|
||||
assert(ret);
|
||||
|
||||
cb = BIO_new_mem_buf(certificate, certificate_size);
|
||||
if (!cb)
|
||||
return log_oom();
|
||||
|
||||
cert = PEM_read_bio_X509(cb, NULL, NULL, NULL);
|
||||
if (!cert)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Failed to parse X.509 certificate: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
if (ret)
|
||||
*ret = TAKE_PTR(cert);
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "openssl is not supported, cannot parse X509 certificate.");
|
||||
#endif
|
||||
}
|
||||
|
||||
static int parse_private_key(const char *key, size_t key_size, EVP_PKEY **ret) {
|
||||
#if HAVE_OPENSSL
|
||||
_cleanup_(BIO_freep) BIO *kb = NULL;
|
||||
_cleanup_(EVP_PKEY_freep) EVP_PKEY *pk = NULL;
|
||||
|
||||
assert(key);
|
||||
assert(key_size > 0);
|
||||
assert(ret);
|
||||
|
||||
kb = BIO_new_mem_buf(key, key_size);
|
||||
if (!kb)
|
||||
return log_oom();
|
||||
|
||||
pk = PEM_read_bio_PrivateKey(kb, NULL, NULL, NULL);
|
||||
if (!pk)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse PEM private key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
if (ret)
|
||||
*ret = TAKE_PTR(pk);
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "openssl is not supported, cannot parse private key.");
|
||||
#endif
|
||||
}
|
||||
|
||||
static int sign_verity_roothash(
|
||||
const uint8_t *roothash,
|
||||
size_t roothash_size,
|
||||
uint8_t **ret_signature,
|
||||
size_t *ret_signature_size) {
|
||||
|
||||
#if HAVE_OPENSSL
|
||||
_cleanup_(BIO_freep) BIO *rb = NULL;
|
||||
_cleanup_(PKCS7_freep) PKCS7 *p7 = NULL;
|
||||
_cleanup_free_ char *hex = NULL;
|
||||
_cleanup_free_ uint8_t *sig = NULL;
|
||||
int sigsz;
|
||||
|
||||
assert(roothash);
|
||||
assert(roothash_size > 0);
|
||||
assert(ret_signature);
|
||||
assert(ret_signature_size);
|
||||
|
||||
hex = hexmem(roothash, roothash_size);
|
||||
if (!hex)
|
||||
return log_oom();
|
||||
|
||||
rb = BIO_new_mem_buf(hex, -1);
|
||||
if (!rb)
|
||||
return log_oom();
|
||||
|
||||
p7 = PKCS7_sign(arg_certificate, arg_private_key, NULL, rb, PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY);
|
||||
if (!p7)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to calculate PKCS7 signature: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
sigsz = i2d_PKCS7(p7, &sig);
|
||||
if (sigsz < 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert PKCS7 signature to DER: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
*ret_signature = TAKE_PTR(sig);
|
||||
*ret_signature_size = sigsz;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "openssl is not supported, cannot setup verity signature: %m");
|
||||
#endif
|
||||
}
|
||||
|
||||
static int context_verity_sig(Context *context) {
|
||||
int fd = -1, r;
|
||||
|
||||
assert(context);
|
||||
|
||||
LIST_FOREACH(partitions, p, context->partitions) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||
_cleanup_free_ uint8_t *sig = NULL;
|
||||
_cleanup_free_ char *text = NULL;
|
||||
Partition *hp;
|
||||
uint8_t fp[X509_FINGERPRINT_SIZE];
|
||||
size_t sigsz, padsz;
|
||||
|
||||
if (p->dropped)
|
||||
continue;
|
||||
|
||||
if (PARTITION_EXISTS(p))
|
||||
continue;
|
||||
|
||||
if (p->verity != VERITY_SIG)
|
||||
continue;
|
||||
|
||||
assert_se(hp = p->siblings[VERITY_HASH]);
|
||||
assert(!hp->dropped);
|
||||
|
||||
assert(arg_certificate);
|
||||
|
||||
if (fd < 0)
|
||||
assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
|
||||
|
||||
r = sign_verity_roothash(hp->roothash, hp->roothash_size, &sig, &sigsz);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = x509_fingerprint(arg_certificate, fp);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Unable to calculate X509 certificate fingerprint: %m");
|
||||
|
||||
r = json_build(&v,
|
||||
JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR("rootHash", JSON_BUILD_HEX(hp->roothash, hp->roothash_size)),
|
||||
JSON_BUILD_PAIR(
|
||||
"certificateFingerprint",
|
||||
JSON_BUILD_HEX(fp, sizeof(fp))
|
||||
),
|
||||
JSON_BUILD_PAIR("signature", JSON_BUILD_BASE64(sig, sigsz))
|
||||
)
|
||||
);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to build JSON object: %m");
|
||||
|
||||
r = json_variant_format(v, 0, &text);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to format JSON object: %m");
|
||||
|
||||
padsz = round_up_size(strlen(text), 4096);
|
||||
assert_se(padsz <= p->new_size);
|
||||
|
||||
r = strgrowpad0(&text, padsz);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to pad string to %s", FORMAT_BYTES(padsz));
|
||||
|
||||
if (lseek(fd, p->offset, SEEK_SET) == (off_t) -1)
|
||||
return log_error_errno(errno, "Failed to seek to partition offset: %m");
|
||||
|
||||
r = loop_write(fd, text, padsz, /*do_poll=*/ false);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write verity signature to partition: %m");
|
||||
|
||||
if (fsync(fd) < 0)
|
||||
return log_error_errno(errno, "Failed to synchronize verity signature JSON: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int partition_acquire_uuid(Context *context, Partition *p, sd_id128_t *ret) {
|
||||
struct {
|
||||
sd_id128_t type_uuid;
|
||||
@ -3787,7 +3995,7 @@ static int context_acquire_partition_uuids_and_labels(Context *context) {
|
||||
|
||||
if (!sd_id128_is_null(p->current_uuid))
|
||||
p->new_uuid = p->current_uuid; /* Never change initialized UUIDs */
|
||||
else if (!p->new_uuid_is_set && p->verity == VERITY_OFF) {
|
||||
else if (!p->new_uuid_is_set && !IN_SET(p->verity, VERITY_DATA, VERITY_HASH)) {
|
||||
/* Not explicitly set by user! */
|
||||
r = partition_acquire_uuid(context, p, &p->new_uuid);
|
||||
if (r < 0)
|
||||
@ -4205,6 +4413,10 @@ static int context_write_partition_table(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = context_verity_sig(context);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = context_mangle_partitions(context);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -4747,6 +4959,10 @@ static int help(void) {
|
||||
" --image=PATH Operate relative to image file\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"
|
||||
" --certificate=PATH PEM certificate to use when generating verity\n"
|
||||
" roothash signatures\n"
|
||||
" --tpm2-device=PATH Path to TPM2 device node to use\n"
|
||||
" --tpm2-pcrs=PCR1+PCR2+PCR3+…\n"
|
||||
" TPM2 PCR indexes to use for TPM2 enrollment\n"
|
||||
@ -4787,6 +5003,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_SIZE,
|
||||
ARG_JSON,
|
||||
ARG_KEY_FILE,
|
||||
ARG_PRIVATE_KEY,
|
||||
ARG_CERTIFICATE,
|
||||
ARG_TPM2_DEVICE,
|
||||
ARG_TPM2_PCRS,
|
||||
ARG_TPM2_PUBLIC_KEY,
|
||||
@ -4812,6 +5030,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "size", required_argument, NULL, ARG_SIZE },
|
||||
{ "json", required_argument, NULL, ARG_JSON },
|
||||
{ "key-file", required_argument, NULL, ARG_KEY_FILE },
|
||||
{ "private-key", required_argument, NULL, ARG_PRIVATE_KEY },
|
||||
{ "certificate", required_argument, NULL, ARG_CERTIFICATE },
|
||||
{ "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE },
|
||||
{ "tpm2-pcrs", required_argument, NULL, ARG_TPM2_PCRS },
|
||||
{ "tpm2-public-key", required_argument, NULL, ARG_TPM2_PUBLIC_KEY },
|
||||
@ -4985,6 +5205,46 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_PRIVATE_KEY: {
|
||||
_cleanup_(erase_and_freep) char *k = NULL;
|
||||
size_t n = 0;
|
||||
|
||||
r = read_full_file_full(
|
||||
AT_FDCWD, optarg, UINT64_MAX, SIZE_MAX,
|
||||
READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
|
||||
NULL,
|
||||
&k, &n);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read key file '%s': %m", optarg);
|
||||
|
||||
EVP_PKEY_free(arg_private_key);
|
||||
arg_private_key = NULL;
|
||||
r = parse_private_key(k, n, &arg_private_key);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_CERTIFICATE: {
|
||||
_cleanup_free_ char *cert = NULL;
|
||||
size_t n = 0;
|
||||
|
||||
r = read_full_file_full(
|
||||
AT_FDCWD, optarg, UINT64_MAX, SIZE_MAX,
|
||||
READ_FULL_FILE_CONNECT_SOCKET,
|
||||
NULL,
|
||||
&cert, &n);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read certificate file '%s': %m", optarg);
|
||||
|
||||
X509_free(arg_certificate);
|
||||
arg_certificate = NULL;
|
||||
r = parse_x509_certificate(cert, n, &arg_certificate);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_TPM2_DEVICE: {
|
||||
_cleanup_free_ char *device = NULL;
|
||||
|
||||
|
@ -10,6 +10,9 @@ TEST_DESCRIPTION="test systemd-repart"
|
||||
test_append_files() {
|
||||
if ! get_bool "${TEST_NO_QEMU:=}"; then
|
||||
install_dmevent
|
||||
if command -v openssl >/dev/null 2>&1; then
|
||||
inst_binary openssl
|
||||
fi
|
||||
instmods dm_verity =md
|
||||
generate_module_dependencies
|
||||
fi
|
||||
|
@ -726,17 +726,47 @@ Verity=hash
|
||||
VerityMatchKey=root
|
||||
EOF
|
||||
|
||||
cat >"$defs/verity-sig.conf" <<EOF
|
||||
[Partition]
|
||||
Type=root-${architecture}-verity-sig
|
||||
Verity=signature
|
||||
VerityMatchKey=root
|
||||
EOF
|
||||
|
||||
# Unfortunately OpenSSL insists on reading some config file, hence provide one with mostly placeholder contents
|
||||
cat >> "$defs/verity.openssl.cnf" <<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 "$defs/verity.openssl.cnf" -new -x509 -newkey rsa:1024 -keyout "$defs/verity.key" -out "$defs/verity.crt" -days 365 -nodes
|
||||
|
||||
mkdir -p /run/verity.d
|
||||
ln -s "$defs/verity.crt" /run/verity.d/ok.crt
|
||||
|
||||
output=$(systemd-repart --definitions="$defs" \
|
||||
--seed="$seed" \
|
||||
--dry-run=no \
|
||||
--empty=create \
|
||||
--size=auto \
|
||||
--json=pretty \
|
||||
--private-key="$defs/verity.key" \
|
||||
--certificate="$defs/verity.crt" \
|
||||
"$imgs/verity")
|
||||
|
||||
roothash=$(jq -r ".[] | select(.type == \"root-${architecture}-verity\") | .roothash" <<< "$output")
|
||||
|
||||
# Check that we can dissect, mount and unmount a repart verity image.
|
||||
# Check that we can dissect, mount and unmount a repart verity image.
|
||||
|
||||
systemd-dissect "$imgs/verity" --root-hash "$roothash"
|
||||
systemd-dissect "$imgs/verity" --root-hash "$roothash" -M "$imgs/mnt"
|
||||
|
Loading…
x
Reference in New Issue
Block a user