]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
dm-crypt: Allow to specify the integrity key size as option
authorIngo Franzki <ifranzki@linux.ibm.com>
Fri, 16 Aug 2024 11:21:33 +0000 (13:21 +0200)
committerMikulas Patocka <mpatocka@redhat.com>
Wed, 21 Aug 2024 13:36:27 +0000 (15:36 +0200)
For the MAC based integrity operation, the integrity key size (i.e.
key_mac_size) is currently set to the digest size of the used digest.

For wrapped key HMAC algorithms, the key size is independent of the
cryptographic key size. So there is no known size of the mac key in
such cases. The desired key size can optionally be specified as argument
when the dm-crypt device is configured via 'integrity_key_size:%u'.
If no integrity_key_size argument is specified, the mac key size
is still set to the digest size, as before.

Increase version number to 1.28.0 so that support for the new
argument can be detected by user space (i.e. cryptsetup).

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Milan Broz <gmazyland@gmail.com>
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Documentation/admin-guide/device-mapper/dm-crypt.rst
drivers/md/dm-crypt.c

index 552c9155165d7c89920f5bbd8d38a02e01386822..cde1d5594b0d9c3d66806a6a69e3c06060664f1d 100644 (file)
@@ -160,6 +160,10 @@ iv_large_sectors
    The <iv_offset> must be multiple of <sector_size> (in 512 bytes units)
    if this flag is specified.
 
+integrity_key_size:<bytes>
+   Use an integrity key of <bytes> size instead of using an integrity key size
+   of the digest size of the used HMAC algorithm.
+
 
 Module parameters::
 
index 348b4b26c272334d6f12ccd27a0e394bf1f31880..d5533b43054edb97f50c73c06a484c5902eacd0f 100644 (file)
@@ -147,6 +147,7 @@ enum cipher_flags {
        CRYPT_MODE_INTEGRITY_AEAD,      /* Use authenticated mode for cipher */
        CRYPT_IV_LARGE_SECTORS,         /* Calculate IV from sector_size, not 512B sectors */
        CRYPT_ENCRYPT_PREPROCESS,       /* Must preprocess data for encryption (elephant) */
+       CRYPT_KEY_MAC_SIZE_SET,         /* The integrity_key_size option was used */
 };
 
 /*
@@ -2937,7 +2938,8 @@ static int crypt_ctr_auth_cipher(struct crypt_config *cc, char *cipher_api)
        if (IS_ERR(mac))
                return PTR_ERR(mac);
 
-       cc->key_mac_size = crypto_ahash_digestsize(mac);
+       if (!test_bit(CRYPT_KEY_MAC_SIZE_SET, &cc->cipher_flags))
+               cc->key_mac_size = crypto_ahash_digestsize(mac);
        crypto_free_ahash(mac);
 
        cc->authenc_key = kmalloc(crypt_authenckey_size(cc), GFP_KERNEL);
@@ -3219,6 +3221,13 @@ static int crypt_ctr_optional(struct dm_target *ti, unsigned int argc, char **ar
                        cc->cipher_auth = kstrdup(sval, GFP_KERNEL);
                        if (!cc->cipher_auth)
                                return -ENOMEM;
+               } else if (sscanf(opt_string, "integrity_key_size:%u%c", &val, &dummy) == 1) {
+                       if (!val) {
+                               ti->error = "Invalid integrity_key_size argument";
+                               return -EINVAL;
+                       }
+                       cc->key_mac_size = val;
+                       set_bit(CRYPT_KEY_MAC_SIZE_SET, &cc->cipher_flags);
                } else if (sscanf(opt_string, "sector_size:%hu%c", &cc->sector_size, &dummy) == 1) {
                        if (cc->sector_size < (1 << SECTOR_SHIFT) ||
                            cc->sector_size > 4096 ||
@@ -3607,10 +3616,10 @@ static void crypt_status(struct dm_target *ti, status_type_t type,
                num_feature_args += test_bit(DM_CRYPT_NO_OFFLOAD, &cc->flags);
                num_feature_args += test_bit(DM_CRYPT_NO_READ_WORKQUEUE, &cc->flags);
                num_feature_args += test_bit(DM_CRYPT_NO_WRITE_WORKQUEUE, &cc->flags);
+               num_feature_args += !!cc->used_tag_size;
                num_feature_args += cc->sector_size != (1 << SECTOR_SHIFT);
                num_feature_args += test_bit(CRYPT_IV_LARGE_SECTORS, &cc->cipher_flags);
-               if (cc->used_tag_size)
-                       num_feature_args++;
+               num_feature_args += test_bit(CRYPT_KEY_MAC_SIZE_SET, &cc->cipher_flags);
                if (num_feature_args) {
                        DMEMIT(" %d", num_feature_args);
                        if (ti->num_discard_bios)
@@ -3631,6 +3640,8 @@ static void crypt_status(struct dm_target *ti, status_type_t type,
                                DMEMIT(" sector_size:%d", cc->sector_size);
                        if (test_bit(CRYPT_IV_LARGE_SECTORS, &cc->cipher_flags))
                                DMEMIT(" iv_large_sectors");
+                       if (test_bit(CRYPT_KEY_MAC_SIZE_SET, &cc->cipher_flags))
+                               DMEMIT(" integrity_key_size:%u", cc->key_mac_size);
                }
                break;
 
@@ -3758,7 +3769,7 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
 
 static struct target_type crypt_target = {
        .name   = "crypt",
-       .version = {1, 27, 0},
+       .version = {1, 28, 0},
        .module = THIS_MODULE,
        .ctr    = crypt_ctr,
        .dtr    = crypt_dtr,