diff options
author | Theodore Ts'o <tytso@mit.edu> | 2015-05-01 16:56:50 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2015-05-01 16:56:50 -0400 |
commit | a44cd7a05496d60fd2ba8cca080e3db8f481549b (patch) | |
tree | dd8d05d845817e4a429804d8ffe09dd68b6881e6 /fs | |
parent | 5de0b4d0cd153c471640b13aae6ae6d18d0a4603 (diff) |
ext4 crypto: add padding to filenames before encrypting
This obscures the length of the filenames, to decrease the amount of
information leakage. By default, we pad the filenames to the next 4
byte boundaries. This costs nothing, since the directory entries are
aligned to 4 byte boundaries anyway. Filenames can also be padded to
8, 16, or 32 bytes, which will consume more directory space.
Change-Id: Ibb7a0fb76d2c48e2061240a709358ff40b14f322
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/crypto_fname.c | 12 | ||||
-rw-r--r-- | fs/ext4/crypto_key.c | 1 | ||||
-rw-r--r-- | fs/ext4/crypto_policy.c | 14 | ||||
-rw-r--r-- | fs/ext4/ext4.h | 1 | ||||
-rw-r--r-- | fs/ext4/ext4_crypto.h | 11 |
5 files changed, 31 insertions, 8 deletions
diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c index 7a877e609e5f..fded02f72299 100644 --- a/fs/ext4/crypto_fname.c +++ b/fs/ext4/crypto_fname.c | |||
@@ -66,6 +66,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx, | |||
66 | int res = 0; | 66 | int res = 0; |
67 | char iv[EXT4_CRYPTO_BLOCK_SIZE]; | 67 | char iv[EXT4_CRYPTO_BLOCK_SIZE]; |
68 | struct scatterlist sg[1]; | 68 | struct scatterlist sg[1]; |
69 | int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK); | ||
69 | char *workbuf; | 70 | char *workbuf; |
70 | 71 | ||
71 | if (iname->len <= 0 || iname->len > ctx->lim) | 72 | if (iname->len <= 0 || iname->len > ctx->lim) |
@@ -73,6 +74,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx, | |||
73 | 74 | ||
74 | ciphertext_len = (iname->len < EXT4_CRYPTO_BLOCK_SIZE) ? | 75 | ciphertext_len = (iname->len < EXT4_CRYPTO_BLOCK_SIZE) ? |
75 | EXT4_CRYPTO_BLOCK_SIZE : iname->len; | 76 | EXT4_CRYPTO_BLOCK_SIZE : iname->len; |
77 | ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding); | ||
76 | ciphertext_len = (ciphertext_len > ctx->lim) | 78 | ciphertext_len = (ciphertext_len > ctx->lim) |
77 | ? ctx->lim : ciphertext_len; | 79 | ? ctx->lim : ciphertext_len; |
78 | 80 | ||
@@ -101,7 +103,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx, | |||
101 | /* Create encryption request */ | 103 | /* Create encryption request */ |
102 | sg_init_table(sg, 1); | 104 | sg_init_table(sg, 1); |
103 | sg_set_page(sg, ctx->workpage, PAGE_SIZE, 0); | 105 | sg_set_page(sg, ctx->workpage, PAGE_SIZE, 0); |
104 | ablkcipher_request_set_crypt(req, sg, sg, iname->len, iv); | 106 | ablkcipher_request_set_crypt(req, sg, sg, ciphertext_len, iv); |
105 | res = crypto_ablkcipher_encrypt(req); | 107 | res = crypto_ablkcipher_encrypt(req); |
106 | if (res == -EINPROGRESS || res == -EBUSY) { | 108 | if (res == -EINPROGRESS || res == -EBUSY) { |
107 | BUG_ON(req->base.data != &ecr); | 109 | BUG_ON(req->base.data != &ecr); |
@@ -356,6 +358,7 @@ struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx( | |||
356 | if (IS_ERR(ctx)) | 358 | if (IS_ERR(ctx)) |
357 | return ctx; | 359 | return ctx; |
358 | 360 | ||
361 | ctx->flags = ei->i_crypt_policy_flags; | ||
359 | if (ctx->has_valid_key) { | 362 | if (ctx->has_valid_key) { |
360 | if (ctx->key.mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) { | 363 | if (ctx->key.mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) { |
361 | printk_once(KERN_WARNING | 364 | printk_once(KERN_WARNING |
@@ -468,6 +471,7 @@ int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx, | |||
468 | u32 namelen) | 471 | u32 namelen) |
469 | { | 472 | { |
470 | u32 ciphertext_len; | 473 | u32 ciphertext_len; |
474 | int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK); | ||
471 | 475 | ||
472 | if (ctx == NULL) | 476 | if (ctx == NULL) |
473 | return -EIO; | 477 | return -EIO; |
@@ -475,6 +479,7 @@ int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx, | |||
475 | return -EACCES; | 479 | return -EACCES; |
476 | ciphertext_len = (namelen < EXT4_CRYPTO_BLOCK_SIZE) ? | 480 | ciphertext_len = (namelen < EXT4_CRYPTO_BLOCK_SIZE) ? |
477 | EXT4_CRYPTO_BLOCK_SIZE : namelen; | 481 | EXT4_CRYPTO_BLOCK_SIZE : namelen; |
482 | ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding); | ||
478 | ciphertext_len = (ciphertext_len > ctx->lim) | 483 | ciphertext_len = (ciphertext_len > ctx->lim) |
479 | ? ctx->lim : ciphertext_len; | 484 | ? ctx->lim : ciphertext_len; |
480 | return (int) ciphertext_len; | 485 | return (int) ciphertext_len; |
@@ -490,10 +495,13 @@ int ext4_fname_crypto_alloc_buffer(struct ext4_fname_crypto_ctx *ctx, | |||
490 | u32 ilen, struct ext4_str *crypto_str) | 495 | u32 ilen, struct ext4_str *crypto_str) |
491 | { | 496 | { |
492 | unsigned int olen; | 497 | unsigned int olen; |
498 | int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK); | ||
493 | 499 | ||
494 | if (!ctx) | 500 | if (!ctx) |
495 | return -EIO; | 501 | return -EIO; |
496 | olen = ext4_fname_crypto_round_up(ilen, EXT4_CRYPTO_BLOCK_SIZE); | 502 | if (padding < EXT4_CRYPTO_BLOCK_SIZE) |
503 | padding = EXT4_CRYPTO_BLOCK_SIZE; | ||
504 | olen = ext4_fname_crypto_round_up(ilen, padding); | ||
497 | crypto_str->len = olen; | 505 | crypto_str->len = olen; |
498 | if (olen < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2) | 506 | if (olen < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2) |
499 | olen = EXT4_FNAME_CRYPTO_DIGEST_SIZE*2; | 507 | olen = EXT4_FNAME_CRYPTO_DIGEST_SIZE*2; |
diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c index c8392af8abbb..52170d0b7c40 100644 --- a/fs/ext4/crypto_key.c +++ b/fs/ext4/crypto_key.c | |||
@@ -110,6 +110,7 @@ int ext4_generate_encryption_key(struct inode *inode) | |||
110 | } | 110 | } |
111 | res = 0; | 111 | res = 0; |
112 | 112 | ||
113 | ei->i_crypt_policy_flags = ctx.flags; | ||
113 | if (S_ISREG(inode->i_mode)) | 114 | if (S_ISREG(inode->i_mode)) |
114 | crypt_key->mode = ctx.contents_encryption_mode; | 115 | crypt_key->mode = ctx.contents_encryption_mode; |
115 | else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) | 116 | else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) |
diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c index 30eaf9e9864a..a6d6291aea16 100644 --- a/fs/ext4/crypto_policy.c +++ b/fs/ext4/crypto_policy.c | |||
@@ -37,6 +37,8 @@ static int ext4_is_encryption_context_consistent_with_policy( | |||
37 | return 0; | 37 | return 0; |
38 | return (memcmp(ctx.master_key_descriptor, policy->master_key_descriptor, | 38 | return (memcmp(ctx.master_key_descriptor, policy->master_key_descriptor, |
39 | EXT4_KEY_DESCRIPTOR_SIZE) == 0 && | 39 | EXT4_KEY_DESCRIPTOR_SIZE) == 0 && |
40 | (ctx.flags == | ||
41 | policy->flags) && | ||
40 | (ctx.contents_encryption_mode == | 42 | (ctx.contents_encryption_mode == |
41 | policy->contents_encryption_mode) && | 43 | policy->contents_encryption_mode) && |
42 | (ctx.filenames_encryption_mode == | 44 | (ctx.filenames_encryption_mode == |
@@ -56,25 +58,25 @@ static int ext4_create_encryption_context_from_policy( | |||
56 | printk(KERN_WARNING | 58 | printk(KERN_WARNING |
57 | "%s: Invalid contents encryption mode %d\n", __func__, | 59 | "%s: Invalid contents encryption mode %d\n", __func__, |
58 | policy->contents_encryption_mode); | 60 | policy->contents_encryption_mode); |
59 | res = -EINVAL; | 61 | return -EINVAL; |
60 | goto out; | ||
61 | } | 62 | } |
62 | if (!ext4_valid_filenames_enc_mode(policy->filenames_encryption_mode)) { | 63 | if (!ext4_valid_filenames_enc_mode(policy->filenames_encryption_mode)) { |
63 | printk(KERN_WARNING | 64 | printk(KERN_WARNING |
64 | "%s: Invalid filenames encryption mode %d\n", __func__, | 65 | "%s: Invalid filenames encryption mode %d\n", __func__, |
65 | policy->filenames_encryption_mode); | 66 | policy->filenames_encryption_mode); |
66 | res = -EINVAL; | 67 | return -EINVAL; |
67 | goto out; | ||
68 | } | 68 | } |
69 | if (policy->flags & ~EXT4_POLICY_FLAGS_VALID) | ||
70 | return -EINVAL; | ||
69 | ctx.contents_encryption_mode = policy->contents_encryption_mode; | 71 | ctx.contents_encryption_mode = policy->contents_encryption_mode; |
70 | ctx.filenames_encryption_mode = policy->filenames_encryption_mode; | 72 | ctx.filenames_encryption_mode = policy->filenames_encryption_mode; |
73 | ctx.flags = policy->flags; | ||
71 | BUILD_BUG_ON(sizeof(ctx.nonce) != EXT4_KEY_DERIVATION_NONCE_SIZE); | 74 | BUILD_BUG_ON(sizeof(ctx.nonce) != EXT4_KEY_DERIVATION_NONCE_SIZE); |
72 | get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE); | 75 | get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE); |
73 | 76 | ||
74 | res = ext4_xattr_set(inode, EXT4_XATTR_INDEX_ENCRYPTION, | 77 | res = ext4_xattr_set(inode, EXT4_XATTR_INDEX_ENCRYPTION, |
75 | EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx, | 78 | EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx, |
76 | sizeof(ctx), 0); | 79 | sizeof(ctx), 0); |
77 | out: | ||
78 | if (!res) | 80 | if (!res) |
79 | ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT); | 81 | ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT); |
80 | return res; | 82 | return res; |
@@ -115,6 +117,7 @@ int ext4_get_policy(struct inode *inode, struct ext4_encryption_policy *policy) | |||
115 | policy->version = 0; | 117 | policy->version = 0; |
116 | policy->contents_encryption_mode = ctx.contents_encryption_mode; | 118 | policy->contents_encryption_mode = ctx.contents_encryption_mode; |
117 | policy->filenames_encryption_mode = ctx.filenames_encryption_mode; | 119 | policy->filenames_encryption_mode = ctx.filenames_encryption_mode; |
120 | policy->flags = ctx.flags; | ||
118 | memcpy(&policy->master_key_descriptor, ctx.master_key_descriptor, | 121 | memcpy(&policy->master_key_descriptor, ctx.master_key_descriptor, |
119 | EXT4_KEY_DESCRIPTOR_SIZE); | 122 | EXT4_KEY_DESCRIPTOR_SIZE); |
120 | return 0; | 123 | return 0; |
@@ -176,6 +179,7 @@ int ext4_inherit_context(struct inode *parent, struct inode *child) | |||
176 | EXT4_ENCRYPTION_MODE_AES_256_XTS; | 179 | EXT4_ENCRYPTION_MODE_AES_256_XTS; |
177 | ctx.filenames_encryption_mode = | 180 | ctx.filenames_encryption_mode = |
178 | EXT4_ENCRYPTION_MODE_AES_256_CTS; | 181 | EXT4_ENCRYPTION_MODE_AES_256_CTS; |
182 | ctx.flags = 0; | ||
179 | memset(ctx.master_key_descriptor, 0x42, | 183 | memset(ctx.master_key_descriptor, 0x42, |
180 | EXT4_KEY_DESCRIPTOR_SIZE); | 184 | EXT4_KEY_DESCRIPTOR_SIZE); |
181 | res = 0; | 185 | res = 0; |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index dfb113816672..bca1bdc67725 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -911,6 +911,7 @@ struct ext4_inode_info { | |||
911 | 911 | ||
912 | /* on-disk additional length */ | 912 | /* on-disk additional length */ |
913 | __u16 i_extra_isize; | 913 | __u16 i_extra_isize; |
914 | char i_crypt_policy_flags; | ||
914 | 915 | ||
915 | /* Indicate the inline data space. */ | 916 | /* Indicate the inline data space. */ |
916 | u16 i_inline_off; | 917 | u16 i_inline_off; |
diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h index c2ba35a914b6..d75159c101ce 100644 --- a/fs/ext4/ext4_crypto.h +++ b/fs/ext4/ext4_crypto.h | |||
@@ -20,12 +20,20 @@ struct ext4_encryption_policy { | |||
20 | char version; | 20 | char version; |
21 | char contents_encryption_mode; | 21 | char contents_encryption_mode; |
22 | char filenames_encryption_mode; | 22 | char filenames_encryption_mode; |
23 | char flags; | ||
23 | char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE]; | 24 | char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE]; |
24 | } __attribute__((__packed__)); | 25 | } __attribute__((__packed__)); |
25 | 26 | ||
26 | #define EXT4_ENCRYPTION_CONTEXT_FORMAT_V1 1 | 27 | #define EXT4_ENCRYPTION_CONTEXT_FORMAT_V1 1 |
27 | #define EXT4_KEY_DERIVATION_NONCE_SIZE 16 | 28 | #define EXT4_KEY_DERIVATION_NONCE_SIZE 16 |
28 | 29 | ||
30 | #define EXT4_POLICY_FLAGS_PAD_4 0x00 | ||
31 | #define EXT4_POLICY_FLAGS_PAD_8 0x01 | ||
32 | #define EXT4_POLICY_FLAGS_PAD_16 0x02 | ||
33 | #define EXT4_POLICY_FLAGS_PAD_32 0x03 | ||
34 | #define EXT4_POLICY_FLAGS_PAD_MASK 0x03 | ||
35 | #define EXT4_POLICY_FLAGS_VALID 0x03 | ||
36 | |||
29 | /** | 37 | /** |
30 | * Encryption context for inode | 38 | * Encryption context for inode |
31 | * | 39 | * |
@@ -41,7 +49,7 @@ struct ext4_encryption_context { | |||
41 | char format; | 49 | char format; |
42 | char contents_encryption_mode; | 50 | char contents_encryption_mode; |
43 | char filenames_encryption_mode; | 51 | char filenames_encryption_mode; |
44 | char reserved; | 52 | char flags; |
45 | char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE]; | 53 | char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE]; |
46 | char nonce[EXT4_KEY_DERIVATION_NONCE_SIZE]; | 54 | char nonce[EXT4_KEY_DERIVATION_NONCE_SIZE]; |
47 | } __attribute__((__packed__)); | 55 | } __attribute__((__packed__)); |
@@ -120,6 +128,7 @@ struct ext4_fname_crypto_ctx { | |||
120 | struct crypto_hash *htfm; | 128 | struct crypto_hash *htfm; |
121 | struct page *workpage; | 129 | struct page *workpage; |
122 | struct ext4_encryption_key key; | 130 | struct ext4_encryption_key key; |
131 | unsigned flags : 8; | ||
123 | unsigned has_valid_key : 1; | 132 | unsigned has_valid_key : 1; |
124 | unsigned ctfm_key_is_ready : 1; | 133 | unsigned ctfm_key_is_ready : 1; |
125 | }; | 134 | }; |