diff --git a/lib/integrity/integrity.c b/lib/integrity/integrity.c index 0def1b57..017a4c9d 100644 --- a/lib/integrity/integrity.c +++ b/lib/integrity/integrity.c @@ -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, diff --git a/lib/integrity/integrity.h b/lib/integrity/integrity.h index e95686b6..64d091ca 100644 --- a/lib/integrity/integrity.h +++ b/lib/integrity/integrity.h @@ -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, diff --git a/lib/setup.c b/lib/setup.c index d8e44824..fb79eb11 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -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; diff --git a/src/integritysetup.c b/src/integritysetup.c index 28509ecc..77f9f953 100644 --- a/src/integritysetup.c +++ b/src/integritysetup.c @@ -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, ¶ms2)) + 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."), diff --git a/tests/integrity-compat-test b/tests/integrity-compat-test index b87141d9..8607e854 100755 --- a/tests/integrity-compat-test +++ b/tests/integrity-compat-test @@ -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