Introduce 'fixate-volume-key' option to repart/cryptsetup to pin the exact LUKS volume key hash (#40343)
Add an option to generate the expected volume key hash for LUKS volumes by systemd-repart and put it to crypttab, make systemd-cryptsetup check it upon attaching. The format of the hash matches what's currently being measured to TPM2 PCR with tpm2-measure-pcr=. Closes #40123
This commit is contained in:
@@ -1012,6 +1012,26 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>fixate-volume-key=</option></term>
|
||||
|
||||
<listitem><para>Pin the expected hash of the volume key.</para>
|
||||
|
||||
<para>In certain cases, e.g. for LUKS volumes where the key is sealed to the TPM2, this may be required
|
||||
to provide a guarantee that the volume being attached is the volume which was previously created.
|
||||
<option>fixate-volume-key=</option> can be used to set the expected volume key hash and refuse to attach the volume
|
||||
if it has a different one. The expected hash matches the digest which is measured to the sha256 PCR bank of the
|
||||
TPM2 when <option>tpm2-measure-pcr=</option> is used.</para>
|
||||
|
||||
<para>For newly created LUKS volumes, the expected hash can be generated by
|
||||
<citerefentry><refentrytitle>systemd-repart</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
|
||||
For additional details, see the <option>EncryptedVolume=</option> description at
|
||||
<citerefentry><refentrytitle>repart.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v260"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
<para>At early boot and when the system manager configuration is
|
||||
@@ -1121,6 +1141,8 @@ external /dev/sda3 keyfile:LABEL=keydev keyfile-timeout=10s,cipher=xchac
|
||||
<member><citerefentry><refentrytitle>systemd-cryptsetup@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>systemd-cryptsetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>systemd-cryptenroll</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>systemd-repart</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>repart.d</refentrytitle><manvolnum>5</manvolnum></citerefentry></member>
|
||||
<member><citerefentry project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry></member>
|
||||
<member><citerefentry project='die-net'><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
|
||||
<member><citerefentry project='man-pages'><refentrytitle>mkswap</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
|
||||
|
||||
+7
-2
@@ -869,13 +869,18 @@
|
||||
<term><varname>EncryptedVolume=</varname></term>
|
||||
|
||||
<listitem><para>Specifies how the encrypted partition should be set up. Takes at least one and at most
|
||||
three fields separated with a colon (<literal>:</literal>). The first field specifies the encrypted
|
||||
four fields separated with a colon (<literal>:</literal>). The first field specifies the encrypted
|
||||
volume name under <filename>/dev/mapper/</filename>. If not specified, <literal>luks-UUID</literal>
|
||||
will be used where <literal>UUID</literal> is the LUKS UUID. The second field specifies the keyfile
|
||||
to use following the same format as specified in crypttab. The third field specifies a
|
||||
comma-delimited list of crypttab options. These fields correspond to the first, third and fourth
|
||||
comma-delimited list of crypttab options. These three fields correspond to the first, third and fourth
|
||||
column of the
|
||||
<citerefentry><refentrytitle>crypttab</refentrytitle><manvolnum>5</manvolnum></citerefentry> format.
|
||||
The fourth field contains extra options, which are not directly reflected to crypttab options. Currently,
|
||||
the only supported extra option is <varname>fixate-volume-key</varname>. When specified, the volume key
|
||||
hash will be taken upon LUKS volume formatting and the result will be added to the list of crypttab options,
|
||||
i.e. <varname>fixate-volume-key=expected-hash</varname> will be added to the fourth column of the generated
|
||||
crypttab.
|
||||
</para>
|
||||
|
||||
<para>Note that this setting is only taken into account when <option>--generate-crypttab=</option>
|
||||
|
||||
+52
-15
@@ -126,6 +126,7 @@ static char *arg_tpm2_measure_keyslot_nvpcr = NULL;
|
||||
static char *arg_link_keyring = NULL;
|
||||
static char *arg_link_key_type = NULL;
|
||||
static char *arg_link_key_description = NULL;
|
||||
static char *arg_fixate_volume_key = NULL;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_cipher, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_hash, freep);
|
||||
@@ -143,6 +144,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_tpm2_pcrlock, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_link_keyring, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_link_key_type, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_link_key_description, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_fixate_volume_key, freep);
|
||||
|
||||
static const char* const passphrase_type_table[_PASSPHRASE_TYPE_MAX] = {
|
||||
[PASSPHRASE_REGULAR] = "passphrase",
|
||||
@@ -651,6 +653,11 @@ static int parse_one_option(const char *option) {
|
||||
#else
|
||||
log_error("Build lacks libcryptsetup support for linking volume keys in user specified kernel keyrings upon device activation, ignoring: %s", option);
|
||||
#endif
|
||||
} else if ((val = startswith(option, "fixate-volume-key="))) {
|
||||
r = free_and_strdup(&arg_fixate_volume_key, val);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
} else if (!streq(option, "x-initrd.attach"))
|
||||
log_warning("Encountered unknown /etc/crypttab option '%s', ignoring.", option);
|
||||
|
||||
@@ -1050,24 +1057,29 @@ static int measure_volume_key(
|
||||
* unprotected direct hash of the secret volume key over the wire to the TPM. Hence let's instead
|
||||
* send a HMAC signature instead. */
|
||||
|
||||
_cleanup_free_ char *escaped = NULL;
|
||||
escaped = xescape(name, ":"); /* avoid ambiguity around ":" once we join things below */
|
||||
if (!escaped)
|
||||
return log_oom();
|
||||
_cleanup_free_ char *prefix = NULL;
|
||||
|
||||
_cleanup_free_ char *s = NULL;
|
||||
s = strjoin("cryptsetup:", escaped, ":", strempty(crypt_get_uuid(cd)));
|
||||
if (!s)
|
||||
return log_oom();
|
||||
/* Note: what is extended to the SHA256 bank here must match the expected hash of 'fixate-volume-key='
|
||||
* calculated by cryptsetup_get_volume_key_id(). */
|
||||
r = cryptsetup_get_volume_key_prefix(cd, name, &prefix);
|
||||
if (r)
|
||||
return log_error_errno(r, "Could not verify pcr banks: %m");
|
||||
|
||||
r = tpm2_pcr_extend_bytes(c, l ?: arg_tpm2_measure_banks, arg_tpm2_measure_pcr, &IOVEC_MAKE_STRING(s), &IOVEC_MAKE(volume_key, volume_key_size), TPM2_EVENT_VOLUME_KEY, s);
|
||||
r = tpm2_pcr_extend_bytes(
|
||||
c,
|
||||
/* banks= */ l ?: arg_tpm2_measure_banks,
|
||||
/* pcr_index = */ arg_tpm2_measure_pcr,
|
||||
/* data = */ &IOVEC_MAKE_STRING(prefix),
|
||||
/* secret = */ &IOVEC_MAKE(volume_key, volume_key_size),
|
||||
/* event_type = */ TPM2_EVENT_VOLUME_KEY,
|
||||
/* description = */ prefix);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not extend PCR: %m");
|
||||
|
||||
log_struct(LOG_INFO,
|
||||
LOG_MESSAGE_ID(SD_MESSAGE_TPM_PCR_EXTEND_STR),
|
||||
LOG_MESSAGE("Successfully extended PCR index %u with '%s' and volume key (banks %s).", arg_tpm2_measure_pcr, s, joined),
|
||||
LOG_ITEM("MEASURING=%s", s),
|
||||
LOG_MESSAGE("Successfully extended PCR index %u with '%s' and volume key (banks %s).", arg_tpm2_measure_pcr, prefix, joined),
|
||||
LOG_ITEM("MEASURING=%s", prefix),
|
||||
LOG_ITEM("PCR=%u", arg_tpm2_measure_pcr),
|
||||
LOG_ITEM("BANKS=%s", joined));
|
||||
|
||||
@@ -1173,12 +1185,36 @@ static int measured_crypt_activate_by_volume_key(
|
||||
|
||||
/* A wrapper around crypt_activate_by_volume_key() which also measures to a PCR if that's requested. */
|
||||
|
||||
/* First, check if volume key digest matches the expectation. */
|
||||
if (arg_fixate_volume_key) {
|
||||
_cleanup_free_ char *key_id = NULL;
|
||||
|
||||
r = cryptsetup_get_volume_key_id(
|
||||
cd,
|
||||
/* volume_name= */ name,
|
||||
/* volume_key= */ volume_key,
|
||||
/* volume_key_size= */ volume_key_size,
|
||||
/* ret= */ &key_id);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get volume key id.");
|
||||
|
||||
if (!streq(arg_fixate_volume_key, key_id))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Volume key id: '%s' does not match the expectation: '%s'.",
|
||||
key_id, arg_fixate_volume_key);
|
||||
}
|
||||
|
||||
r = crypt_activate_by_volume_key(cd, name, volume_key, volume_key_size, flags);
|
||||
if (r == -EEXIST) /* volume is already active */
|
||||
return log_external_activation(r, name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (arg_tpm2_measure_pcr == UINT_MAX) {
|
||||
log_debug("Not measuring volume key, deactivated.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (volume_key_size > 0)
|
||||
(void) measure_volume_key(cd, name, volume_key, volume_key_size); /* OK if fails */
|
||||
else
|
||||
@@ -1204,14 +1240,12 @@ static int measured_crypt_activate_by_passphrase(
|
||||
assert(cd);
|
||||
|
||||
/* A wrapper around crypt_activate_by_passphrase() which also measures to a PCR if that's
|
||||
* requested. Note that we need the volume key for the measurement, and
|
||||
* requested. Note that we may need the volume key for the measurement and/or for the comparison, and
|
||||
* crypt_activate_by_passphrase() doesn't give us access to this. Hence, we operate indirectly, and
|
||||
* retrieve the volume key first, and then activate through that. */
|
||||
|
||||
if (arg_tpm2_measure_pcr == UINT_MAX) {
|
||||
log_debug("Not measuring volume key, deactivated.");
|
||||
if (arg_tpm2_measure_pcr == UINT_MAX && !arg_fixate_volume_key)
|
||||
goto shortcut;
|
||||
}
|
||||
|
||||
r = crypt_get_volume_key_size(cd);
|
||||
if (r < 0)
|
||||
@@ -1453,6 +1487,9 @@ static bool use_token_plugins(void) {
|
||||
return false;
|
||||
if (arg_tpm2_measure_keyslot_nvpcr)
|
||||
return false;
|
||||
/* Volume key is also needed if the expected key id is set */
|
||||
if (arg_fixate_volume_key)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
/* Disable tokens if we're in FIDO2 mode with manual parameters. */
|
||||
|
||||
+69
-10
@@ -318,6 +318,7 @@ typedef struct PartitionEncryptedVolume {
|
||||
char *name;
|
||||
char *keyfile;
|
||||
char *options;
|
||||
bool fixate_volume_key;
|
||||
} PartitionEncryptedVolume;
|
||||
|
||||
static PartitionEncryptedVolume* partition_encrypted_volume_free(PartitionEncryptedVolume *c) {
|
||||
@@ -2547,7 +2548,8 @@ static int config_parse_encrypted_volume(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_free_ char *volume = NULL, *keyfile = NULL, *options = NULL;
|
||||
_cleanup_free_ char *volume = NULL, *keyfile = NULL, *options = NULL, *extra = NULL;
|
||||
bool fixate_volume_key = false;
|
||||
Partition *p = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
@@ -2558,7 +2560,7 @@ static int config_parse_encrypted_volume(
|
||||
|
||||
const char *q = rvalue;
|
||||
r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_DONT_COALESCE_SEPARATORS|EXTRACT_UNQUOTE,
|
||||
&volume, &keyfile, &options);
|
||||
&volume, &keyfile, &options, &extra);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0) {
|
||||
@@ -2589,10 +2591,29 @@ static int config_parse_encrypted_volume(
|
||||
if (!p->encrypted_volume)
|
||||
return log_oom();
|
||||
|
||||
for (const char *e = extra;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
|
||||
r = extract_first_word(&e, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS | EXTRACT_UNESCAPE_SEPARATORS);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Failed to parse extra options '%s', ignoring", word);
|
||||
break;
|
||||
}
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (streq(word, "fixate-volume-key"))
|
||||
fixate_volume_key = true;
|
||||
else
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown extra option '%s', ignoring", word);
|
||||
}
|
||||
|
||||
*p->encrypted_volume = (PartitionEncryptedVolume) {
|
||||
.name = TAKE_PTR(volume),
|
||||
.keyfile = TAKE_PTR(keyfile),
|
||||
.options = TAKE_PTR(options),
|
||||
.fixate_volume_key = fixate_volume_key,
|
||||
};
|
||||
|
||||
return 0;
|
||||
@@ -5174,6 +5195,44 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to LUKS2 format future partition: %m");
|
||||
|
||||
if (p->encrypted_volume && p->encrypted_volume->fixate_volume_key) {
|
||||
_cleanup_free_ char *key_id = NULL, *hash_option = NULL;
|
||||
|
||||
r = sym_crypt_get_volume_key_size(cd);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine volume key size: %m");
|
||||
if (r == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume key has zero size and 'fixate-volume-key' is used");
|
||||
|
||||
_cleanup_(iovec_done) struct iovec vk = {
|
||||
.iov_base = malloc(r),
|
||||
.iov_len = r,
|
||||
};
|
||||
|
||||
if (!vk.iov_base)
|
||||
return log_oom();
|
||||
|
||||
r = sym_crypt_volume_key_get(cd, CRYPT_ANY_SLOT, (char *) vk.iov_base, &vk.iov_len, NULL, 0);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get volume key: %m");
|
||||
|
||||
r = cryptsetup_get_volume_key_id(
|
||||
cd,
|
||||
/* volume_name= */ p->encrypted_volume->name,
|
||||
/* volume_key= */ vk.iov_base,
|
||||
/* volume_key_size= */ vk.iov_len,
|
||||
/* ret= */ &key_id);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get volume key hash: %m");
|
||||
|
||||
hash_option = strjoin("fixate-volume-key=", key_id);
|
||||
if (!hash_option)
|
||||
return log_oom();
|
||||
|
||||
if (!strextend_with_separator(&p->encrypted_volume->options, ",", hash_option))
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (IN_SET(p->encrypt, ENCRYPT_KEY_FILE, ENCRYPT_KEY_FILE_TPM2)) {
|
||||
/* Use partition-specific key if available, otherwise fall back to global key */
|
||||
struct iovec *iovec_key = arg_key.iov_base ? &arg_key : &p->key;
|
||||
@@ -10719,14 +10778,6 @@ static int run(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = context_fstab(context);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = context_crypttab(context);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = context_update_verity_size(context);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -10782,6 +10833,14 @@ static int run(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = context_fstab(context);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = context_crypttab(context);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) context_dump(context, /* late= */ true);
|
||||
|
||||
context_disarm_auto_removal(context);
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#include "alloc-util.h"
|
||||
#include "cryptsetup-util.h"
|
||||
#include "dlfcn-util.h"
|
||||
#include "escape.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "hmac.h"
|
||||
#include "log.h"
|
||||
#include "parse-util.h"
|
||||
#include "string-util.h"
|
||||
@@ -198,6 +201,64 @@ int cryptsetup_add_token_json(struct crypt_device *cd, sd_json_variant *v) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cryptsetup_get_volume_key_prefix(
|
||||
struct crypt_device *cd,
|
||||
const char *volume_name,
|
||||
char **ret) {
|
||||
|
||||
_cleanup_free_ char *volume = NULL;
|
||||
const char *uuid;
|
||||
char *s;
|
||||
|
||||
uuid = sym_crypt_get_uuid(cd);
|
||||
if (!uuid)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get LUKS UUID.");
|
||||
|
||||
if (volume_name)
|
||||
/* avoid ambiguity around ":" once we join things below */
|
||||
volume = xescape(volume_name, ":");
|
||||
else
|
||||
volume = strjoin("luks-", uuid);
|
||||
if (!volume)
|
||||
return log_oom_debug();
|
||||
|
||||
s = strjoin("cryptsetup:", volume, ":", uuid);
|
||||
if (!s)
|
||||
return log_oom_debug();
|
||||
|
||||
*ret = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The hash must match what measure_volume_key() extends to the SHA256 bank of the TPM2. */
|
||||
int cryptsetup_get_volume_key_id(
|
||||
struct crypt_device *cd,
|
||||
const char *volume_name,
|
||||
const void *volume_key,
|
||||
size_t volume_key_size,
|
||||
char **ret) {
|
||||
|
||||
_cleanup_free_ char *prefix = NULL;
|
||||
uint8_t digest[SHA256_DIGEST_SIZE];
|
||||
char *hex;
|
||||
int r;
|
||||
|
||||
r = cryptsetup_get_volume_key_prefix(cd, volume_name, &prefix);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to get LUKS volume key prefix.");
|
||||
|
||||
hmac_sha256(volume_key, volume_key_size, prefix, strlen(prefix), digest);
|
||||
|
||||
hex = hexmem(digest, sizeof(digest));
|
||||
if (!hex)
|
||||
return log_oom_debug();
|
||||
|
||||
*ret = hex;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int dlopen_cryptsetup(void) {
|
||||
|
||||
@@ -66,6 +66,9 @@ int cryptsetup_set_minimal_pbkdf(struct crypt_device *cd);
|
||||
|
||||
int cryptsetup_get_token_as_json(struct crypt_device *cd, int idx, const char *verify_type, sd_json_variant **ret);
|
||||
int cryptsetup_add_token_json(struct crypt_device *cd, sd_json_variant *v);
|
||||
int cryptsetup_get_volume_key_prefix(struct crypt_device *cd, const char *volume_name, char **ret);
|
||||
int cryptsetup_get_volume_key_id(struct crypt_device *cd, const char *volume_name, const void *volume_key,
|
||||
size_t volume_key_size, char **ret);
|
||||
#endif
|
||||
|
||||
int dlopen_cryptsetup(void);
|
||||
|
||||
@@ -151,7 +151,7 @@ typedef enum Tpm2UserspaceEventType {
|
||||
|
||||
DECLARE_STRING_TABLE_LOOKUP(tpm2_userspace_event_type, Tpm2UserspaceEventType);
|
||||
|
||||
int tpm2_pcr_extend_bytes(Tpm2Context *c, char **banks, unsigned pcr_index, const struct iovec *data, const struct iovec *secret, Tpm2UserspaceEventType event, const char *description);
|
||||
int tpm2_pcr_extend_bytes(Tpm2Context *c, char **banks, unsigned pcr_index, const struct iovec *data, const struct iovec *secret, Tpm2UserspaceEventType event_type, const char *description);
|
||||
int tpm2_nvpcr_get_index(const char *name, uint32_t *ret);
|
||||
int tpm2_nvpcr_extend_bytes(Tpm2Context *c, const Tpm2Handle *session, const char *name, const struct iovec *data, const struct iovec *secret, Tpm2UserspaceEventType event_type, const char *description);
|
||||
int tpm2_nvpcr_acquire_anchor_secret(struct iovec *ret, bool sync_secondary);
|
||||
|
||||
@@ -1942,6 +1942,61 @@ EOF
|
||||
cmp "$imgs/test1.img" "$imgs/test2.img"
|
||||
}
|
||||
|
||||
testcase_luks2_keyhash() {
|
||||
local defs imgs output root
|
||||
|
||||
defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
|
||||
imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
|
||||
root="$(mktemp --directory "/var/test-repart.root.XXXXXXXXXX")"
|
||||
# shellcheck disable=SC2064
|
||||
trap "rm -rf '$defs' '$imgs' '$root'" RETURN
|
||||
chmod 0755 "$defs"
|
||||
|
||||
echo "*** testcase for fixate-volume-key ***"
|
||||
|
||||
volume="test-repart-lukskeyhash-$RANDOM"
|
||||
|
||||
tee "$defs/root.conf" <<EOF
|
||||
[Partition]
|
||||
Type=linux-generic
|
||||
Format=ext4
|
||||
Encrypt=key-file
|
||||
EncryptedVolume=$volume:::fixate-volume-key
|
||||
EOF
|
||||
|
||||
systemd-repart --pretty=yes \
|
||||
--definitions "$defs" \
|
||||
--empty=create \
|
||||
--size=100M \
|
||||
--seed="$seed" \
|
||||
--dry-run=no \
|
||||
--offline="$OFFLINE" \
|
||||
--generate-crypttab="$imgs/crypttab" \
|
||||
"$imgs/enckeyhash.img"
|
||||
|
||||
loop="$(losetup -P --show --find "$imgs/enckeyhash.img")"
|
||||
udevadm wait --timeout=60 --settle "${loop:?}p1"
|
||||
|
||||
touch "$imgs/empty-password"
|
||||
|
||||
# Check that the volume can be attached with the correct hash
|
||||
expected_hash="$(grep UUID= "$imgs/crypttab" | sed s,.*fixate-volume-key=,,)"
|
||||
echo "Expected hash: $expected_hash"
|
||||
echo "Trying to attach the volume"
|
||||
systemd-cryptsetup attach $volume "${loop}p1" "$imgs/empty-password" "fixate-volume-key=$expected_hash"
|
||||
echo "Trying to detach the volume"
|
||||
systemd-cryptsetup detach $volume
|
||||
echo "Success!"
|
||||
|
||||
# Check that the volume cannot be attached with incorrect hash
|
||||
echo "Trying to attach the volume with wrong hash"
|
||||
systemd-cryptsetup attach $volume "${loop}p1" "$imgs/empty-password" "fixate-volume-key=aaaaaabbbbbbccccccddddddeeeeeeffffff1111112222223333334444445555" && exit 1
|
||||
# Verify the volume is not attached
|
||||
[ ! -f "/dev/mapper/$volume" ] || exit 1
|
||||
|
||||
losetup -d "$loop"
|
||||
}
|
||||
|
||||
OFFLINE="yes"
|
||||
run_testcases
|
||||
|
||||
|
||||
Reference in New Issue
Block a user