add patch improve-warning-directory-handling-messages
[ext4-patch-queue.git] / separate-kernel-and-user-structure-for-encryption-key
blob548fafa84173712d184cf89ae62fd7ab1f143542
1 ext4 crypto: separate kernel and userspace structure for the key
3 Use struct ext4_encryption_key only for the master key passed via the
4 kernel keyring.
6 For internal kernel space users, we now use struct ext4_crypt_info.
7 This will allow us to put information from the policy structure so we
8 can cache it and avoid needing to constantly looking up the extended
9 attribute.  We will do this in a spearate patch.  This patch is mostly
10 mechnical to make it easier for patch review.
12 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
13 ---
14  fs/ext4/crypto.c       | 18 +++++++++---------
15  fs/ext4/crypto_fname.c | 33 ++++++++++-----------------------
16  fs/ext4/crypto_key.c   | 21 +++++++++++----------
17  fs/ext4/ext4.h         |  2 +-
18  fs/ext4/ext4_crypto.h  | 15 +++++++++++----
19  fs/ext4/super.c        |  2 +-
20  6 files changed, 43 insertions(+), 48 deletions(-)
22 diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
23 index 8ff1527..918200e 100644
24 --- a/fs/ext4/crypto.c
25 +++ b/fs/ext4/crypto.c
26 @@ -118,7 +118,7 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
27         struct ext4_crypto_ctx *ctx = NULL;
28         int res = 0;
29         unsigned long flags;
30 -       struct ext4_encryption_key *key = &EXT4_I(inode)->i_encryption_key;
31 +       struct ext4_crypt_info *ci = &EXT4_I(inode)->i_crypt_info;
33         if (!ext4_read_workqueue)
34                 ext4_init_crypto();
35 @@ -152,14 +152,14 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
37         /* Allocate a new Crypto API context if we don't already have
38          * one or if it isn't the right mode. */
39 -       BUG_ON(key->mode == EXT4_ENCRYPTION_MODE_INVALID);
40 -       if (ctx->tfm && (ctx->mode != key->mode)) {
41 +       BUG_ON(ci->ci_mode == EXT4_ENCRYPTION_MODE_INVALID);
42 +       if (ctx->tfm && (ctx->mode != ci->ci_mode)) {
43                 crypto_free_tfm(ctx->tfm);
44                 ctx->tfm = NULL;
45                 ctx->mode = EXT4_ENCRYPTION_MODE_INVALID;
46         }
47         if (!ctx->tfm) {
48 -               switch (key->mode) {
49 +               switch (ci->ci_mode) {
50                 case EXT4_ENCRYPTION_MODE_AES_256_XTS:
51                         ctx->tfm = crypto_ablkcipher_tfm(
52                                 crypto_alloc_ablkcipher("xts(aes)", 0, 0));
53 @@ -177,9 +177,9 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
54                         ctx->tfm = NULL;
55                         goto out;
56                 }
57 -               ctx->mode = key->mode;
58 +               ctx->mode = ci->ci_mode;
59         }
60 -       BUG_ON(key->size != ext4_encryption_key_size(key->mode));
61 +       BUG_ON(ci->ci_size != ext4_encryption_key_size(ci->ci_mode));
63         /* There shouldn't be a bounce page attached to the crypto
64          * context at this point. */
65 @@ -322,7 +322,7 @@ static int ext4_page_crypto(struct ext4_crypto_ctx *ctx,
66         int res = 0;
68         BUG_ON(!ctx->tfm);
69 -       BUG_ON(ctx->mode != ei->i_encryption_key.mode);
70 +       BUG_ON(ctx->mode != ei->i_crypt_info.ci_mode);
72         if (ctx->mode != EXT4_ENCRYPTION_MODE_AES_256_XTS) {
73                 printk_ratelimited(KERN_ERR
74 @@ -334,8 +334,8 @@ static int ext4_page_crypto(struct ext4_crypto_ctx *ctx,
75         crypto_ablkcipher_clear_flags(atfm, ~0);
76         crypto_tfm_set_flags(ctx->tfm, CRYPTO_TFM_REQ_WEAK_KEY);
78 -       res = crypto_ablkcipher_setkey(atfm, ei->i_encryption_key.raw,
79 -                                      ei->i_encryption_key.size);
80 +       res = crypto_ablkcipher_setkey(atfm, ei->i_crypt_info.ci_raw,
81 +                                      ei->i_crypt_info.ci_size);
82         if (res) {
83                 printk_ratelimited(KERN_ERR
84                                    "%s: crypto_ablkcipher_setkey() failed\n",
85 diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
86 index 23d7f1d..d9f08dd 100644
87 --- a/fs/ext4/crypto_fname.c
88 +++ b/fs/ext4/crypto_fname.c
89 @@ -278,33 +278,24 @@ void ext4_put_fname_crypto_ctx(struct ext4_fname_crypto_ctx **ctx)
90  }
92  /**
93 - * ext4_search_fname_crypto_ctx() -
94 - */
95 -static struct ext4_fname_crypto_ctx *ext4_search_fname_crypto_ctx(
96 -               const struct ext4_encryption_key *key)
98 -       return NULL;
101 -/**
102   * ext4_alloc_fname_crypto_ctx() -
103   */
104  struct ext4_fname_crypto_ctx *ext4_alloc_fname_crypto_ctx(
105 -       const struct ext4_encryption_key *key)
106 +       const struct ext4_crypt_info *ci)
108         struct ext4_fname_crypto_ctx *ctx;
110         ctx = kmalloc(sizeof(struct ext4_fname_crypto_ctx), GFP_NOFS);
111         if (ctx == NULL)
112                 return ERR_PTR(-ENOMEM);
113 -       if (key->mode == EXT4_ENCRYPTION_MODE_INVALID) {
114 +       if (ci->ci_mode == EXT4_ENCRYPTION_MODE_INVALID) {
115                 /* This will automatically set key mode to invalid
116                  * As enum for ENCRYPTION_MODE_INVALID is zero */
117 -               memset(&ctx->key, 0, sizeof(ctx->key));
118 +               memset(&ctx->ci, 0, sizeof(ctx->ci));
119         } else {
120 -               memcpy(&ctx->key, key, sizeof(struct ext4_encryption_key));
121 +               memcpy(&ctx->ci, ci, sizeof(struct ext4_crypt_info));
122         }
123 -       ctx->has_valid_key = (EXT4_ENCRYPTION_MODE_INVALID == key->mode)
124 +       ctx->has_valid_key = (EXT4_ENCRYPTION_MODE_INVALID == ci->ci_mode)
125                 ? 0 : 1;
126         ctx->ctfm_key_is_ready = 0;
127         ctx->ctfm = NULL;
128 @@ -335,21 +326,17 @@ struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(
129         if (!ext4_has_encryption_key(inode))
130                 ext4_generate_encryption_key(inode);
132 -       /* Get a crypto context based on the key.
133 -        * A new context is allocated if no context matches the requested key.
134 -        */
135 -       ctx = ext4_search_fname_crypto_ctx(&(ei->i_encryption_key));
136 -       if (ctx == NULL)
137 -               ctx = ext4_alloc_fname_crypto_ctx(&(ei->i_encryption_key));
138 +       /* Get a crypto context based on the key. */
139 +       ctx = ext4_alloc_fname_crypto_ctx(&(ei->i_crypt_info));
140         if (IS_ERR(ctx))
141                 return ctx;
143         ctx->flags = ei->i_crypt_policy_flags;
144         if (ctx->has_valid_key) {
145 -               if (ctx->key.mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) {
146 +               if (ctx->ci.ci_mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) {
147                         printk_once(KERN_WARNING
148                                     "ext4: unsupported key mode %d\n",
149 -                                   ctx->key.mode);
150 +                                   ctx->ci.ci_mode);
151                         return ERR_PTR(-ENOKEY);
152                 }
154 @@ -389,7 +376,7 @@ struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(
155                          * are pretty weak,
156                          * we directly use the inode master key */
157                         res = crypto_ablkcipher_setkey(ctx->ctfm,
158 -                                       ctx->key.raw, ctx->key.size);
159 +                                       ctx->ci.ci_raw, ctx->ci.ci_size);
160                         if (res) {
161                                 ext4_put_fname_crypto_ctx(&ctx);
162                                 return ERR_PTR(-EIO);
163 diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
164 index 52170d0..ec6635d 100644
165 --- a/fs/ext4/crypto_key.c
166 +++ b/fs/ext4/crypto_key.c
167 @@ -91,7 +91,7 @@ out:
168  int ext4_generate_encryption_key(struct inode *inode)
170         struct ext4_inode_info *ei = EXT4_I(inode);
171 -       struct ext4_encryption_key *crypt_key = &ei->i_encryption_key;
172 +       struct ext4_crypt_info *crypt_info = &ei->i_crypt_info;
173         char full_key_descriptor[EXT4_KEY_DESC_PREFIX_SIZE +
174                                  (EXT4_KEY_DESCRIPTOR_SIZE * 2) + 1];
175         struct key *keyring_key = NULL;
176 @@ -112,17 +112,17 @@ int ext4_generate_encryption_key(struct inode *inode)
178         ei->i_crypt_policy_flags = ctx.flags;
179         if (S_ISREG(inode->i_mode))
180 -               crypt_key->mode = ctx.contents_encryption_mode;
181 +               crypt_info->ci_mode = ctx.contents_encryption_mode;
182         else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
183 -               crypt_key->mode = ctx.filenames_encryption_mode;
184 +               crypt_info->ci_mode = ctx.filenames_encryption_mode;
185         else {
186                 printk(KERN_ERR "ext4 crypto: Unsupported inode type.\n");
187                 BUG();
188         }
189 -       crypt_key->size = ext4_encryption_key_size(crypt_key->mode);
190 -       BUG_ON(!crypt_key->size);
191 +       crypt_info->ci_size = ext4_encryption_key_size(crypt_info->ci_mode);
192 +       BUG_ON(!crypt_info->ci_size);
193         if (DUMMY_ENCRYPTION_ENABLED(sbi)) {
194 -               memset(crypt_key->raw, 0x42, EXT4_AES_256_XTS_KEY_SIZE);
195 +               memset(crypt_info->ci_raw, 0x42, EXT4_AES_256_XTS_KEY_SIZE);
196                 goto out;
197         }
198         memcpy(full_key_descriptor, EXT4_KEY_DESC_PREFIX,
199 @@ -148,19 +148,20 @@ int ext4_generate_encryption_key(struct inode *inode)
200         BUILD_BUG_ON(EXT4_AES_128_ECB_KEY_SIZE !=
201                      EXT4_KEY_DERIVATION_NONCE_SIZE);
202         BUG_ON(master_key->size != EXT4_AES_256_XTS_KEY_SIZE);
203 -       res = ext4_derive_key_aes(ctx.nonce, master_key->raw, crypt_key->raw);
204 +       res = ext4_derive_key_aes(ctx.nonce, master_key->raw,
205 +                                 crypt_info->ci_raw);
206  out:
207         if (keyring_key)
208                 key_put(keyring_key);
209         if (res < 0)
210 -               crypt_key->mode = EXT4_ENCRYPTION_MODE_INVALID;
211 +               crypt_info->ci_mode = EXT4_ENCRYPTION_MODE_INVALID;
212         return res;
215  int ext4_has_encryption_key(struct inode *inode)
217         struct ext4_inode_info *ei = EXT4_I(inode);
218 -       struct ext4_encryption_key *crypt_key = &ei->i_encryption_key;
219 +       struct ext4_crypt_info *crypt_info = &ei->i_crypt_info;
221 -       return (crypt_key->mode != EXT4_ENCRYPTION_MODE_INVALID);
222 +       return (crypt_info->ci_mode != EXT4_ENCRYPTION_MODE_INVALID);
224 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
225 index 8071a0a..e20a06c 100644
226 --- a/fs/ext4/ext4.h
227 +++ b/fs/ext4/ext4.h
228 @@ -955,7 +955,7 @@ struct ext4_inode_info {
230  #ifdef CONFIG_EXT4_FS_ENCRYPTION
231         /* Encryption params */
232 -       struct ext4_encryption_key i_encryption_key;
233 +       struct ext4_crypt_info i_crypt_info;
234  #endif
235  };
237 diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h
238 index 552424a..deecbe8 100644
239 --- a/fs/ext4/ext4_crypto.h
240 +++ b/fs/ext4/ext4_crypto.h
241 @@ -66,10 +66,17 @@ struct ext4_encryption_context {
242  #define EXT4_KEY_DESC_PREFIX "ext4:"
243  #define EXT4_KEY_DESC_PREFIX_SIZE 5
245 +/* This is passed in from userspace into the kernel keyring */
246  struct ext4_encryption_key {
247 -       uint32_t mode;
248 -       char raw[EXT4_MAX_KEY_SIZE];
249 -       uint32_t size;
250 +        __u32 mode;
251 +        char raw[EXT4_MAX_KEY_SIZE];
252 +        __u32 size;
253 +} __attribute__((__packed__));
255 +struct ext4_crypt_info {
256 +       unsigned char   ci_mode;
257 +       unsigned char   ci_size;
258 +       char            ci_raw[EXT4_MAX_KEY_SIZE];
259  };
261  #define EXT4_CTX_REQUIRES_FREE_ENCRYPT_FL             0x00000001
262 @@ -125,7 +132,7 @@ struct ext4_fname_crypto_ctx {
263         u32 lim;
264         struct crypto_ablkcipher *ctfm;
265         struct crypto_hash *htfm;
266 -       struct ext4_encryption_key key;
267 +       struct ext4_crypt_info ci;
268         unsigned flags : 8;
269         unsigned has_valid_key : 1;
270         unsigned ctfm_key_is_ready : 1;
271 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
272 index f9ebd58..a2eb108 100644
273 --- a/fs/ext4/super.c
274 +++ b/fs/ext4/super.c
275 @@ -877,7 +877,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
276         atomic_set(&ei->i_unwritten, 0);
277         INIT_WORK(&ei->i_rsv_conversion_work, ext4_end_io_rsv_work);
278  #ifdef CONFIG_EXT4_FS_ENCRYPTION
279 -       ei->i_encryption_key.mode = EXT4_ENCRYPTION_MODE_INVALID;
280 +       ei->i_crypt_info.ci_mode = EXT4_ENCRYPTION_MODE_INVALID;
281  #endif
283         return &ei->vfs_inode;