Calculate hash integrity size instead of requiring an explicit tag size.

When integritysetup formats a device with hash or HMAC integrity checksums,
it requires explicitly tag size entry from a user (or default value).

This leads to confusion and shortened tags.

This patch calculates tag size according to real hash output, and
if tag size is specified, it warns if these values differ.

Fixes: #492.
This commit is contained in:
Milan Broz
2019-11-28 22:20:08 +01:00
parent d9d39f1812
commit a0e87c9420
5 changed files with 90 additions and 53 deletions

View File

@@ -142,6 +142,27 @@ int INTEGRITY_key_size(struct crypt_device *cd, const char *integrity)
return -EINVAL;
}
/* Return hash or hmac(hash) size, if known */
int INTEGRITY_hash_tag_size(const char *integrity)
{
char hash[MAX_CIPHER_LEN];
int r;
if (!integrity)
return 0;
if (!strcmp(integrity, "crc32") || !strcmp(integrity, "crc32c"))
return 4;
r = sscanf(integrity, "hmac(%" MAX_CIPHER_LEN_STR "[^)]s", hash);
if (r == 1)
r = crypt_hash_size(hash);
else
r = crypt_hash_size(integrity);
return r < 0 ? 0 : r;
}
int INTEGRITY_tag_size(struct crypt_device *cd,
const char *integrity,
const char *cipher,

View File

@@ -70,6 +70,7 @@ int INTEGRITY_tag_size(struct crypt_device *cd,
const char *integrity,
const char *cipher,
const char *cipher_mode);
int INTEGRITY_hash_tag_size(const char *integrity);
int INTEGRITY_format(struct crypt_device *cd,
const struct crypt_params_integrity *params,

View File

@@ -2136,7 +2136,7 @@ static int _crypt_format_integrity(struct crypt_device *cd,
const char *uuid,
struct crypt_params_integrity *params)
{
int r;
int r, integrity_tag_size;
char *integrity = NULL, *journal_integrity = NULL, *journal_crypt = NULL;
struct volume_key *journal_crypt_key = NULL, *journal_mac_key = NULL;
@@ -2193,6 +2193,14 @@ static int _crypt_format_integrity(struct crypt_device *cd,
goto err;
}
integrity_tag_size = INTEGRITY_hash_tag_size(integrity);
if (integrity_tag_size > 0 && params->tag_size && integrity_tag_size != params->tag_size)
log_std(cd, _("WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"),
params->tag_size, integrity, integrity_tag_size);
if (params->tag_size)
integrity_tag_size = params->tag_size;
cd->u.integrity.journal_crypt_key = journal_crypt_key;
cd->u.integrity.journal_mac_key = journal_mac_key;
cd->u.integrity.params.journal_size = params->journal_size;
@@ -2201,7 +2209,7 @@ static int _crypt_format_integrity(struct crypt_device *cd,
cd->u.integrity.params.interleave_sectors = params->interleave_sectors;
cd->u.integrity.params.buffer_sectors = params->buffer_sectors;
cd->u.integrity.params.sector_size = params->sector_size;
cd->u.integrity.params.tag_size = params->tag_size;
cd->u.integrity.params.tag_size = integrity_tag_size;
cd->u.integrity.params.integrity = integrity;
cd->u.integrity.params.journal_integrity = journal_integrity;
cd->u.integrity.params.journal_crypt = journal_crypt;

View File

@@ -24,7 +24,6 @@
#define PACKAGE_INTEGRITY "integritysetup"
#define DEFAULT_TAG_SIZE 4
#define DEFAULT_ALG_NAME "crc32c"
#define MAX_KEY_SIZE 4096
@@ -183,7 +182,7 @@ static int action_format(int arg)
.buffer_sectors = opt_buffer_sectors,
.tag_size = opt_tag_size,
.sector_size = opt_sector_size ?: SECTOR_SIZE,
};
}, params2;
char integrity[MAX_CIPHER_LEN], journal_integrity[MAX_CIPHER_LEN], journal_crypt[MAX_CIPHER_LEN];
char *integrity_key = NULL, *msg = NULL;
int r;
@@ -250,8 +249,9 @@ static int action_format(int arg)
if (r < 0) /* FIXME: call wipe signatures again */
goto out;
if (!opt_batch_mode)
log_std(_("Formatted with tag size %u, internal integrity %s.\n"), opt_tag_size, opt_integrity);
if (!opt_batch_mode && !crypt_get_integrity_info(cd, &params2))
log_std(_("Formatted with tag size %u, internal integrity %s.\n"),
params2.tag_size, params2.integrity);
if (!opt_no_wipe)
r = _wipe_data_device(cd, integrity_key);
@@ -499,8 +499,7 @@ static void help(poptContext popt_context,
crypt_get_dir());
log_std(_("\nDefault compiled-in dm-integrity parameters:\n"
"\tTag size: %u bytes, Checksum algorithm: %s\n"),
DEFAULT_TAG_SIZE, DEFAULT_ALG_NAME);
"\tChecksum algorithm: %s\n"), DEFAULT_ALG_NAME);
poptFreeContext(popt_context);
exit(EXIT_SUCCESS);
} else if (key->shortName == 'V') {
@@ -637,9 +636,6 @@ int main(int argc, const char **argv)
poptGetInvocationName(popt_context));
}
if (!strcmp(aname, "format") && opt_tag_size == 0)
opt_tag_size = DEFAULT_TAG_SIZE;
if (opt_integrity_recalculate && strcmp(aname, "open"))
usage(popt_context, EXIT_FAILURE,
_("Option --integrity-recalculate can be used only for open action."),

View File

@@ -141,53 +141,64 @@ int_check_sum() # alg checksum [keyfile keysize]
int_check_sum_only $2
}
intformat() # alg alg_out tagsize sector_size csum [keyfile keysize]
intformat() # alg alg_out tagsize outtagsize sector_size csum [keyfile keysize]
{
if [ -n "$7" ] ; then
KEY_PARAMS="--integrity-key-file $6 --integrity-key-size $7"
if [ -n "$8" ] ; then
KEY_PARAMS="--integrity-key-file $7 --integrity-key-size $8"
else
KEY_PARAMS=""
fi
echo -n "[INTEGRITY:$2:$3:$4]"
if [ $3 -ne 0 ] ; then
TAG_PARAMS="--tag-size $3"
else
TAG_PARAMS=""
fi
echo -n "[INTEGRITY:$2:$4:$5]"
echo -n "[FORMAT]"
$INTSETUP format --integrity-legacy-padding -q --integrity $1 --tag-size $3 --sector-size $4 $KEY_PARAMS $DEV || fail "Cannot format device."
dump_check "tag_size" $3
dump_check "sector_size" $4
$INTSETUP format --integrity-legacy-padding -q --integrity $1 $TAG_PARAMS --sector-size $5 $KEY_PARAMS $DEV >/dev/null || fail "Cannot format device."
dump_check "tag_size" $4
dump_check "sector_size" $5
echo -n "[ACTIVATE]"
$INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS || fail "Cannot activate device."
status_check "tag size" $3
status_check "tag size" $4
status_check "integrity" $2
status_check "sector size" "$4 bytes"
int_check_sum $1 $5 $6 $7
status_check "sector size" "$5 bytes"
int_check_sum $1 $6 $7 $8
echo -n "[REMOVE]"
$INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
echo "[OK]"
}
int_error_detection() # mode alg tagsize sector_size key_file key_size
int_error_detection() # mode alg tagsize outtagsize sector_size key_file key_size
{
if [ "$1" == "B" ] ; then
INT_MODE="-B"
else
INT_MODE=""
fi
if [ -n "$6" ] ; then
KEY_PARAMS="--integrity-key-file $5 --integrity-key-size $6"
if [ -n "$7" ] ; then
KEY_PARAMS="--integrity-key-file $6 --integrity-key-size $7"
else
KEY_PARAMS=""
fi
if [ $3 -ne 0 ] ; then
TAG_PARAMS="--tag-size $3"
else
TAG_PARAMS=""
fi
dd if=/dev/zero of=$DEV bs=1M count=32 >/dev/null 2>&1
echo -n "[INTEGRITY:$1:$2:$3:$4]"
echo -n "[INTEGRITY:$1:$2:$4:$5]"
echo -n "[FORMAT]"
$INTSETUP format -q --integrity $2 --tag-size $3 --sector-size $4 $KEY_PARAMS $DEV $INT_MODE || fail "Cannot format device."
$INTSETUP format -q --integrity $2 $TAG_PARAMS --sector-size $5 $KEY_PARAMS $DEV $INT_MODE >/dev/null || fail "Cannot format device."
echo -n "[ACTIVATE]"
$INTSETUP open $DEV $DEV_NAME --integrity $2 --integrity-no-journal $KEY_PARAMS $INT_MODE || fail "Cannot activate device."
if [ -n "$5" -a -n "$6" ]; then
if [ -n "$6" -a -n "$7" ]; then
echo -n "[KEYED HASH]"
KEY_HEX=$(xxd -c 256 -l $6 -p $5)
KEY_HEX=$(xxd -c 256 -l $7 -p $6)
[ -z "$KEY_HEX" ] && fail "Cannot decode key."
dmsetup table --showkeys $DEV_NAME | grep -q $KEY_HEX || fail "Key mismatch."
fi
@@ -305,29 +316,29 @@ modprobe dm-integrity >/dev/null 2>&1
dm_integrity_features
add_device
intformat crc32c crc32c 4 512 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7
intformat crc32 crc32 4 512 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7
intformat sha1 sha1 20 512 6eedd6344dab8875cd185fcd6565dfc869ab36bc57e577f40c685290b1fa7fe7
intformat sha1 sha1 16 4096 e152ec88227b539cd9cafd8bdb587a1072d720cd6bcebe1398d4136c9e7f337b
intformat sha256 sha256 32 512 8e5fe4119558e117bfc40e3b0f13ade3abe497b52604d4c7cca0cfd6c7f4cf11
intformat hmac-sha256 hmac\(sha256\) 32 512 8e5fe4119558e117bfc40e3b0f13ade3abe497b52604d4c7cca0cfd6c7f4cf11 $KEY_FILE 32
intformat sha256 sha256 32 4096 33f7dfa5163ca9f740383fb8b0919574e38a7b20a94a4170fde4238196b7c4b4
intformat hmac-sha256 hmac\(sha256\) 32 4096 33f7dfa5163ca9f740383fb8b0919574e38a7b20a94a4170fde4238196b7c4b4 $KEY_FILE 32
intformat crc32c crc32c 0 4 512 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7
intformat crc32 crc32 0 4 512 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7
intformat sha1 sha1 0 20 512 6eedd6344dab8875cd185fcd6565dfc869ab36bc57e577f40c685290b1fa7fe7
intformat sha1 sha1 16 16 4096 e152ec88227b539cd9cafd8bdb587a1072d720cd6bcebe1398d4136c9e7f337b
intformat sha256 sha256 0 32 512 8e5fe4119558e117bfc40e3b0f13ade3abe497b52604d4c7cca0cfd6c7f4cf11
intformat hmac-sha256 hmac\(sha256\) 0 32 512 8e5fe4119558e117bfc40e3b0f13ade3abe497b52604d4c7cca0cfd6c7f4cf11 $KEY_FILE 32
intformat sha256 sha256 0 32 4096 33f7dfa5163ca9f740383fb8b0919574e38a7b20a94a4170fde4238196b7c4b4
intformat hmac-sha256 hmac\(sha256\) 0 32 4096 33f7dfa5163ca9f740383fb8b0919574e38a7b20a94a4170fde4238196b7c4b4 $KEY_FILE 32
echo "Error detection tests:"
int_error_detection J crc32c 4 512
int_error_detection J crc32c 4 4096
int_error_detection J crc32 4 512
int_error_detection J crc32 4 4096
int_error_detection J sha1 20 512
int_error_detection J sha1 16 512
int_error_detection J sha1 20 4096
int_error_detection J sha256 32 512
int_error_detection J sha256 32 4096
int_error_detection J crc32c 0 4 512
int_error_detection J crc32c 0 4 4096
int_error_detection J crc32 0 4 512
int_error_detection J crc32 0 4 4096
int_error_detection J sha1 0 20 512
int_error_detection J sha1 16 16 512
int_error_detection J sha1 0 20 4096
int_error_detection J sha256 0 32 512
int_error_detection J sha256 0 32 4096
which xxd >/dev/null 2>&1 || skip "WARNING: xxd tool required."
int_error_detection J hmac-sha256 32 512 $KEY_FILE 32
int_error_detection J hmac-sha256 32 4096 $KEY_FILE 32
int_error_detection J hmac-sha256 0 32 512 $KEY_FILE 32
int_error_detection J hmac-sha256 0 32 4096 $KEY_FILE 32
echo "Journal parameters tests:"
# Watermark is calculated in kernel, so it can be rounded down/up
@@ -385,12 +396,12 @@ if [ -n "$DM_INTEGRITY_BITMAP" ] ; then
$INTSETUP close $DEV_NAME fail "Cannot deactivate device."
echo "[OK]"
echo "Bitmap error detection tests:"
int_error_detection B crc32c 4 512
int_error_detection B crc32c 4 4096
int_error_detection B sha256 32 512
int_error_detection B sha256 32 4096
int_error_detection B hmac-sha256 32 512 $KEY_FILE 32
int_error_detection B hmac-sha256 32 4096 $KEY_FILE 32
int_error_detection B crc32c 0 4 512
int_error_detection B crc32c 0 4 4096
int_error_detection B sha256 0 32 512
int_error_detection B sha256 0 32 4096
int_error_detection B hmac-sha256 0 32 512 $KEY_FILE 32
int_error_detection B hmac-sha256 0 32 4096 $KEY_FILE 32
else
echo "[N/A]"
fi