]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
Update ext4 encryption format to final v4.1 version
authorTheodore Ts'o <tytso@mit.edu>
Sun, 3 May 2015 18:48:25 +0000 (14:48 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Sun, 3 May 2015 21:01:59 +0000 (17:01 -0400)
The directory hash is now calculated using the on-disk encrypted
filename, and we no longer use the digest encoding or the SHA-256
encoding, so remove them from the ext2fs library until there is some
reason we need them.

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
e2fsck/pass2.c
e2fsck/rehash.c
lib/ext2fs/Makefile.in
lib/ext2fs/digest_encode.c
lib/ext2fs/ext2_fs.h
lib/ext2fs/ext2fs.h
misc/e4crypt.c

index d795c06a7a6bb500c5103ac4dbabc18d186cbbfb..ecc0aaa07603d4a56e83cb876667f68baae227af 100644 (file)
@@ -855,32 +855,6 @@ err:
        return retval;
 }
 
-int get_filename_hash(ext2_filsys fs, int encrypted, int version,
-                     const char *name, int len, ext2_dirhash_t *ret_hash,
-                     ext2_dirhash_t *ret_minor_hash)
-{
-       char    buf[2*EXT2FS_DIGEST_SIZE];
-       int     buf_len;
-
-       if (!encrypted)
-               return ext2fs_dirhash(version, name, len,
-                                     fs->super->s_hash_seed,
-                                     ret_hash, ret_minor_hash);
-
-       if (len <= EXT2FS_DIGEST_SIZE)
-               buf_len = ext2fs_digest_encode(name, len, buf);
-       else {
-               ext2fs_sha256(name, len, buf + EXT2FS_DIGEST_SIZE);
-               buf[0] = 'I';
-               buf_len = ext2fs_digest_encode(buf + EXT2FS_DIGEST_SIZE,
-                                              EXT2FS_DIGEST_SIZE, buf + 1);
-               buf_len++;
-       }
-       return ext2fs_dirhash(version, buf, buf_len,
-                             fs->super->s_hash_seed,
-                             ret_hash, ret_minor_hash);
-}
-
 static int check_dir_block2(ext2_filsys fs,
                           struct ext2_db_entry2 *db,
                           void *priv_data)
@@ -1422,10 +1396,9 @@ skip_checksum:
 
 #ifdef ENABLE_HTREE
                if (dx_db) {
-                       get_filename_hash(fs, encrypted, dx_dir->hashversion,
-                                         dirent->name,
-                                         ext2fs_dirent_name_len(dirent),
-                                         &hash, 0);
+                       ext2fs_dirhash(dx_dir->hashversion, dirent->name,
+                                      ext2fs_dirent_name_len(dirent),
+                                      fs->super->s_hash_seed, &hash, 0);
                        if (hash < dx_db->min_hash)
                                dx_db->min_hash = hash;
                        if (hash > dx_db->max_hash)
index 3efa114a5f0264465a8ab9845da64923f140e12d..bddbe1927d504396b4198cccf2830d9ab5cf2ae7 100644 (file)
@@ -112,9 +112,6 @@ static int fill_dir_block(ext2_filsys fs,
        char                    *dir;
        unsigned int            offset, dir_offset, rec_len, name_len;
        int                     hash_alg;
-       int                     encrypted = 0;
-       char                    processed_filename[2*EXT2FS_DIGEST_SIZE];
-       int                     processed_filename_len;
 
        if (blockcnt < 0)
                return 0;
@@ -125,11 +122,6 @@ static int fill_dir_block(ext2_filsys fs,
                return BLOCK_ABORT;
        }
 
-       /* Determine if the directory is encrypted */
-       if (fd->ctx->encrypted_dirs)
-               encrypted = ext2fs_u32_list_test(fd->ctx->encrypted_dirs,
-                                               fd->ino);
-
        dir = (fd->buf+offset);
        if (*block_nr == 0) {
                memset(dir, 0, fs->blocksize);
@@ -190,10 +182,10 @@ static int fill_dir_block(ext2_filsys fs,
                if (fd->compress)
                        ent->hash = ent->minor_hash = 0;
                else {
-                       fd->err = get_filename_hash(fs, encrypted,
-                                       hash_alg, dirent->name,
-                                       ext2fs_dirent_name_len(dirent),
-                                       &ent->hash, &ent->minor_hash);
+                       fd->err = ext2fs_dirhash(hash_alg, dirent->name,
+                                                name_len,
+                                                fs->super->s_hash_seed,
+                                                &ent->hash, &ent->minor_hash);
                        if (fd->err)
                                return BLOCK_ABORT;
                }
@@ -378,9 +370,6 @@ static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
        char                    new_name[256];
        unsigned int            new_len;
        int                     hash_alg;
-       int                     encrypted = 0;
-       char                    processed_filename[2*EXT2FS_DIGEST_SIZE];
-       int                     processed_filename_len;
 
        clear_problem_context(&pctx);
        pctx.ino = ino;
@@ -390,10 +379,6 @@ static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
            (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH))
                hash_alg += 3;
 
-       /* Determine if the directory is encrypted */
-       if (fd->ctx->encrypted_dirs)
-               encrypted = ext2fs_u32_list_test(fd->ctx->encrypted_dirs,
-                                               fd->ino);
        for (i=1; i < fd->num_array; i++) {
                ent = fd->harray + i;
                prev = ent - 1;
@@ -429,9 +414,9 @@ static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
                if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
                        memcpy(ent->dir->name, new_name, new_len);
                        ext2fs_dirent_set_name_len(ent->dir, new_len);
-                       get_filename_hash(fs, encrypted,
-                                         hash_alg, new_name, new_len,
-                                         &ent->hash, &ent->minor_hash);
+                       ext2fs_dirhash(hash_alg, new_name, new_len,
+                                      fs->super->s_hash_seed,
+                                      &ent->hash, &ent->minor_hash);
                        fixed++;
                }
        }
index 8a7f8ca5290281724ee31586bdc1933d96353633..21469795e5bb22c5a7e6d9ccb5d125c33c4a2196 100644 (file)
@@ -73,7 +73,6 @@ OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \
        csum.o \
        dblist.o \
        dblist_dir.o \
-       digest_encode.o \
        dirblock.o \
        dirhash.o \
        dir_iterate.o \
@@ -116,7 +115,6 @@ OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \
        read_bb_file.o \
        res_gdt.o \
        rw_bitmaps.o \
-       sha256.o \
        sha512.o \
        swapfs.o \
        symlink.o \
index a24ba6ca2f68a7f3ac223439001d6520c6f655b2..d90b3006b9c0586dc76cd6d64eb9cfa686a24738 100644 (file)
 #endif
 #include "ext2fs.h"
 
+static const char *lookup_table =
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
+
 /**
  * ext2fs_digest_encode() -
  *
  * Encodes the input digest using characters from the set [a-zA-Z0-9_+].
  * The encoded string is roughly 4/3 times the size of the input string.
  */
-int ext2fs_digest_encode(const char *src, unsigned long len, char *dst)
+int ext2fs_digest_encode(const char *src, int len, char *dst)
 {
-       static const char *lookup_table =
-               "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+";
-       unsigned num_chunks, i;
-       char tmp_buf[3];
-       unsigned c0, c1, c2, c3;
+       int i = 0, bits = 0, ac = 0;
+       char *cp = dst;
 
-       num_chunks = len/3;
-       for (i = 0; i < num_chunks; i++) {
-               c0 = src[3*i] & 0x3f;
-               c1 = (((src[3*i]>>6)&0x3) | ((src[3*i+1] & 0xf)<<2)) & 0x3f;
-               c2 = (((src[3*i+1]>>4)&0xf) | ((src[3*i+2] & 0x3)<<4)) & 0x3f;
-               c3 = (src[3*i+2]>>2) & 0x3f;
-               dst[4*i] = lookup_table[c0];
-               dst[4*i+1] = lookup_table[c1];
-               dst[4*i+2] = lookup_table[c2];
-               dst[4*i+3] = lookup_table[c3];
+       while (i < len) {
+               ac += (((unsigned char) src[i]) << bits);
+               bits += 8;
+               do {
+                       *cp++ = lookup_table[ac & 0x3f];
+                       ac >>= 6;
+                       bits -= 6;
+               } while (bits >= 6);
+               i++;
        }
-       if (i*3 < len) {
-               memset(tmp_buf, 0, 3);
-               memcpy(tmp_buf, &src[3*i], len-3*i);
-               c0 = tmp_buf[0] & 0x3f;
-               c1 = (((tmp_buf[0]>>6)&0x3) | ((tmp_buf[1] & 0xf)<<2)) & 0x3f;
-               c2 = (((tmp_buf[1]>>4)&0xf) | ((tmp_buf[2] & 0x3)<<4)) & 0x3f;
-               c3 = (tmp_buf[2]>>2) & 0x3f;
-               dst[4*i] = lookup_table[c0];
-               dst[4*i+1] = lookup_table[c1];
-               dst[4*i+2] = lookup_table[c2];
-               dst[4*i+3] = lookup_table[c3];
+       if (bits)
+               *cp++ = lookup_table[ac & 0x3f];
+       return cp - dst;
+}
+
+int ext2fs_digest_decode(const char *src, int len, char *dst)
+{
+       int i = 0, bits = 0, ac = 0;
+       const char *p;
+       char *cp = dst;
+
+       while (i < len) {
+               p = strchr(lookup_table, src[i]);
+               if (p == NULL || src[i] == 0)
+                       return -1;
+               ac += (p - lookup_table) << bits;
+               bits += 6;
+               if (bits >= 8) {
+                       *cp++ = ac & 0xff;
+                       ac >>= 8;
+                       bits -= 8;
+               }
                i++;
        }
-       return (i * 4);
+       if (ac)
+               return -1;
+       return cp - dst;
 }
 
+
 #ifdef UNITTEST
 static const struct {
        unsigned char d[32];
@@ -71,52 +84,65 @@ static const struct {
            0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
            0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
            0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 }, 32,
-       "JdlXcHj+CqHM7tpYz_wUKCIRbrozBojtKwzMBGNu4wfa"
+       "jDLxChJ,cQhm7TPyZ+WukcirBROZbOJTkWZmbgnU4WF"
        },
        { { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
            0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
            0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
            0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }, 32,
-       "6INf+_yapREqbbK3D5QiJa7aHnQLxOhN0cX+Hjpav0ka"
+       "6inF,+YAPreQBBk3d5qIjA7AhNqlXoHn0Cx,hJPAV0K"
        },
        { { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
            0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
            0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
            0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }, 32,
-       "K0OAHjTb4GB5aBYKm4dy5mkpKNfz+hYz2ZE7uNX2gema"
+       "k0oahJtB4gb5AbykM4DY5MKPknFZ,HyZ2ze7Unx2GEM"
        },
        { { 0x00, }, 1,
-       "aaaa"
+       "AA"
        },
        { { 0x01, }, 1,
-       "baaa"
+       "BA"
        },
        { { 0x01, 0x02 }, 2,
-       "biaa"
+       "BIA"
        },
        { { 0x01, 0x02, 0x03 }, 3,
-       "biWa"
+       "BIwA"
        },
        { { 0x01, 0x02, 0x03, 0x04 }, 4,
-       "biWaeaaa"
+       "BIwAEA"
        },
        { { 0x01, 0x02, 0x03, 0x04, 0xff }, 5,
-       "biWae8pa"
+       "BIwAE8P"
        },
        { { 0x01, 0x02, 0x03, 0x04, 0xff, 0xfe }, 6,
-       "biWae8V+"
+       "BIwAE8v,"
        },
        { { 0x01, 0x02, 0x03, 0x04, 0xff, 0xfe, 0xfd }, 7,
-       "biWae8V+9daa"
+       "BIwAE8v,9D"
        },
 };
 
 int main(int argc, char **argv)
 {
-       int i, ret, len;
+       int i, ret, len, len2;
        int errors = 0;
-       unsigned char tmp[1024];
+       unsigned char tmp[1024], tmp2[1024];
 
+       if (argc == 3 && !strcmp(argv[1], "encode")) {
+               memset(tmp, 0, sizeof(tmp));
+               ext2fs_digest_encode(argv[2], strlen(argv[2]), tmp);
+               puts(tmp);
+               exit(0);
+       }
+       if (argc == 3 && !strcmp(argv[1], "decode")) {
+               memset(tmp, 0, sizeof(tmp));
+               ret = ext2fs_digest_decode(argv[2], strlen(argv[2]), tmp);
+               puts(tmp);
+               fprintf(stderr, "returned %d\n", ret);
+               exit(0);
+       }
        for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
                memset(tmp, 0, sizeof(tmp));
                ret = ext2fs_digest_encode(tests[i].d, tests[i].len, tmp);
@@ -126,12 +152,26 @@ int main(int argc, char **argv)
                        printf("FAILED returned %d, string length was %d\n",
                               ret, len);
                        errors++;
-               } else if (memcmp(tmp, tests[i].ed, ret) != 0) {
+                       continue;
+               } else if (strcmp(tmp, tests[i].ed) != 0) {
                        printf("FAILED: got %s, expected %s\n", tmp,
                               tests[i].ed);
                        errors++;
-               } else
-                       printf("OK\n");
+                       continue;
+               }
+               ret = ext2fs_digest_decode(tmp, len, tmp2);
+               if (ret != tests[i].len) {
+                       printf("FAILED decode returned %d, expected %d\n",
+                              ret, tests[i].len);
+                       errors++;
+                       continue;
+               }
+               if (memcmp(tmp2, tests[i].d, ret) != 0) {
+                       puts("FAILED: decode mismatched");
+                       errors++;
+                       continue;
+               }
+               printf("OK\n");
        }
        for (i = 1; i < argc; i++) {
                memset(tmp, 0, sizeof(tmp));
index a755cfac8eae3e7328e5ed6811d18b0614e75fbd..918ae707e349b747c4696ca5b49003d9679e57de 100644 (file)
@@ -593,6 +593,7 @@ struct ext4_encryption_policy {
   char version;
   char contents_encryption_mode;
   char filenames_encryption_mode;
+  char flags;
   char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE];
 } __attribute__((__packed__));
 
index 560b148c1149a478240ac3ebc380db630fa53b03..17a45901b565c5c1f509ecf7a379bca869eb20c0 100644 (file)
@@ -1071,9 +1071,12 @@ extern errcode_t
                                              void      *priv_data),
                                  void *priv_data);
 
+#if 0
 /* digest_encode.c */
 #define EXT2FS_DIGEST_SIZE EXT2FS_SHA256_LENGTH
-extern int ext2fs_digest_encode(const char *src, unsigned long len, char *dst);
+extern int ext2fs_digest_encode(const char *src, int len, char *dst);
+extern int ext2fs_digest_decode(const char *src, int len, char *dst);
+#endif
 
 /* dirblock.c */
 extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
@@ -1564,10 +1567,12 @@ extern errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
 /* res_gdt.c */
 extern errcode_t ext2fs_create_resize_inode(ext2_filsys fs);
 
+#if 0
 /*sha256.c */
 #define EXT2FS_SHA256_LENGTH 32
 extern void ext2fs_sha256(const unsigned char *in, unsigned long in_size,
                   unsigned char out[EXT2FS_SHA256_LENGTH]);
+#endif
 
 /* sha512.c */
 #define EXT2FS_SHA512_LENGTH 64
index f2b30cdf5da03f04cb5295d6f9f02ba7137449c6..b99421a4ee9976e8c1b6d0290d967fa48081febd 100644 (file)
@@ -95,6 +95,18 @@ static const size_t hexchars_size = 16;
 #define EXT4_IOC_SET_ENCRYPTION_POLICY      _IOR('f', 19, struct ext4_encryption_policy)
 #define EXT4_IOC_GET_ENCRYPTION_POLICY      _IOW('f', 21, struct ext4_encryption_policy)
 
+static int int_log2(int arg)
+{
+       int     l = 0;
+
+       arg >>= 1;
+       while (arg) {
+               l++;
+               arg >>= 1;
+       }
+       return l;
+}
+
 static void validate_paths(int argc, char *argv[], int path_start_index)
 {
        int x;
@@ -313,7 +325,7 @@ static void parse_salt(char *salt_str, int flags)
        add_salt(salt_buf, salt_len);
 }
 
-static void set_policy(struct salt *set_salt,
+static void set_policy(struct salt *set_salt, int pad,
                       int argc, char *argv[], int path_start_index)
 {
        struct salt *salt;
@@ -323,6 +335,12 @@ static void set_policy(struct salt *set_salt,
        int x;
        int rc;
 
+       if ((pad != 4) && (pad != 8) &&
+                (pad != 16) && (pad != 32)) {
+               fprintf(stderr, "Invalid padding %d\n", pad);
+               exit(1);
+       }
+
        for (x = path_start_index; x < argc; x++) {
                fd = open(argv[x], O_DIRECTORY);
                if (fd == -1) {
@@ -348,6 +366,7 @@ static void set_policy(struct salt *set_salt,
                        EXT4_ENCRYPTION_MODE_AES_256_XTS;
                policy.filenames_encryption_mode =
                        EXT4_ENCRYPTION_MODE_AES_256_CTS;
+               policy.flags = int_log2(pad >> 2);
                memcpy(policy.master_key_descriptor, salt->key_desc,
                       EXT4_KEY_DESCRIPTOR_SIZE);
                rc = ioctl(fd, EXT4_IOC_SET_ENCRYPTION_POLICY, &policy);
@@ -610,14 +629,17 @@ void do_add_key(int argc, char **argv, const struct cmd_desc *cmd)
 {
        struct salt *salt;
        char *keyring = NULL;
-       int i, opt;
+       int i, opt, pad = 4;
 
-       while ((opt = getopt(argc, argv, "k:S:vq")) != -1) {
+       while ((opt = getopt(argc, argv, "k:S:p:vq")) != -1) {
                switch (opt) {
                case 'k':
                        /* Specify a keyring. */
                        keyring = optarg;
                        break;
+               case 'p':
+                       pad = atoi(optarg);
+                       break;
                case 'S':
                        /* Salt value for passphrase. */
                        parse_salt(optarg, 0);
@@ -654,7 +676,7 @@ void do_add_key(int argc, char **argv, const struct cmd_desc *cmd)
                insert_key_into_keyring(keyring, salt);
        }
        if (optind != argc)
-               set_policy(NULL, argc, argv, optind);
+               set_policy(NULL, pad, argc, argv, optind);
        clear_secrets();
        exit(0);
 }
@@ -674,27 +696,38 @@ void do_set_policy(int argc, char **argv, const struct cmd_desc *cmd)
        char *key_ref_str = NULL;
        char *keyring = NULL;
        int add_passphrase = 0;
-       int i, opt;
+       int i, c, opt, pad = 4;
 
-       if (argc < 3) {
+       while ((c = getopt (argc, argv, "p:")) != EOF) {
+               switch (c) {
+               case 'p':
+                       pad = atoi(optarg);
+                       break;
+               }
+       }
+
+       if (argc < optind + 2) {
                fprintf(stderr, "Missing required argument(s).\n\n");
                fputs("USAGE:\n  ", stderr);
                fputs(cmd->cmd_help, stderr);
                exit(1);
        }
 
-       strcpy(saltbuf.key_ref_str, argv[1]);
-       if ((strlen(argv[1]) != (EXT4_KEY_DESCRIPTOR_SIZE * 2)) ||
-           hex2byte(argv[1], (EXT4_KEY_DESCRIPTOR_SIZE * 2),
+       printf("arg %s\n", argv[optind]);
+       exit(0);
+
+       strcpy(saltbuf.key_ref_str, argv[optind]);
+       if ((strlen(argv[optind]) != (EXT4_KEY_DESCRIPTOR_SIZE * 2)) ||
+           hex2byte(argv[optind], (EXT4_KEY_DESCRIPTOR_SIZE * 2),
                     saltbuf.key_desc, EXT4_KEY_DESCRIPTOR_SIZE)) {
                printf("Invalid key descriptor [%s]. Valid characters "
                       "are 0-9 and a-f, lower case.  "
                       "Length must be %d.\n",
-                      argv[1], (EXT4_KEY_DESCRIPTOR_SIZE * 2));
+                      argv[optind], (EXT4_KEY_DESCRIPTOR_SIZE * 2));
                        exit(1);
        }
-       validate_paths(argc, argv, 2);
-       set_policy(&saltbuf, argc, argv, 2);
+       validate_paths(argc, argv, optind+1);
+       set_policy(&saltbuf, pad, argc, argv, optind+1);
        exit(0);
 }