diff options
author | Daniel Walter <dwalter@sigma-star.at> | 2017-06-19 03:27:58 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2017-06-23 20:05:07 -0400 |
commit | b7e7cf7a66a27e62c5f873a0068cee34094bf5d7 (patch) | |
tree | e86d2bbc849e8a854e7f3a22846a08bef49423b9 | |
parent | 27e47a6342e21b005a15a1f0afea0b6f179e0a71 (diff) |
fscrypt: add support for AES-128-CBC
fscrypt provides facilities to use different encryption algorithms which
are selectable by userspace when setting the encryption policy. Currently,
only AES-256-XTS for file contents and AES-256-CBC-CTS for file names are
implemented. This is a clear case of kernel offers the mechanism and
userspace selects a policy. Similar to what dm-crypt and ecryptfs have.
This patch adds support for using AES-128-CBC for file contents and
AES-128-CBC-CTS for file name encryption. To mitigate watermarking
attacks, IVs are generated using the ESSIV algorithm. While AES-CBC is
actually slightly less secure than AES-XTS from a security point of view,
there is more widespread hardware support. Using AES-CBC gives us the
acceptable performance while still providing a moderate level of security
for persistent storage.
Especially low-powered embedded devices with crypto accelerators such as
CAAM or CESA often only support AES-CBC. Since using AES-CBC over AES-XTS
is basically thought of a last resort, we use AES-128-CBC over AES-256-CBC
since it has less encryption rounds and yields noticeable better
performance starting from a file size of just a few kB.
Signed-off-by: Daniel Walter <dwalter@sigma-star.at>
[david@sigma-star.at: addressed review comments]
Signed-off-by: David Gstir <david@sigma-star.at>
Reviewed-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r-- | fs/crypto/Kconfig | 1 | ||||
-rw-r--r-- | fs/crypto/crypto.c | 23 | ||||
-rw-r--r-- | fs/crypto/fscrypt_private.h | 9 | ||||
-rw-r--r-- | fs/crypto/keyinfo.c | 173 | ||||
-rw-r--r-- | fs/crypto/policy.c | 8 | ||||
-rw-r--r-- | include/linux/fscrypt_common.h | 16 | ||||
-rw-r--r-- | include/uapi/linux/fs.h | 2 |
7 files changed, 174 insertions, 58 deletions
diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig index 08b46e6e3995..02b7d91c9231 100644 --- a/fs/crypto/Kconfig +++ b/fs/crypto/Kconfig | |||
@@ -7,6 +7,7 @@ config FS_ENCRYPTION | |||
7 | select CRYPTO_XTS | 7 | select CRYPTO_XTS |
8 | select CRYPTO_CTS | 8 | select CRYPTO_CTS |
9 | select CRYPTO_CTR | 9 | select CRYPTO_CTR |
10 | select CRYPTO_SHA256 | ||
10 | select KEYS | 11 | select KEYS |
11 | help | 12 | help |
12 | Enable encryption of files and directories. This | 13 | Enable encryption of files and directories. This |
diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 6d6eca394d4d..c7835df7e7b8 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/ratelimit.h> | 26 | #include <linux/ratelimit.h> |
27 | #include <linux/dcache.h> | 27 | #include <linux/dcache.h> |
28 | #include <linux/namei.h> | 28 | #include <linux/namei.h> |
29 | #include <crypto/aes.h> | ||
29 | #include "fscrypt_private.h" | 30 | #include "fscrypt_private.h" |
30 | 31 | ||
31 | static unsigned int num_prealloc_crypto_pages = 32; | 32 | static unsigned int num_prealloc_crypto_pages = 32; |
@@ -147,8 +148,8 @@ int fscrypt_do_page_crypto(const struct inode *inode, fscrypt_direction_t rw, | |||
147 | { | 148 | { |
148 | struct { | 149 | struct { |
149 | __le64 index; | 150 | __le64 index; |
150 | u8 padding[FS_XTS_TWEAK_SIZE - sizeof(__le64)]; | 151 | u8 padding[FS_IV_SIZE - sizeof(__le64)]; |
151 | } xts_tweak; | 152 | } iv; |
152 | struct skcipher_request *req = NULL; | 153 | struct skcipher_request *req = NULL; |
153 | DECLARE_FS_COMPLETION_RESULT(ecr); | 154 | DECLARE_FS_COMPLETION_RESULT(ecr); |
154 | struct scatterlist dst, src; | 155 | struct scatterlist dst, src; |
@@ -158,6 +159,16 @@ int fscrypt_do_page_crypto(const struct inode *inode, fscrypt_direction_t rw, | |||
158 | 159 | ||
159 | BUG_ON(len == 0); | 160 | BUG_ON(len == 0); |
160 | 161 | ||
162 | BUILD_BUG_ON(sizeof(iv) != FS_IV_SIZE); | ||
163 | BUILD_BUG_ON(AES_BLOCK_SIZE != FS_IV_SIZE); | ||
164 | iv.index = cpu_to_le64(lblk_num); | ||
165 | memset(iv.padding, 0, sizeof(iv.padding)); | ||
166 | |||
167 | if (ci->ci_essiv_tfm != NULL) { | ||
168 | crypto_cipher_encrypt_one(ci->ci_essiv_tfm, (u8 *)&iv, | ||
169 | (u8 *)&iv); | ||
170 | } | ||
171 | |||
161 | req = skcipher_request_alloc(tfm, gfp_flags); | 172 | req = skcipher_request_alloc(tfm, gfp_flags); |
162 | if (!req) { | 173 | if (!req) { |
163 | printk_ratelimited(KERN_ERR | 174 | printk_ratelimited(KERN_ERR |
@@ -170,15 +181,11 @@ int fscrypt_do_page_crypto(const struct inode *inode, fscrypt_direction_t rw, | |||
170 | req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, | 181 | req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, |
171 | page_crypt_complete, &ecr); | 182 | page_crypt_complete, &ecr); |
172 | 183 | ||
173 | BUILD_BUG_ON(sizeof(xts_tweak) != FS_XTS_TWEAK_SIZE); | ||
174 | xts_tweak.index = cpu_to_le64(lblk_num); | ||
175 | memset(xts_tweak.padding, 0, sizeof(xts_tweak.padding)); | ||
176 | |||
177 | sg_init_table(&dst, 1); | 184 | sg_init_table(&dst, 1); |
178 | sg_set_page(&dst, dest_page, len, offs); | 185 | sg_set_page(&dst, dest_page, len, offs); |
179 | sg_init_table(&src, 1); | 186 | sg_init_table(&src, 1); |
180 | sg_set_page(&src, src_page, len, offs); | 187 | sg_set_page(&src, src_page, len, offs); |
181 | skcipher_request_set_crypt(req, &src, &dst, len, &xts_tweak); | 188 | skcipher_request_set_crypt(req, &src, &dst, len, &iv); |
182 | if (rw == FS_DECRYPT) | 189 | if (rw == FS_DECRYPT) |
183 | res = crypto_skcipher_decrypt(req); | 190 | res = crypto_skcipher_decrypt(req); |
184 | else | 191 | else |
@@ -477,6 +484,8 @@ static void __exit fscrypt_exit(void) | |||
477 | destroy_workqueue(fscrypt_read_workqueue); | 484 | destroy_workqueue(fscrypt_read_workqueue); |
478 | kmem_cache_destroy(fscrypt_ctx_cachep); | 485 | kmem_cache_destroy(fscrypt_ctx_cachep); |
479 | kmem_cache_destroy(fscrypt_info_cachep); | 486 | kmem_cache_destroy(fscrypt_info_cachep); |
487 | |||
488 | fscrypt_essiv_cleanup(); | ||
480 | } | 489 | } |
481 | module_exit(fscrypt_exit); | 490 | module_exit(fscrypt_exit); |
482 | 491 | ||
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 1e1f8a361b75..a1d5021c31ef 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h | |||
@@ -12,10 +12,13 @@ | |||
12 | #define _FSCRYPT_PRIVATE_H | 12 | #define _FSCRYPT_PRIVATE_H |
13 | 13 | ||
14 | #include <linux/fscrypt_supp.h> | 14 | #include <linux/fscrypt_supp.h> |
15 | #include <crypto/hash.h> | ||
15 | 16 | ||
16 | /* Encryption parameters */ | 17 | /* Encryption parameters */ |
17 | #define FS_XTS_TWEAK_SIZE 16 | 18 | #define FS_IV_SIZE 16 |
18 | #define FS_AES_128_ECB_KEY_SIZE 16 | 19 | #define FS_AES_128_ECB_KEY_SIZE 16 |
20 | #define FS_AES_128_CBC_KEY_SIZE 16 | ||
21 | #define FS_AES_128_CTS_KEY_SIZE 16 | ||
19 | #define FS_AES_256_GCM_KEY_SIZE 32 | 22 | #define FS_AES_256_GCM_KEY_SIZE 32 |
20 | #define FS_AES_256_CBC_KEY_SIZE 32 | 23 | #define FS_AES_256_CBC_KEY_SIZE 32 |
21 | #define FS_AES_256_CTS_KEY_SIZE 32 | 24 | #define FS_AES_256_CTS_KEY_SIZE 32 |
@@ -54,6 +57,7 @@ struct fscrypt_info { | |||
54 | u8 ci_filename_mode; | 57 | u8 ci_filename_mode; |
55 | u8 ci_flags; | 58 | u8 ci_flags; |
56 | struct crypto_skcipher *ci_ctfm; | 59 | struct crypto_skcipher *ci_ctfm; |
60 | struct crypto_cipher *ci_essiv_tfm; | ||
57 | u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE]; | 61 | u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE]; |
58 | }; | 62 | }; |
59 | 63 | ||
@@ -87,4 +91,7 @@ extern int fscrypt_do_page_crypto(const struct inode *inode, | |||
87 | extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, | 91 | extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, |
88 | gfp_t gfp_flags); | 92 | gfp_t gfp_flags); |
89 | 93 | ||
94 | /* keyinfo.c */ | ||
95 | extern void __exit fscrypt_essiv_cleanup(void); | ||
96 | |||
90 | #endif /* _FSCRYPT_PRIVATE_H */ | 97 | #endif /* _FSCRYPT_PRIVATE_H */ |
diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 179e578b875b..018c588c7ac3 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c | |||
@@ -10,8 +10,13 @@ | |||
10 | 10 | ||
11 | #include <keys/user-type.h> | 11 | #include <keys/user-type.h> |
12 | #include <linux/scatterlist.h> | 12 | #include <linux/scatterlist.h> |
13 | #include <linux/ratelimit.h> | ||
14 | #include <crypto/aes.h> | ||
15 | #include <crypto/sha.h> | ||
13 | #include "fscrypt_private.h" | 16 | #include "fscrypt_private.h" |
14 | 17 | ||
18 | static struct crypto_shash *essiv_hash_tfm; | ||
19 | |||
15 | static void derive_crypt_complete(struct crypto_async_request *req, int rc) | 20 | static void derive_crypt_complete(struct crypto_async_request *req, int rc) |
16 | { | 21 | { |
17 | struct fscrypt_completion_result *ecr = req->data; | 22 | struct fscrypt_completion_result *ecr = req->data; |
@@ -27,13 +32,13 @@ static void derive_crypt_complete(struct crypto_async_request *req, int rc) | |||
27 | * derive_key_aes() - Derive a key using AES-128-ECB | 32 | * derive_key_aes() - Derive a key using AES-128-ECB |
28 | * @deriving_key: Encryption key used for derivation. | 33 | * @deriving_key: Encryption key used for derivation. |
29 | * @source_key: Source key to which to apply derivation. | 34 | * @source_key: Source key to which to apply derivation. |
30 | * @derived_key: Derived key. | 35 | * @derived_raw_key: Derived raw key. |
31 | * | 36 | * |
32 | * Return: Zero on success; non-zero otherwise. | 37 | * Return: Zero on success; non-zero otherwise. |
33 | */ | 38 | */ |
34 | static int derive_key_aes(u8 deriving_key[FS_AES_128_ECB_KEY_SIZE], | 39 | static int derive_key_aes(u8 deriving_key[FS_AES_128_ECB_KEY_SIZE], |
35 | u8 source_key[FS_AES_256_XTS_KEY_SIZE], | 40 | const struct fscrypt_key *source_key, |
36 | u8 derived_key[FS_AES_256_XTS_KEY_SIZE]) | 41 | u8 derived_raw_key[FS_MAX_KEY_SIZE]) |
37 | { | 42 | { |
38 | int res = 0; | 43 | int res = 0; |
39 | struct skcipher_request *req = NULL; | 44 | struct skcipher_request *req = NULL; |
@@ -60,10 +65,10 @@ static int derive_key_aes(u8 deriving_key[FS_AES_128_ECB_KEY_SIZE], | |||
60 | if (res < 0) | 65 | if (res < 0) |
61 | goto out; | 66 | goto out; |
62 | 67 | ||
63 | sg_init_one(&src_sg, source_key, FS_AES_256_XTS_KEY_SIZE); | 68 | sg_init_one(&src_sg, source_key->raw, source_key->size); |
64 | sg_init_one(&dst_sg, derived_key, FS_AES_256_XTS_KEY_SIZE); | 69 | sg_init_one(&dst_sg, derived_raw_key, source_key->size); |
65 | skcipher_request_set_crypt(req, &src_sg, &dst_sg, | 70 | skcipher_request_set_crypt(req, &src_sg, &dst_sg, source_key->size, |
66 | FS_AES_256_XTS_KEY_SIZE, NULL); | 71 | NULL); |
67 | res = crypto_skcipher_encrypt(req); | 72 | res = crypto_skcipher_encrypt(req); |
68 | if (res == -EINPROGRESS || res == -EBUSY) { | 73 | if (res == -EINPROGRESS || res == -EBUSY) { |
69 | wait_for_completion(&ecr.completion); | 74 | wait_for_completion(&ecr.completion); |
@@ -77,7 +82,7 @@ out: | |||
77 | 82 | ||
78 | static int validate_user_key(struct fscrypt_info *crypt_info, | 83 | static int validate_user_key(struct fscrypt_info *crypt_info, |
79 | struct fscrypt_context *ctx, u8 *raw_key, | 84 | struct fscrypt_context *ctx, u8 *raw_key, |
80 | const char *prefix) | 85 | const char *prefix, int min_keysize) |
81 | { | 86 | { |
82 | char *description; | 87 | char *description; |
83 | struct key *keyring_key; | 88 | struct key *keyring_key; |
@@ -111,50 +116,60 @@ static int validate_user_key(struct fscrypt_info *crypt_info, | |||
111 | master_key = (struct fscrypt_key *)ukp->data; | 116 | master_key = (struct fscrypt_key *)ukp->data; |
112 | BUILD_BUG_ON(FS_AES_128_ECB_KEY_SIZE != FS_KEY_DERIVATION_NONCE_SIZE); | 117 | BUILD_BUG_ON(FS_AES_128_ECB_KEY_SIZE != FS_KEY_DERIVATION_NONCE_SIZE); |
113 | 118 | ||
114 | if (master_key->size != FS_AES_256_XTS_KEY_SIZE) { | 119 | if (master_key->size < min_keysize || master_key->size > FS_MAX_KEY_SIZE |
120 | || master_key->size % AES_BLOCK_SIZE != 0) { | ||
115 | printk_once(KERN_WARNING | 121 | printk_once(KERN_WARNING |
116 | "%s: key size incorrect: %d\n", | 122 | "%s: key size incorrect: %d\n", |
117 | __func__, master_key->size); | 123 | __func__, master_key->size); |
118 | res = -ENOKEY; | 124 | res = -ENOKEY; |
119 | goto out; | 125 | goto out; |
120 | } | 126 | } |
121 | res = derive_key_aes(ctx->nonce, master_key->raw, raw_key); | 127 | res = derive_key_aes(ctx->nonce, master_key, raw_key); |
122 | out: | 128 | out: |
123 | up_read(&keyring_key->sem); | 129 | up_read(&keyring_key->sem); |
124 | key_put(keyring_key); | 130 | key_put(keyring_key); |
125 | return res; | 131 | return res; |
126 | } | 132 | } |
127 | 133 | ||
134 | static const struct { | ||
135 | const char *cipher_str; | ||
136 | int keysize; | ||
137 | } available_modes[] = { | ||
138 | [FS_ENCRYPTION_MODE_AES_256_XTS] = { "xts(aes)", | ||
139 | FS_AES_256_XTS_KEY_SIZE }, | ||
140 | [FS_ENCRYPTION_MODE_AES_256_CTS] = { "cts(cbc(aes))", | ||
141 | FS_AES_256_CTS_KEY_SIZE }, | ||
142 | [FS_ENCRYPTION_MODE_AES_128_CBC] = { "cbc(aes)", | ||
143 | FS_AES_128_CBC_KEY_SIZE }, | ||
144 | [FS_ENCRYPTION_MODE_AES_128_CTS] = { "cts(cbc(aes))", | ||
145 | FS_AES_128_CTS_KEY_SIZE }, | ||
146 | }; | ||
147 | |||
128 | static int determine_cipher_type(struct fscrypt_info *ci, struct inode *inode, | 148 | static int determine_cipher_type(struct fscrypt_info *ci, struct inode *inode, |
129 | const char **cipher_str_ret, int *keysize_ret) | 149 | const char **cipher_str_ret, int *keysize_ret) |
130 | { | 150 | { |
131 | if (S_ISREG(inode->i_mode)) { | 151 | u32 mode; |
132 | if (ci->ci_data_mode == FS_ENCRYPTION_MODE_AES_256_XTS) { | 152 | |
133 | *cipher_str_ret = "xts(aes)"; | 153 | if (!fscrypt_valid_enc_modes(ci->ci_data_mode, ci->ci_filename_mode)) { |
134 | *keysize_ret = FS_AES_256_XTS_KEY_SIZE; | 154 | pr_warn_ratelimited("fscrypt: inode %lu uses unsupported encryption modes (contents mode %d, filenames mode %d)\n", |
135 | return 0; | 155 | inode->i_ino, |
136 | } | 156 | ci->ci_data_mode, ci->ci_filename_mode); |
137 | pr_warn_once("fscrypto: unsupported contents encryption mode " | 157 | return -EINVAL; |
138 | "%d for inode %lu\n", | ||
139 | ci->ci_data_mode, inode->i_ino); | ||
140 | return -ENOKEY; | ||
141 | } | 158 | } |
142 | 159 | ||
143 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) { | 160 | if (S_ISREG(inode->i_mode)) { |
144 | if (ci->ci_filename_mode == FS_ENCRYPTION_MODE_AES_256_CTS) { | 161 | mode = ci->ci_data_mode; |
145 | *cipher_str_ret = "cts(cbc(aes))"; | 162 | } else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) { |
146 | *keysize_ret = FS_AES_256_CTS_KEY_SIZE; | 163 | mode = ci->ci_filename_mode; |
147 | return 0; | 164 | } else { |
148 | } | 165 | WARN_ONCE(1, "fscrypt: filesystem tried to load encryption info for inode %lu, which is not encryptable (file type %d)\n", |
149 | pr_warn_once("fscrypto: unsupported filenames encryption mode " | 166 | inode->i_ino, (inode->i_mode & S_IFMT)); |
150 | "%d for inode %lu\n", | 167 | return -EINVAL; |
151 | ci->ci_filename_mode, inode->i_ino); | ||
152 | return -ENOKEY; | ||
153 | } | 168 | } |
154 | 169 | ||
155 | pr_warn_once("fscrypto: unsupported file type %d for inode %lu\n", | 170 | *cipher_str_ret = available_modes[mode].cipher_str; |
156 | (inode->i_mode & S_IFMT), inode->i_ino); | 171 | *keysize_ret = available_modes[mode].keysize; |
157 | return -ENOKEY; | 172 | return 0; |
158 | } | 173 | } |
159 | 174 | ||
160 | static void put_crypt_info(struct fscrypt_info *ci) | 175 | static void put_crypt_info(struct fscrypt_info *ci) |
@@ -163,9 +178,76 @@ static void put_crypt_info(struct fscrypt_info *ci) | |||
163 | return; | 178 | return; |
164 | 179 | ||
165 | crypto_free_skcipher(ci->ci_ctfm); | 180 | crypto_free_skcipher(ci->ci_ctfm); |
181 | crypto_free_cipher(ci->ci_essiv_tfm); | ||
166 | kmem_cache_free(fscrypt_info_cachep, ci); | 182 | kmem_cache_free(fscrypt_info_cachep, ci); |
167 | } | 183 | } |
168 | 184 | ||
185 | static int derive_essiv_salt(const u8 *key, int keysize, u8 *salt) | ||
186 | { | ||
187 | struct crypto_shash *tfm = READ_ONCE(essiv_hash_tfm); | ||
188 | |||
189 | /* init hash transform on demand */ | ||
190 | if (unlikely(!tfm)) { | ||
191 | struct crypto_shash *prev_tfm; | ||
192 | |||
193 | tfm = crypto_alloc_shash("sha256", 0, 0); | ||
194 | if (IS_ERR(tfm)) { | ||
195 | pr_warn_ratelimited("fscrypt: error allocating SHA-256 transform: %ld\n", | ||
196 | PTR_ERR(tfm)); | ||
197 | return PTR_ERR(tfm); | ||
198 | } | ||
199 | prev_tfm = cmpxchg(&essiv_hash_tfm, NULL, tfm); | ||
200 | if (prev_tfm) { | ||
201 | crypto_free_shash(tfm); | ||
202 | tfm = prev_tfm; | ||
203 | } | ||
204 | } | ||
205 | |||
206 | { | ||
207 | SHASH_DESC_ON_STACK(desc, tfm); | ||
208 | desc->tfm = tfm; | ||
209 | desc->flags = 0; | ||
210 | |||
211 | return crypto_shash_digest(desc, key, keysize, salt); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | static int init_essiv_generator(struct fscrypt_info *ci, const u8 *raw_key, | ||
216 | int keysize) | ||
217 | { | ||
218 | int err; | ||
219 | struct crypto_cipher *essiv_tfm; | ||
220 | u8 salt[SHA256_DIGEST_SIZE]; | ||
221 | |||
222 | essiv_tfm = crypto_alloc_cipher("aes", 0, 0); | ||
223 | if (IS_ERR(essiv_tfm)) | ||
224 | return PTR_ERR(essiv_tfm); | ||
225 | |||
226 | ci->ci_essiv_tfm = essiv_tfm; | ||
227 | |||
228 | err = derive_essiv_salt(raw_key, keysize, salt); | ||
229 | if (err) | ||
230 | goto out; | ||
231 | |||
232 | /* | ||
233 | * Using SHA256 to derive the salt/key will result in AES-256 being | ||
234 | * used for IV generation. File contents encryption will still use the | ||
235 | * configured keysize (AES-128) nevertheless. | ||
236 | */ | ||
237 | err = crypto_cipher_setkey(essiv_tfm, salt, sizeof(salt)); | ||
238 | if (err) | ||
239 | goto out; | ||
240 | |||
241 | out: | ||
242 | memzero_explicit(salt, sizeof(salt)); | ||
243 | return err; | ||
244 | } | ||
245 | |||
246 | void __exit fscrypt_essiv_cleanup(void) | ||
247 | { | ||
248 | crypto_free_shash(essiv_hash_tfm); | ||
249 | } | ||
250 | |||
169 | int fscrypt_get_encryption_info(struct inode *inode) | 251 | int fscrypt_get_encryption_info(struct inode *inode) |
170 | { | 252 | { |
171 | struct fscrypt_info *crypt_info; | 253 | struct fscrypt_info *crypt_info; |
@@ -212,6 +294,7 @@ int fscrypt_get_encryption_info(struct inode *inode) | |||
212 | crypt_info->ci_data_mode = ctx.contents_encryption_mode; | 294 | crypt_info->ci_data_mode = ctx.contents_encryption_mode; |
213 | crypt_info->ci_filename_mode = ctx.filenames_encryption_mode; | 295 | crypt_info->ci_filename_mode = ctx.filenames_encryption_mode; |
214 | crypt_info->ci_ctfm = NULL; | 296 | crypt_info->ci_ctfm = NULL; |
297 | crypt_info->ci_essiv_tfm = NULL; | ||
215 | memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor, | 298 | memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor, |
216 | sizeof(crypt_info->ci_master_key)); | 299 | sizeof(crypt_info->ci_master_key)); |
217 | 300 | ||
@@ -228,10 +311,12 @@ int fscrypt_get_encryption_info(struct inode *inode) | |||
228 | if (!raw_key) | 311 | if (!raw_key) |
229 | goto out; | 312 | goto out; |
230 | 313 | ||
231 | res = validate_user_key(crypt_info, &ctx, raw_key, FS_KEY_DESC_PREFIX); | 314 | res = validate_user_key(crypt_info, &ctx, raw_key, FS_KEY_DESC_PREFIX, |
315 | keysize); | ||
232 | if (res && inode->i_sb->s_cop->key_prefix) { | 316 | if (res && inode->i_sb->s_cop->key_prefix) { |
233 | int res2 = validate_user_key(crypt_info, &ctx, raw_key, | 317 | int res2 = validate_user_key(crypt_info, &ctx, raw_key, |
234 | inode->i_sb->s_cop->key_prefix); | 318 | inode->i_sb->s_cop->key_prefix, |
319 | keysize); | ||
235 | if (res2) { | 320 | if (res2) { |
236 | if (res2 == -ENOKEY) | 321 | if (res2 == -ENOKEY) |
237 | res = -ENOKEY; | 322 | res = -ENOKEY; |
@@ -243,18 +328,30 @@ int fscrypt_get_encryption_info(struct inode *inode) | |||
243 | ctfm = crypto_alloc_skcipher(cipher_str, 0, 0); | 328 | ctfm = crypto_alloc_skcipher(cipher_str, 0, 0); |
244 | if (!ctfm || IS_ERR(ctfm)) { | 329 | if (!ctfm || IS_ERR(ctfm)) { |
245 | res = ctfm ? PTR_ERR(ctfm) : -ENOMEM; | 330 | res = ctfm ? PTR_ERR(ctfm) : -ENOMEM; |
246 | printk(KERN_DEBUG | 331 | pr_debug("%s: error %d (inode %lu) allocating crypto tfm\n", |
247 | "%s: error %d (inode %u) allocating crypto tfm\n", | 332 | __func__, res, inode->i_ino); |
248 | __func__, res, (unsigned) inode->i_ino); | ||
249 | goto out; | 333 | goto out; |
250 | } | 334 | } |
251 | crypt_info->ci_ctfm = ctfm; | 335 | crypt_info->ci_ctfm = ctfm; |
252 | crypto_skcipher_clear_flags(ctfm, ~0); | 336 | crypto_skcipher_clear_flags(ctfm, ~0); |
253 | crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_REQ_WEAK_KEY); | 337 | crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_REQ_WEAK_KEY); |
338 | /* | ||
339 | * if the provided key is longer than keysize, we use the first | ||
340 | * keysize bytes of the derived key only | ||
341 | */ | ||
254 | res = crypto_skcipher_setkey(ctfm, raw_key, keysize); | 342 | res = crypto_skcipher_setkey(ctfm, raw_key, keysize); |
255 | if (res) | 343 | if (res) |
256 | goto out; | 344 | goto out; |
257 | 345 | ||
346 | if (S_ISREG(inode->i_mode) && | ||
347 | crypt_info->ci_data_mode == FS_ENCRYPTION_MODE_AES_128_CBC) { | ||
348 | res = init_essiv_generator(crypt_info, raw_key, keysize); | ||
349 | if (res) { | ||
350 | pr_debug("%s: error %d (inode %lu) allocating essiv tfm\n", | ||
351 | __func__, res, inode->i_ino); | ||
352 | goto out; | ||
353 | } | ||
354 | } | ||
258 | if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL) | 355 | if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL) |
259 | crypt_info = NULL; | 356 | crypt_info = NULL; |
260 | out: | 357 | out: |
diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index 210976e7a269..9914d51dff86 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c | |||
@@ -38,12 +38,8 @@ static int create_encryption_context_from_policy(struct inode *inode, | |||
38 | memcpy(ctx.master_key_descriptor, policy->master_key_descriptor, | 38 | memcpy(ctx.master_key_descriptor, policy->master_key_descriptor, |
39 | FS_KEY_DESCRIPTOR_SIZE); | 39 | FS_KEY_DESCRIPTOR_SIZE); |
40 | 40 | ||
41 | if (!fscrypt_valid_contents_enc_mode( | 41 | if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, |
42 | policy->contents_encryption_mode)) | 42 | policy->filenames_encryption_mode)) |
43 | return -EINVAL; | ||
44 | |||
45 | if (!fscrypt_valid_filenames_enc_mode( | ||
46 | policy->filenames_encryption_mode)) | ||
47 | return -EINVAL; | 43 | return -EINVAL; |
48 | 44 | ||
49 | if (policy->flags & ~FS_POLICY_FLAGS_VALID) | 45 | if (policy->flags & ~FS_POLICY_FLAGS_VALID) |
diff --git a/include/linux/fscrypt_common.h b/include/linux/fscrypt_common.h index 0a30c106c1e5..4022c61f7e9b 100644 --- a/include/linux/fscrypt_common.h +++ b/include/linux/fscrypt_common.h | |||
@@ -91,14 +91,18 @@ static inline bool fscrypt_dummy_context_enabled(struct inode *inode) | |||
91 | return false; | 91 | return false; |
92 | } | 92 | } |
93 | 93 | ||
94 | static inline bool fscrypt_valid_contents_enc_mode(u32 mode) | 94 | static inline bool fscrypt_valid_enc_modes(u32 contents_mode, |
95 | u32 filenames_mode) | ||
95 | { | 96 | { |
96 | return (mode == FS_ENCRYPTION_MODE_AES_256_XTS); | 97 | if (contents_mode == FS_ENCRYPTION_MODE_AES_128_CBC && |
97 | } | 98 | filenames_mode == FS_ENCRYPTION_MODE_AES_128_CTS) |
99 | return true; | ||
98 | 100 | ||
99 | static inline bool fscrypt_valid_filenames_enc_mode(u32 mode) | 101 | if (contents_mode == FS_ENCRYPTION_MODE_AES_256_XTS && |
100 | { | 102 | filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS) |
101 | return (mode == FS_ENCRYPTION_MODE_AES_256_CTS); | 103 | return true; |
104 | |||
105 | return false; | ||
102 | } | 106 | } |
103 | 107 | ||
104 | static inline bool fscrypt_is_dot_dotdot(const struct qstr *str) | 108 | static inline bool fscrypt_is_dot_dotdot(const struct qstr *str) |
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 24e61a54feaa..a2a3ffb06038 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h | |||
@@ -272,6 +272,8 @@ struct fsxattr { | |||
272 | #define FS_ENCRYPTION_MODE_AES_256_GCM 2 | 272 | #define FS_ENCRYPTION_MODE_AES_256_GCM 2 |
273 | #define FS_ENCRYPTION_MODE_AES_256_CBC 3 | 273 | #define FS_ENCRYPTION_MODE_AES_256_CBC 3 |
274 | #define FS_ENCRYPTION_MODE_AES_256_CTS 4 | 274 | #define FS_ENCRYPTION_MODE_AES_256_CTS 4 |
275 | #define FS_ENCRYPTION_MODE_AES_128_CBC 5 | ||
276 | #define FS_ENCRYPTION_MODE_AES_128_CTS 6 | ||
275 | 277 | ||
276 | struct fscrypt_policy { | 278 | struct fscrypt_policy { |
277 | __u8 version; | 279 | __u8 version; |