diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 426aa1b27f17..fe6f6524c1aa 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -101,6 +101,10 @@ static inline bool fscrypt_valid_enc_modes(u32 contents_mode, filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS) return true; + if (contents_mode == FS_ENCRYPTION_MODE_SPECK128_256_XTS && + filenames_mode == FS_ENCRYPTION_MODE_SPECK128_256_CTS) + return true; + return false; } diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 7c00331da5df..472f69188a96 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -134,6 +134,8 @@ static const struct { FS_AES_128_CBC_KEY_SIZE }, [FS_ENCRYPTION_MODE_AES_128_CTS] = { "cts(cbc(aes))", FS_AES_128_CTS_KEY_SIZE }, + [FS_ENCRYPTION_MODE_SPECK128_256_XTS] = { "xts(speck128)", 64 }, + [FS_ENCRYPTION_MODE_SPECK128_256_CTS] = { "cts(cbc(speck128))", 32 }, }; static int determine_cipher_type(struct fscrypt_info *ci, struct inode *inode, diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c index f240cef8b326..f6096ee77662 100644 --- a/fs/ext4/crypto.c +++ b/fs/ext4/crypto.c @@ -457,9 +457,17 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex) return err; } -bool ext4_valid_contents_enc_mode(uint32_t mode) +bool ext4_valid_enc_modes(uint32_t contents_mode, uint32_t filenames_mode) { - return (mode == EXT4_ENCRYPTION_MODE_AES_256_XTS); + if (contents_mode == EXT4_ENCRYPTION_MODE_AES_256_XTS) { + return (filenames_mode == EXT4_ENCRYPTION_MODE_AES_256_CTS || + filenames_mode == EXT4_ENCRYPTION_MODE_AES_256_HEH); + } + + if (contents_mode == EXT4_ENCRYPTION_MODE_SPECK128_256_XTS) + return filenames_mode == EXT4_ENCRYPTION_MODE_SPECK128_256_CTS; + + return false; } /** diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c index 026716bdbbfc..5e5afb6ef71a 100644 --- a/fs/ext4/crypto_fname.c +++ b/fs/ext4/crypto_fname.c @@ -42,12 +42,6 @@ static void ext4_dir_crypt_complete(struct crypto_async_request *req, int res) complete(&ecr->completion); } -bool ext4_valid_filenames_enc_mode(uint32_t mode) -{ - return (mode == EXT4_ENCRYPTION_MODE_AES_256_CTS || - mode == EXT4_ENCRYPTION_MODE_AES_256_HEH); -} - static unsigned max_name_len(struct inode *inode) { return S_ISLNK(inode->i_mode) ? inode->i_sb->s_blocksize : diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c index 14ae7781f2a8..68225223ffd8 100644 --- a/fs/ext4/crypto_key.c +++ b/fs/ext4/crypto_key.c @@ -258,6 +258,12 @@ int ext4_get_encryption_info(struct inode *inode) case EXT4_ENCRYPTION_MODE_AES_256_HEH: cipher_str = "heh(aes)"; break; + case EXT4_ENCRYPTION_MODE_SPECK128_256_XTS: + cipher_str = "xts(speck128)"; + break; + case EXT4_ENCRYPTION_MODE_SPECK128_256_CTS: + cipher_str = "cts(cbc(speck128))"; + break; default: printk_once(KERN_WARNING "ext4: unsupported key mode %d (ino %u)\n", diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c index e4f4fc4e56ab..818fa45ecf08 100644 --- a/fs/ext4/crypto_policy.c +++ b/fs/ext4/crypto_policy.c @@ -60,16 +60,12 @@ static int ext4_create_encryption_context_from_policy( ctx.format = EXT4_ENCRYPTION_CONTEXT_FORMAT_V1; memcpy(ctx.master_key_descriptor, policy->master_key_descriptor, EXT4_KEY_DESCRIPTOR_SIZE); - if (!ext4_valid_contents_enc_mode(policy->contents_encryption_mode)) { + if (!ext4_valid_enc_modes(policy->contents_encryption_mode, + policy->filenames_encryption_mode)) { printk(KERN_WARNING - "%s: Invalid contents encryption mode %d\n", __func__, - policy->contents_encryption_mode); - return -EINVAL; - } - if (!ext4_valid_filenames_enc_mode(policy->filenames_encryption_mode)) { - printk(KERN_WARNING - "%s: Invalid filenames encryption mode %d\n", __func__, - policy->filenames_encryption_mode); + "%s: Invalid encryption modes (contents %d, filenames %d)\n", + __func__, policy->contents_encryption_mode, + policy->filenames_encryption_mode); return -EINVAL; } if (policy->flags & ~EXT4_POLICY_FLAGS_VALID) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 6edacb849e48..40992b68e639 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -589,6 +589,8 @@ enum { #define EXT4_ENCRYPTION_MODE_AES_256_GCM 2 #define EXT4_ENCRYPTION_MODE_AES_256_CBC 3 #define EXT4_ENCRYPTION_MODE_AES_256_CTS 4 +#define EXT4_ENCRYPTION_MODE_SPECK128_256_XTS 7 +#define EXT4_ENCRYPTION_MODE_SPECK128_256_CTS 8 #define EXT4_ENCRYPTION_MODE_AES_256_HEH 126 #include "ext4_crypto.h" @@ -2259,7 +2261,7 @@ int ext4_get_policy(struct inode *inode, /* crypto.c */ extern struct kmem_cache *ext4_crypt_info_cachep; -bool ext4_valid_contents_enc_mode(uint32_t mode); +bool ext4_valid_enc_modes(uint32_t contents_mode, uint32_t filenames_mode); uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size); extern struct workqueue_struct *ext4_read_workqueue; struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode, @@ -2290,7 +2292,6 @@ static inline int ext4_sb_has_crypto(struct super_block *sb) #endif /* crypto_fname.c */ -bool ext4_valid_filenames_enc_mode(uint32_t mode); u32 ext4_fname_crypto_round_up(u32 size, u32 blksize); unsigned ext4_fname_encrypted_size(struct inode *inode, u32 ilen); int ext4_fname_crypto_alloc_buffer(struct inode *inode, diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h index e52637d969db..f7ba3be9d7ac 100644 --- a/fs/ext4/ext4_crypto.h +++ b/fs/ext4/ext4_crypto.h @@ -124,6 +124,10 @@ static inline int ext4_encryption_key_size(int mode) return EXT4_AES_256_CTS_KEY_SIZE; case EXT4_ENCRYPTION_MODE_AES_256_HEH: return EXT4_AES_256_HEH_KEY_SIZE; + case EXT4_ENCRYPTION_MODE_SPECK128_256_XTS: + return 64; + case EXT4_ENCRYPTION_MODE_SPECK128_256_CTS: + return 32; default: BUG(); } diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 60d27496c328..d122ea5338d1 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -193,6 +193,8 @@ struct inodes_stat_t { #define FS_ENCRYPTION_MODE_AES_256_CTS 4 #define FS_ENCRYPTION_MODE_AES_128_CBC 5 #define FS_ENCRYPTION_MODE_AES_128_CTS 6 +#define FS_ENCRYPTION_MODE_SPECK128_256_XTS 7 +#define FS_ENCRYPTION_MODE_SPECK128_256_CTS 8 struct fscrypt_policy {