]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ext4 crypto: enable encryption feature flag
authorTheodore Ts'o <tytso@mit.edu>
Wed, 8 Apr 2015 04:20:21 +0000 (00:20 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Wed, 8 Apr 2015 04:20:21 +0000 (00:20 -0400)
Also add the test dummy encryption mode flag so we can more easily
test the encryption patches using xfstests.

Change-Id: I63a7f5b969738eed81b2f12715cfff161a988d84
Signed-off-by: Michael Halcrow <mhalcrow@google.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/crypto_key.c
fs/ext4/crypto_policy.c
fs/ext4/ext4.h
fs/ext4/ialloc.c
fs/ext4/namei.c
fs/ext4/super.c

index 55bbd77b18eadfeebfc535e30c174fa43768fdaa..845370950d8d744a84d7b8af9f9be5dad2b3de8f 100644 (file)
@@ -104,6 +104,7 @@ int ext4_generate_encryption_key(struct inode *inode)
        struct ext4_encryption_key *master_key;
        struct ext4_encryption_context ctx;
        struct user_key_payload *ukp;
+       struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        int res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
                                 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
                                 &ctx, sizeof(ctx));
@@ -115,6 +116,20 @@ int ext4_generate_encryption_key(struct inode *inode)
        }
        res = 0;
 
+       if (S_ISREG(inode->i_mode))
+               crypt_key->mode = ctx.contents_encryption_mode;
+       else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+               crypt_key->mode = ctx.filenames_encryption_mode;
+       else {
+               printk(KERN_ERR "ext4 crypto: Unsupported inode type.\n");
+               BUG();
+       }
+       crypt_key->size = ext4_encryption_key_size(crypt_key->mode);
+       BUG_ON(!crypt_key->size);
+       if (unlikely(sbi->s_mount_flags & EXT4_MF_TEST_DUMMY_ENCRYPTION)) {
+               memset(crypt_key->raw, 0x42, EXT4_AES_256_XTS_KEY_SIZE);
+               goto out;
+       }
        memcpy(full_key_descriptor, EXT4_KEY_DESC_PREFIX,
               EXT4_KEY_DESC_PREFIX_SIZE);
        ext4_to_hex(&full_key_descriptor[EXT4_KEY_DESC_PREFIX_SIZE],
@@ -134,21 +149,9 @@ int ext4_generate_encryption_key(struct inode *inode)
                goto out;
        }
        master_key = (struct ext4_encryption_key *)ukp->data;
-
-       if (S_ISREG(inode->i_mode))
-               crypt_key->mode = ctx.contents_encryption_mode;
-       else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
-               crypt_key->mode = ctx.filenames_encryption_mode;
-       else {
-               printk(KERN_ERR "ext4 crypto: Unsupported inode type.\n");
-               BUG();
-       }
-       crypt_key->size = ext4_encryption_key_size(crypt_key->mode);
-       BUG_ON(!crypt_key->size);
        BUILD_BUG_ON(EXT4_AES_128_ECB_KEY_SIZE !=
                     EXT4_KEY_DERIVATION_NONCE_SIZE);
        BUG_ON(master_key->size != EXT4_AES_256_XTS_KEY_SIZE);
-       BUG_ON(crypt_key->size < EXT4_AES_256_CBC_KEY_SIZE);
        res = ext4_derive_key_aes(ctx.nonce, master_key->raw, crypt_key->raw);
 out:
        if (keyring_key)
index ab216bbb0d4fb3c95792841a0241a182a0daa705..a6163fe7b79f05641c1c68e54176c63584a76197 100644 (file)
@@ -174,17 +174,31 @@ int ext4_is_child_context_consistent_with_parent(struct inode *parent,
 int ext4_inherit_context(struct inode *parent, struct inode *child)
 {
        struct ext4_encryption_context ctx;
+       struct ext4_sb_info *sbi = EXT4_SB(parent->i_sb);
        int res = ext4_xattr_get(parent, EXT4_XATTR_INDEX_ENCRYPTION,
                                 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
                                 &ctx, sizeof(ctx));
 
-       if (res != sizeof(ctx))
-               return -ENOENT;
-
+       if (res != sizeof(ctx)) {
+               if (unlikely(sbi->s_mount_flags &
+                            EXT4_MF_TEST_DUMMY_ENCRYPTION)) {
+                       ctx.format = EXT4_ENCRYPTION_CONTEXT_FORMAT_V0;
+                       ctx.contents_encryption_mode =
+                               EXT4_ENCRYPTION_MODE_AES_256_XTS;
+                       ctx.filenames_encryption_mode =
+                               EXT4_ENCRYPTION_MODE_AES_256_CTS;
+                       memset(ctx.master_key_descriptor, 0x42,
+                              EXT4_KEY_DESCRIPTOR_SIZE);
+                       res = 0;
+               } else {
+                       goto out;
+               }
+       }
        get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE);
        res = ext4_xattr_set(child, EXT4_XATTR_INDEX_ENCRYPTION,
                             EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx,
                             sizeof(ctx), 0);
+out:
        if (!res)
                ext4_set_inode_flag(child, EXT4_INODE_ENCRYPT);
        return res;
index cd32eba4e6df0208fab15697827a64357ba79c9f..3eded5583203b19eb74538f69dde1bfacb554830 100644 (file)
@@ -1193,8 +1193,9 @@ struct ext4_super_block {
 /*
  * run-time mount flags
  */
-#define EXT4_MF_MNTDIR_SAMPLED 0x0001
-#define EXT4_MF_FS_ABORTED     0x0002  /* Fatal error detected */
+#define EXT4_MF_MNTDIR_SAMPLED         0x0001
+#define EXT4_MF_FS_ABORTED             0x0002  /* Fatal error detected */
+#define EXT4_MF_TEST_DUMMY_ENCRYPTION  0x0004
 
 /* Number of quota types we support */
 #define EXT4_MAXQUOTAS 2
@@ -1606,8 +1607,9 @@ static inline int ext4_encrypted_inode(struct inode *inode)
                                         EXT4_FEATURE_INCOMPAT_EXTENTS| \
                                         EXT4_FEATURE_INCOMPAT_64BIT| \
                                         EXT4_FEATURE_INCOMPAT_FLEX_BG| \
-                                        EXT4_FEATURE_INCOMPAT_MMP |    \
-                                        EXT4_FEATURE_INCOMPAT_INLINE_DATA)
+                                        EXT4_FEATURE_INCOMPAT_MMP | \
+                                        EXT4_FEATURE_INCOMPAT_INLINE_DATA | \
+                                        EXT4_FEATURE_INCOMPAT_ENCRYPT)
 #define EXT4_FEATURE_RO_COMPAT_SUPP    (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
                                         EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
                                         EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \
index 850267c89407eacd09db87873c35211ad68264d0..35a599eeb7ac3ba3f5251e1153981727e41797c1 100644 (file)
@@ -998,7 +998,9 @@ got:
 
        /* If the directory encrypted, then we should encrypt the inode. */
        if ((S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) &&
-           ext4_encrypted_inode(dir))
+           (ext4_encrypted_inode(dir) ||
+            unlikely(sbi->s_mount_flags &
+                     EXT4_MF_TEST_DUMMY_ENCRYPTION)))
                ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
 
        ext4_set_inode_flags(inode);
index 7670777ac3b4348fc0dcedc473401eb57acf6040..c5197176dba4e41ca0b0688c18e31bf57a9e4519 100644 (file)
@@ -2573,6 +2573,9 @@ static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        handle_t *handle;
        struct inode *inode;
        int err, credits, retries = 0;
+#ifdef CONFIG_EXT4_FS_ENCRYPTION
+       struct ext4_sb_info *sbi = EXT4_SB(dir->i_sb);
+#endif
 
        dquot_initialize(dir);
 
@@ -2594,7 +2597,9 @@ retry:
                if (!err && IS_DIRSYNC(dir))
                        ext4_handle_sync(handle);
 #ifdef CONFIG_EXT4_FS_ENCRYPTION
-               if (!err && ext4_encrypted_inode(dir)) {
+               if (!err && (ext4_encrypted_inode(dir) ||
+                            unlikely(sbi->s_mount_flags &
+                                     EXT4_MF_TEST_DUMMY_ENCRYPTION))) {
                        err = ext4_inherit_context(dir, inode);
                        if (err)
                                ext4_unlink(dir, dentry);
@@ -2759,6 +2764,9 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        handle_t *handle;
        struct inode *inode;
        int err, credits, retries = 0;
+#ifdef CONFIG_EXT4_FS_ENCRYPTION
+       struct ext4_sb_info *sbi = EXT4_SB(dir->i_sb);
+#endif
 
        if (EXT4_DIR_LINK_MAX(dir))
                return -EMLINK;
@@ -2802,7 +2810,8 @@ out_clear_inode:
        if (IS_DIRSYNC(dir))
                ext4_handle_sync(handle);
 #ifdef CONFIG_EXT4_FS_ENCRYPTION
-       if (ext4_encrypted_inode(dir)) {
+       if (ext4_encrypted_inode(dir) ||
+           unlikely(sbi->s_mount_flags & EXT4_MF_TEST_DUMMY_ENCRYPTION)) {
                err = ext4_inherit_context(dir, inode);
                if (err)
                        ext4_unlink(dir, dentry);
index e79d903612f96111b43c87a3ad94b6043f7c13d9..2c3e7d311b207856ab7db3e55adfc93c97e11d4a 100644 (file)
@@ -1106,7 +1106,7 @@ enum {
        Opt_commit, Opt_min_batch_time, Opt_max_batch_time, Opt_journal_dev,
        Opt_journal_path, Opt_journal_checksum, Opt_journal_async_commit,
        Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
-       Opt_data_err_abort, Opt_data_err_ignore,
+       Opt_data_err_abort, Opt_data_err_ignore, Opt_test_dummy_encryption,
        Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
        Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err,
@@ -1197,6 +1197,7 @@ static const match_table_t tokens = {
        {Opt_init_itable, "init_itable"},
        {Opt_noinit_itable, "noinit_itable"},
        {Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
+       {Opt_test_dummy_encryption, "test_dummy_encryption"},
        {Opt_removed, "check=none"},    /* mount option from ext2/3 */
        {Opt_removed, "nocheck"},       /* mount option from ext2/3 */
        {Opt_removed, "reservation"},   /* mount option from ext2/3 */
@@ -1398,6 +1399,7 @@ static const struct mount_opts {
        {Opt_jqfmt_vfsv0, QFMT_VFS_V0, MOPT_QFMT},
        {Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT},
        {Opt_max_dir_size_kb, 0, MOPT_GTE0},
+       {Opt_test_dummy_encryption, 0, MOPT_GTE0},
        {Opt_err, 0, 0}
 };
 
@@ -1574,6 +1576,15 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
                }
                *journal_ioprio =
                        IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, arg);
+       } else if (token == Opt_test_dummy_encryption) {
+#ifdef CONFIG_EXT4_FS_ENCRYPTION
+               sbi->s_mount_flags |= EXT4_MF_TEST_DUMMY_ENCRYPTION;
+               ext4_msg(sb, KERN_WARNING,
+                        "Test dummy encryption mode enabled");
+#else
+               ext4_msg(sb, KERN_WARNING,
+                        "Test dummy encryption mount option ignored");
+#endif
        } else if (m->flags & MOPT_DATAJ) {
                if (is_remount) {
                        if (!sbi->s_journal)
@@ -4045,6 +4056,13 @@ no_journal:
                }
        }
 
+       if (unlikely(sbi->s_mount_flags & EXT4_MF_TEST_DUMMY_ENCRYPTION) &&
+           !(sb->s_flags & MS_RDONLY) &&
+           !EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT)) {
+               EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT);
+               ext4_commit_super(sb, 1);
+       }
+
        /*
         * Get the # of file system overhead blocks from the
         * superblock if present.