aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs/main.c
diff options
context:
space:
mode:
authorMichael Halcrow <mhalcrow@us.ibm.com>2007-10-16 04:27:53 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:43:10 -0400
commitf4aad16adfb8f0a2d666fdf8af4bd0dff2ce75e4 (patch)
tree42e7f191d1a3a1e1375af24acc5c336b30c5c4d1 /fs/ecryptfs/main.c
parentcce76f9b9696a59974be9ed43478c000c57e597a (diff)
eCryptfs: add key list structure; search keyring
Add support structures for handling multiple keys. The list in crypt_stat contains the key identifiers for all of the keys that should be used for encrypting each file's File Encryption Key (FEK). For now, each inode inherits this list from the mount-wide crypt_stat struct, via the ecryptfs_copy_mount_wide_sigs_to_inode_sigs() function. This patch also removes the global key tfm from the mount-wide crypt_stat struct, instead keeping a list of tfm's meant for dealing with the various inode FEK's. eCryptfs will now search the user's keyring for FEK's parsed from the existing file metadata, so the user can make keys available at any time before or after mounting. Now that multiple FEK packets can be written to the file metadata, we need to be more meticulous about size limits. The updates to the code for writing out packets to the file metadata makes sizes and limits more explicit, uniformly expressed, and (hopefully) easier to follow. Signed-off-by: Michael Halcrow <mhalcrow@us.ibm.com> Cc: "Serge E. Hallyn" <serge@hallyn.com> Cc: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ecryptfs/main.c')
-rw-r--r--fs/ecryptfs/main.c121
1 files changed, 44 insertions, 77 deletions
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index a98497264fe8..6e2170c96c02 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -179,38 +179,40 @@ static match_table_t tokens = {
179 {ecryptfs_opt_err, NULL} 179 {ecryptfs_opt_err, NULL}
180}; 180};
181 181
182/** 182static int ecryptfs_init_global_auth_toks(
183 * ecryptfs_verify_version 183 struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
184 * @version: The version number to confirm
185 *
186 * Returns zero on good version; non-zero otherwise
187 */
188static int ecryptfs_verify_version(u16 version)
189{ 184{
185 struct ecryptfs_global_auth_tok *global_auth_tok;
190 int rc = 0; 186 int rc = 0;
191 unsigned char major; 187
192 unsigned char minor; 188 list_for_each_entry(global_auth_tok,
193 189 &mount_crypt_stat->global_auth_tok_list,
194 major = ((version >> 8) & 0xFF); 190 mount_crypt_stat_list) {
195 minor = (version & 0xFF); 191 if ((rc = ecryptfs_keyring_auth_tok_for_sig(
196 if (major != ECRYPTFS_VERSION_MAJOR) { 192 &global_auth_tok->global_auth_tok_key,
197 ecryptfs_printk(KERN_ERR, "Major version number mismatch. " 193 &global_auth_tok->global_auth_tok,
198 "Expected [%d]; got [%d]\n", 194 global_auth_tok->sig))) {
199 ECRYPTFS_VERSION_MAJOR, major); 195 printk(KERN_ERR "Could not find valid key in user "
200 rc = -EINVAL; 196 "session keyring for sig specified in mount "
201 goto out; 197 "option: [%s]\n", global_auth_tok->sig);
202 } 198 global_auth_tok->flags |= ECRYPTFS_AUTH_TOK_INVALID;
203 if (minor != ECRYPTFS_VERSION_MINOR) { 199 rc = 0;
204 ecryptfs_printk(KERN_ERR, "Minor version number mismatch. " 200 } else
205 "Expected [%d]; got [%d]\n", 201 global_auth_tok->flags &= ~ECRYPTFS_AUTH_TOK_INVALID;
206 ECRYPTFS_VERSION_MINOR, minor);
207 rc = -EINVAL;
208 goto out;
209 } 202 }
210out:
211 return rc; 203 return rc;
212} 204}
213 205
206static void ecryptfs_init_mount_crypt_stat(
207 struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
208{
209 memset((void *)mount_crypt_stat, 0,
210 sizeof(struct ecryptfs_mount_crypt_stat));
211 INIT_LIST_HEAD(&mount_crypt_stat->global_auth_tok_list);
212 mutex_init(&mount_crypt_stat->global_auth_tok_list_mutex);
213 mount_crypt_stat->flags |= ECRYPTFS_MOUNT_CRYPT_STAT_INITIALIZED;
214}
215
214/** 216/**
215 * ecryptfs_parse_options 217 * ecryptfs_parse_options
216 * @sb: The ecryptfs super block 218 * @sb: The ecryptfs super block
@@ -264,14 +266,13 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
264 case ecryptfs_opt_sig: 266 case ecryptfs_opt_sig:
265 case ecryptfs_opt_ecryptfs_sig: 267 case ecryptfs_opt_ecryptfs_sig:
266 sig_src = args[0].from; 268 sig_src = args[0].from;
267 sig_dst = 269 rc = ecryptfs_add_global_auth_tok(mount_crypt_stat,
268 mount_crypt_stat->global_auth_tok_sig; 270 sig_src);
269 memcpy(sig_dst, sig_src, ECRYPTFS_SIG_SIZE_HEX); 271 if (rc) {
270 sig_dst[ECRYPTFS_SIG_SIZE_HEX] = '\0'; 272 printk(KERN_ERR "Error attempting to register "
271 ecryptfs_printk(KERN_DEBUG, 273 "global sig; rc = [%d]\n", rc);
272 "The mount_crypt_stat " 274 goto out;
273 "global_auth_tok_sig set to: " 275 }
274 "[%s]\n", sig_dst);
275 sig_set = 1; 276 sig_set = 1;
276 break; 277 break;
277 case ecryptfs_opt_debug: 278 case ecryptfs_opt_debug:
@@ -358,55 +359,21 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
358 if (!cipher_key_bytes_set) { 359 if (!cipher_key_bytes_set) {
359 mount_crypt_stat->global_default_cipher_key_size = 0; 360 mount_crypt_stat->global_default_cipher_key_size = 0;
360 } 361 }
361 rc = ecryptfs_process_cipher( 362 if ((rc = ecryptfs_add_new_key_tfm(
362 &mount_crypt_stat->global_key_tfm, 363 NULL, mount_crypt_stat->global_default_cipher_name,
363 mount_crypt_stat->global_default_cipher_name, 364 mount_crypt_stat->global_default_cipher_key_size))) {
364 &mount_crypt_stat->global_default_cipher_key_size); 365 printk(KERN_ERR "Error attempting to initialize cipher with "
365 if (rc) { 366 "name = [%s] and key size = [%d]; rc = [%d]\n",
366 printk(KERN_ERR "Error attempting to initialize cipher [%s] "
367 "with key size [%Zd] bytes; rc = [%d]\n",
368 mount_crypt_stat->global_default_cipher_name, 367 mount_crypt_stat->global_default_cipher_name,
369 mount_crypt_stat->global_default_cipher_key_size, rc); 368 mount_crypt_stat->global_default_cipher_key_size, rc);
370 mount_crypt_stat->global_key_tfm = NULL;
371 mount_crypt_stat->global_auth_tok_key = NULL;
372 rc = -EINVAL;
373 goto out;
374 }
375 mutex_init(&mount_crypt_stat->global_key_tfm_mutex);
376 ecryptfs_printk(KERN_DEBUG, "Requesting the key with description: "
377 "[%s]\n", mount_crypt_stat->global_auth_tok_sig);
378 /* The reference to this key is held until umount is done The
379 * call to key_put is done in ecryptfs_put_super() */
380 auth_tok_key = request_key(&key_type_user,
381 mount_crypt_stat->global_auth_tok_sig,
382 NULL);
383 if (!auth_tok_key || IS_ERR(auth_tok_key)) {
384 ecryptfs_printk(KERN_ERR, "Could not find key with "
385 "description: [%s]\n",
386 mount_crypt_stat->global_auth_tok_sig);
387 process_request_key_err(PTR_ERR(auth_tok_key));
388 rc = -EINVAL; 369 rc = -EINVAL;
389 goto out; 370 goto out;
390 } 371 }
391 auth_tok = ecryptfs_get_key_payload_data(auth_tok_key); 372 if ((rc = ecryptfs_init_global_auth_toks(mount_crypt_stat))) {
392 if (ecryptfs_verify_version(auth_tok->version)) { 373 printk(KERN_WARNING "One or more global auth toks could not "
393 ecryptfs_printk(KERN_ERR, "Data structure version mismatch. " 374 "properly register; rc = [%d]\n", rc);
394 "Userspace tools must match eCryptfs kernel "
395 "module with major version [%d] and minor "
396 "version [%d]\n", ECRYPTFS_VERSION_MAJOR,
397 ECRYPTFS_VERSION_MINOR);
398 rc = -EINVAL;
399 goto out;
400 }
401 if (auth_tok->token_type != ECRYPTFS_PASSWORD
402 && auth_tok->token_type != ECRYPTFS_PRIVATE_KEY) {
403 ecryptfs_printk(KERN_ERR, "Invalid auth_tok structure "
404 "returned from key query\n");
405 rc = -EINVAL;
406 goto out;
407 } 375 }
408 mount_crypt_stat->global_auth_tok_key = auth_tok_key; 376 rc = 0;
409 mount_crypt_stat->global_auth_tok = auth_tok;
410out: 377out:
411 return rc; 378 return rc;
412} 379}