4040#define BITMAP_BLOCK_SIZE 4096 /* don't change it */
4141#define BITMAP_FLUSH_INTERVAL (10 * HZ)
4242#define DISCARD_FILLER 0xf6
43+ #define SALT_SIZE 16
4344
4445/*
4546 * Warning - DEBUG_PRINT prints security-sensitive data to the log,
5758#define SB_VERSION_2 2
5859#define SB_VERSION_3 3
5960#define SB_VERSION_4 4
61+ #define SB_VERSION_5 5
6062#define SB_SECTORS 8
6163#define MAX_SECTORS_PER_BLOCK 8
6264
@@ -72,12 +74,15 @@ struct superblock {
7274 __u8 log2_blocks_per_bitmap_bit ;
7375 __u8 pad [2 ];
7476 __u64 recalc_sector ;
77+ __u8 pad2 [8 ];
78+ __u8 salt [SALT_SIZE ];
7579};
7680
7781#define SB_FLAG_HAVE_JOURNAL_MAC 0x1
7882#define SB_FLAG_RECALCULATING 0x2
7983#define SB_FLAG_DIRTY_BITMAP 0x4
8084#define SB_FLAG_FIXED_PADDING 0x8
85+ #define SB_FLAG_FIXED_HMAC 0x10
8186
8287#define JOURNAL_ENTRY_ROUNDUP 8
8388
@@ -259,6 +264,7 @@ struct dm_integrity_c {
259264 bool recalculate_flag ;
260265 bool discard ;
261266 bool fix_padding ;
267+ bool fix_hmac ;
262268 bool legacy_recalculate ;
263269
264270 struct alg_spec internal_hash_alg ;
@@ -389,8 +395,11 @@ static int dm_integrity_failed(struct dm_integrity_c *ic)
389395
390396static bool dm_integrity_disable_recalculate (struct dm_integrity_c * ic )
391397{
392- if ((ic -> internal_hash_alg .key || ic -> journal_mac_alg .key ) &&
393- !ic -> legacy_recalculate )
398+ if (ic -> legacy_recalculate )
399+ return false;
400+ if (!(ic -> sb -> flags & cpu_to_le32 (SB_FLAG_FIXED_HMAC )) ?
401+ ic -> internal_hash_alg .key || ic -> journal_mac_alg .key :
402+ ic -> internal_hash_alg .key && !ic -> journal_mac_alg .key )
394403 return true;
395404 return false;
396405}
@@ -477,7 +486,9 @@ static void wraparound_section(struct dm_integrity_c *ic, unsigned *sec_ptr)
477486
478487static void sb_set_version (struct dm_integrity_c * ic )
479488{
480- if (ic -> sb -> flags & cpu_to_le32 (SB_FLAG_FIXED_PADDING ))
489+ if (ic -> sb -> flags & cpu_to_le32 (SB_FLAG_FIXED_HMAC ))
490+ ic -> sb -> version = SB_VERSION_5 ;
491+ else if (ic -> sb -> flags & cpu_to_le32 (SB_FLAG_FIXED_PADDING ))
481492 ic -> sb -> version = SB_VERSION_4 ;
482493 else if (ic -> mode == 'B' || ic -> sb -> flags & cpu_to_le32 (SB_FLAG_DIRTY_BITMAP ))
483494 ic -> sb -> version = SB_VERSION_3 ;
@@ -487,10 +498,58 @@ static void sb_set_version(struct dm_integrity_c *ic)
487498 ic -> sb -> version = SB_VERSION_1 ;
488499}
489500
501+ static int sb_mac (struct dm_integrity_c * ic , bool wr )
502+ {
503+ SHASH_DESC_ON_STACK (desc , ic -> journal_mac );
504+ int r ;
505+ unsigned size = crypto_shash_digestsize (ic -> journal_mac );
506+
507+ if (sizeof (struct superblock ) + size > 1 << SECTOR_SHIFT ) {
508+ dm_integrity_io_error (ic , "digest is too long" , - EINVAL );
509+ return - EINVAL ;
510+ }
511+
512+ desc -> tfm = ic -> journal_mac ;
513+
514+ r = crypto_shash_init (desc );
515+ if (unlikely (r < 0 )) {
516+ dm_integrity_io_error (ic , "crypto_shash_init" , r );
517+ return r ;
518+ }
519+
520+ r = crypto_shash_update (desc , (__u8 * )ic -> sb , (1 << SECTOR_SHIFT ) - size );
521+ if (unlikely (r < 0 )) {
522+ dm_integrity_io_error (ic , "crypto_shash_update" , r );
523+ return r ;
524+ }
525+
526+ if (likely (wr )) {
527+ r = crypto_shash_final (desc , (__u8 * )ic -> sb + (1 << SECTOR_SHIFT ) - size );
528+ if (unlikely (r < 0 )) {
529+ dm_integrity_io_error (ic , "crypto_shash_final" , r );
530+ return r ;
531+ }
532+ } else {
533+ __u8 result [HASH_MAX_DIGESTSIZE ];
534+ r = crypto_shash_final (desc , result );
535+ if (unlikely (r < 0 )) {
536+ dm_integrity_io_error (ic , "crypto_shash_final" , r );
537+ return r ;
538+ }
539+ if (memcmp ((__u8 * )ic -> sb + (1 << SECTOR_SHIFT ) - size , result , size )) {
540+ dm_integrity_io_error (ic , "superblock mac" , - EILSEQ );
541+ return - EILSEQ ;
542+ }
543+ }
544+
545+ return 0 ;
546+ }
547+
490548static int sync_rw_sb (struct dm_integrity_c * ic , int op , int op_flags )
491549{
492550 struct dm_io_request io_req ;
493551 struct dm_io_region io_loc ;
552+ int r ;
494553
495554 io_req .bi_op = op ;
496555 io_req .bi_op_flags = op_flags ;
@@ -502,10 +561,28 @@ static int sync_rw_sb(struct dm_integrity_c *ic, int op, int op_flags)
502561 io_loc .sector = ic -> start ;
503562 io_loc .count = SB_SECTORS ;
504563
505- if (op == REQ_OP_WRITE )
564+ if (op == REQ_OP_WRITE ) {
506565 sb_set_version (ic );
566+ if (ic -> journal_mac && ic -> sb -> flags & cpu_to_le32 (SB_FLAG_FIXED_HMAC )) {
567+ r = sb_mac (ic , true);
568+ if (unlikely (r ))
569+ return r ;
570+ }
571+ }
507572
508- return dm_io (& io_req , 1 , & io_loc , NULL );
573+ r = dm_io (& io_req , 1 , & io_loc , NULL );
574+ if (unlikely (r ))
575+ return r ;
576+
577+ if (op == REQ_OP_READ ) {
578+ if (ic -> mode != 'R' && ic -> journal_mac && ic -> sb -> flags & cpu_to_le32 (SB_FLAG_FIXED_HMAC )) {
579+ r = sb_mac (ic , false);
580+ if (unlikely (r ))
581+ return r ;
582+ }
583+ }
584+
585+ return 0 ;
509586}
510587
511588#define BITMAP_OP_TEST_ALL_SET 0
@@ -722,15 +799,32 @@ static void section_mac(struct dm_integrity_c *ic, unsigned section, __u8 result
722799 desc -> tfm = ic -> journal_mac ;
723800
724801 r = crypto_shash_init (desc );
725- if (unlikely (r )) {
802+ if (unlikely (r < 0 )) {
726803 dm_integrity_io_error (ic , "crypto_shash_init" , r );
727804 goto err ;
728805 }
729806
807+ if (ic -> sb -> flags & cpu_to_le32 (SB_FLAG_FIXED_HMAC )) {
808+ uint64_t section_le ;
809+
810+ r = crypto_shash_update (desc , (__u8 * )& ic -> sb -> salt , SALT_SIZE );
811+ if (unlikely (r < 0 )) {
812+ dm_integrity_io_error (ic , "crypto_shash_update" , r );
813+ goto err ;
814+ }
815+
816+ section_le = cpu_to_le64 (section );
817+ r = crypto_shash_update (desc , (__u8 * )& section_le , sizeof section_le );
818+ if (unlikely (r < 0 )) {
819+ dm_integrity_io_error (ic , "crypto_shash_update" , r );
820+ goto err ;
821+ }
822+ }
823+
730824 for (j = 0 ; j < ic -> journal_section_entries ; j ++ ) {
731825 struct journal_entry * je = access_journal_entry (ic , section , j );
732826 r = crypto_shash_update (desc , (__u8 * )& je -> u .sector , sizeof je -> u .sector );
733- if (unlikely (r )) {
827+ if (unlikely (r < 0 )) {
734828 dm_integrity_io_error (ic , "crypto_shash_update" , r );
735829 goto err ;
736830 }
@@ -740,7 +834,7 @@ static void section_mac(struct dm_integrity_c *ic, unsigned section, __u8 result
740834
741835 if (likely (size <= JOURNAL_MAC_SIZE )) {
742836 r = crypto_shash_final (desc , result );
743- if (unlikely (r )) {
837+ if (unlikely (r < 0 )) {
744838 dm_integrity_io_error (ic , "crypto_shash_final" , r );
745839 goto err ;
746840 }
@@ -753,7 +847,7 @@ static void section_mac(struct dm_integrity_c *ic, unsigned section, __u8 result
753847 goto err ;
754848 }
755849 r = crypto_shash_final (desc , digest );
756- if (unlikely (r )) {
850+ if (unlikely (r < 0 )) {
757851 dm_integrity_io_error (ic , "crypto_shash_final" , r );
758852 goto err ;
759853 }
@@ -1556,6 +1650,14 @@ static void integrity_sector_checksum(struct dm_integrity_c *ic, sector_t sector
15561650 goto failed ;
15571651 }
15581652
1653+ if (ic -> sb -> flags & cpu_to_le32 (SB_FLAG_FIXED_HMAC )) {
1654+ r = crypto_shash_update (req , (__u8 * )& ic -> sb -> salt , SALT_SIZE );
1655+ if (unlikely (r < 0 )) {
1656+ dm_integrity_io_error (ic , "crypto_shash_update" , r );
1657+ goto failed ;
1658+ }
1659+ }
1660+
15591661 r = crypto_shash_update (req , (const __u8 * )& sector_le , sizeof sector_le );
15601662 if (unlikely (r < 0 )) {
15611663 dm_integrity_io_error (ic , "crypto_shash_update" , r );
@@ -3149,6 +3251,7 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type,
31493251 arg_count += !!ic -> journal_crypt_alg .alg_string ;
31503252 arg_count += !!ic -> journal_mac_alg .alg_string ;
31513253 arg_count += (ic -> sb -> flags & cpu_to_le32 (SB_FLAG_FIXED_PADDING )) != 0 ;
3254+ arg_count += (ic -> sb -> flags & cpu_to_le32 (SB_FLAG_FIXED_HMAC )) != 0 ;
31523255 arg_count += ic -> legacy_recalculate ;
31533256 DMEMIT ("%s %llu %u %c %u" , ic -> dev -> name , ic -> start ,
31543257 ic -> tag_size , ic -> mode , arg_count );
@@ -3173,6 +3276,8 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type,
31733276 }
31743277 if ((ic -> sb -> flags & cpu_to_le32 (SB_FLAG_FIXED_PADDING )) != 0 )
31753278 DMEMIT (" fix_padding" );
3279+ if ((ic -> sb -> flags & cpu_to_le32 (SB_FLAG_FIXED_HMAC )) != 0 )
3280+ DMEMIT (" fix_hmac" );
31763281 if (ic -> legacy_recalculate )
31773282 DMEMIT (" legacy_recalculate" );
31783283
@@ -3310,6 +3415,11 @@ static int initialize_superblock(struct dm_integrity_c *ic, unsigned journal_sec
33103415 if (!journal_sections )
33113416 journal_sections = 1 ;
33123417
3418+ if (ic -> fix_hmac && (ic -> internal_hash_alg .alg_string || ic -> journal_mac_alg .alg_string )) {
3419+ ic -> sb -> flags |= cpu_to_le32 (SB_FLAG_FIXED_HMAC );
3420+ get_random_bytes (ic -> sb -> salt , SALT_SIZE );
3421+ }
3422+
33133423 if (!ic -> meta_dev ) {
33143424 if (ic -> fix_padding )
33153425 ic -> sb -> flags |= cpu_to_le32 (SB_FLAG_FIXED_PADDING );
@@ -3804,7 +3914,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
38043914 unsigned extra_args ;
38053915 struct dm_arg_set as ;
38063916 static const struct dm_arg _args [] = {
3807- {0 , 16 , "Invalid number of feature args" },
3917+ {0 , 17 , "Invalid number of feature args" },
38083918 };
38093919 unsigned journal_sectors , interleave_sectors , buffer_sectors , journal_watermark , sync_msec ;
38103920 bool should_write_sb ;
@@ -3942,7 +4052,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
39424052 if (r )
39434053 goto bad ;
39444054 } else if (!strncmp (opt_string , "journal_mac:" , strlen ("journal_mac:" ))) {
3945- r = get_alg_and_key (opt_string , & ic -> journal_mac_alg , & ti -> error ,
4055+ r = get_alg_and_key (opt_string , & ic -> journal_mac_alg , & ti -> error ,
39464056 "Invalid journal_mac argument" );
39474057 if (r )
39484058 goto bad ;
@@ -3952,6 +4062,8 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
39524062 ic -> discard = true;
39534063 } else if (!strcmp (opt_string , "fix_padding" )) {
39544064 ic -> fix_padding = true;
4065+ } else if (!strcmp (opt_string , "fix_hmac" )) {
4066+ ic -> fix_hmac = true;
39554067 } else if (!strcmp (opt_string , "legacy_recalculate" )) {
39564068 ic -> legacy_recalculate = true;
39574069 } else {
@@ -4110,7 +4222,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
41104222 should_write_sb = true;
41114223 }
41124224
4113- if (!ic -> sb -> version || ic -> sb -> version > SB_VERSION_4 ) {
4225+ if (!ic -> sb -> version || ic -> sb -> version > SB_VERSION_5 ) {
41144226 r = - EINVAL ;
41154227 ti -> error = "Unknown version" ;
41164228 goto bad ;
@@ -4442,7 +4554,7 @@ static void dm_integrity_dtr(struct dm_target *ti)
44424554
44434555static struct target_type integrity_target = {
44444556 .name = "integrity" ,
4445- .version = {1 , 6 , 0 },
4557+ .version = {1 , 7 , 0 },
44464558 .module = THIS_MODULE ,
44474559 .features = DM_TARGET_SINGLETON | DM_TARGET_INTEGRITY ,
44484560 .ctr = dm_integrity_ctr ,
0 commit comments