aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoberto Sassu <roberto.sassu@polito.it>2011-03-21 11:00:53 -0400
committerTyler Hicks <tyhicks@linux.vnet.ibm.com>2011-03-28 02:49:41 -0400
commit0e1fc5ef470cc1d157005c437a434868d59fead4 (patch)
treea15889a237ad7db00ef695d4338286e663127ee0
parent7762e230fd31fcc1abc03ba32ee957fadc8eafb4 (diff)
eCryptfs: verify authentication tokens before their use
Authentication tokens content may change if another requestor calls the update() method of the corresponding key. The new function ecryptfs_verify_auth_tok_from_key() retrieves the authentication token from the provided key and verifies if it is still valid before being used to encrypt or decrypt an eCryptfs file. Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> [tyhicks: Minor formatting changes] Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h1
-rw-r--r--fs/ecryptfs/keystore.c211
-rw-r--r--fs/ecryptfs/main.c4
3 files changed, 135 insertions, 81 deletions
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 40c93fe41cc3..bd3cafd0949d 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -331,7 +331,6 @@ struct ecryptfs_global_auth_tok {
331 u32 flags; 331 u32 flags;
332 struct list_head mount_crypt_stat_list; 332 struct list_head mount_crypt_stat_list;
333 struct key *global_auth_tok_key; 333 struct key *global_auth_tok_key;
334 struct ecryptfs_auth_tok *global_auth_tok;
335 unsigned char sig[ECRYPTFS_SIG_SIZE_HEX + 1]; 334 unsigned char sig[ECRYPTFS_SIG_SIZE_HEX + 1];
336}; 335};
337 336
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index bd139dfad8e7..3c4039cc18d1 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -65,6 +65,24 @@ static int process_request_key_err(long err_code)
65 return rc; 65 return rc;
66} 66}
67 67
68static int process_find_global_auth_tok_for_sig_err(int err_code)
69{
70 int rc = err_code;
71
72 switch (err_code) {
73 case -ENOENT:
74 ecryptfs_printk(KERN_WARNING, "Missing auth tok\n");
75 break;
76 case -EINVAL:
77 ecryptfs_printk(KERN_WARNING, "Invalid auth tok\n");
78 break;
79 default:
80 rc = process_request_key_err(err_code);
81 break;
82 }
83 return rc;
84}
85
68/** 86/**
69 * ecryptfs_parse_packet_length 87 * ecryptfs_parse_packet_length
70 * @data: Pointer to memory containing length at offset 88 * @data: Pointer to memory containing length at offset
@@ -403,27 +421,117 @@ out:
403 return rc; 421 return rc;
404} 422}
405 423
424/**
425 * ecryptfs_verify_version
426 * @version: The version number to confirm
427 *
428 * Returns zero on good version; non-zero otherwise
429 */
430static int ecryptfs_verify_version(u16 version)
431{
432 int rc = 0;
433 unsigned char major;
434 unsigned char minor;
435
436 major = ((version >> 8) & 0xFF);
437 minor = (version & 0xFF);
438 if (major != ECRYPTFS_VERSION_MAJOR) {
439 ecryptfs_printk(KERN_ERR, "Major version number mismatch. "
440 "Expected [%d]; got [%d]\n",
441 ECRYPTFS_VERSION_MAJOR, major);
442 rc = -EINVAL;
443 goto out;
444 }
445 if (minor != ECRYPTFS_VERSION_MINOR) {
446 ecryptfs_printk(KERN_ERR, "Minor version number mismatch. "
447 "Expected [%d]; got [%d]\n",
448 ECRYPTFS_VERSION_MINOR, minor);
449 rc = -EINVAL;
450 goto out;
451 }
452out:
453 return rc;
454}
455
456/**
457 * ecryptfs_verify_auth_tok_from_key
458 * @auth_tok_key: key containing the authentication token
459 * @auth_tok: authentication token
460 *
461 * Returns zero on valid auth tok; -EINVAL otherwise
462 */
463static int
464ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key,
465 struct ecryptfs_auth_tok **auth_tok)
466{
467 int rc = 0;
468
469 (*auth_tok) = ecryptfs_get_key_payload_data(auth_tok_key);
470 if (ecryptfs_verify_version((*auth_tok)->version)) {
471 printk(KERN_ERR "Data structure version mismatch. Userspace "
472 "tools must match eCryptfs kernel module with major "
473 "version [%d] and minor version [%d]\n",
474 ECRYPTFS_VERSION_MAJOR, ECRYPTFS_VERSION_MINOR);
475 rc = -EINVAL;
476 goto out;
477 }
478 if ((*auth_tok)->token_type != ECRYPTFS_PASSWORD
479 && (*auth_tok)->token_type != ECRYPTFS_PRIVATE_KEY) {
480 printk(KERN_ERR "Invalid auth_tok structure "
481 "returned from key query\n");
482 rc = -EINVAL;
483 goto out;
484 }
485out:
486 return rc;
487}
488
406static int 489static int
407ecryptfs_find_global_auth_tok_for_sig( 490ecryptfs_find_global_auth_tok_for_sig(
408 struct ecryptfs_global_auth_tok **global_auth_tok, 491 struct key **auth_tok_key,
492 struct ecryptfs_auth_tok **auth_tok,
409 struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig) 493 struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig)
410{ 494{
411 struct ecryptfs_global_auth_tok *walker; 495 struct ecryptfs_global_auth_tok *walker;
412 int rc = 0; 496 int rc = 0;
413 497
414 (*global_auth_tok) = NULL; 498 (*auth_tok_key) = NULL;
499 (*auth_tok) = NULL;
415 mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); 500 mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
416 list_for_each_entry(walker, 501 list_for_each_entry(walker,
417 &mount_crypt_stat->global_auth_tok_list, 502 &mount_crypt_stat->global_auth_tok_list,
418 mount_crypt_stat_list) { 503 mount_crypt_stat_list) {
419 if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX) == 0) { 504 if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX))
420 rc = key_validate(walker->global_auth_tok_key); 505 continue;
421 if (!rc) 506
422 (*global_auth_tok) = walker; 507 if (walker->flags & ECRYPTFS_AUTH_TOK_INVALID) {
508 rc = -EINVAL;
423 goto out; 509 goto out;
424 } 510 }
511
512 rc = key_validate(walker->global_auth_tok_key);
513 if (rc) {
514 if (rc == -EKEYEXPIRED)
515 goto out;
516 goto out_invalid_auth_tok;
517 }
518
519 rc = ecryptfs_verify_auth_tok_from_key(
520 walker->global_auth_tok_key, auth_tok);
521 if (rc)
522 goto out_invalid_auth_tok;
523
524 (*auth_tok_key) = walker->global_auth_tok_key;
525 key_get(*auth_tok_key);
526 goto out;
425 } 527 }
426 rc = -EINVAL; 528 rc = -ENOENT;
529 goto out;
530out_invalid_auth_tok:
531 printk(KERN_WARNING "Invalidating auth tok with sig = [%s]\n", sig);
532 walker->flags |= ECRYPTFS_AUTH_TOK_INVALID;
533 key_put(walker->global_auth_tok_key);
534 walker->global_auth_tok_key = NULL;
427out: 535out:
428 mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); 536 mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
429 return rc; 537 return rc;
@@ -451,14 +559,11 @@ ecryptfs_find_auth_tok_for_sig(
451 struct ecryptfs_mount_crypt_stat *mount_crypt_stat, 559 struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
452 char *sig) 560 char *sig)
453{ 561{
454 struct ecryptfs_global_auth_tok *global_auth_tok;
455 int rc = 0; 562 int rc = 0;
456 563
457 (*auth_tok_key) = NULL; 564 rc = ecryptfs_find_global_auth_tok_for_sig(auth_tok_key, auth_tok,
458 (*auth_tok) = NULL; 565 mount_crypt_stat, sig);
459 if (ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok, 566 if (rc == -ENOENT) {
460 mount_crypt_stat, sig)) {
461
462 /* if the flag ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY is set in the 567 /* if the flag ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY is set in the
463 * mount_crypt_stat structure, we prevent to use auth toks that 568 * mount_crypt_stat structure, we prevent to use auth toks that
464 * are not inserted through the ecryptfs_add_global_auth_tok 569 * are not inserted through the ecryptfs_add_global_auth_tok
@@ -470,8 +575,7 @@ ecryptfs_find_auth_tok_for_sig(
470 575
471 rc = ecryptfs_keyring_auth_tok_for_sig(auth_tok_key, auth_tok, 576 rc = ecryptfs_keyring_auth_tok_for_sig(auth_tok_key, auth_tok,
472 sig); 577 sig);
473 } else 578 }
474 (*auth_tok) = global_auth_tok->global_auth_tok;
475 return rc; 579 return rc;
476} 580}
477 581
@@ -1520,38 +1624,6 @@ out:
1520 return rc; 1624 return rc;
1521} 1625}
1522 1626
1523/**
1524 * ecryptfs_verify_version
1525 * @version: The version number to confirm
1526 *
1527 * Returns zero on good version; non-zero otherwise
1528 */
1529static int ecryptfs_verify_version(u16 version)
1530{
1531 int rc = 0;
1532 unsigned char major;
1533 unsigned char minor;
1534
1535 major = ((version >> 8) & 0xFF);
1536 minor = (version & 0xFF);
1537 if (major != ECRYPTFS_VERSION_MAJOR) {
1538 ecryptfs_printk(KERN_ERR, "Major version number mismatch. "
1539 "Expected [%d]; got [%d]\n",
1540 ECRYPTFS_VERSION_MAJOR, major);
1541 rc = -EINVAL;
1542 goto out;
1543 }
1544 if (minor != ECRYPTFS_VERSION_MINOR) {
1545 ecryptfs_printk(KERN_ERR, "Minor version number mismatch. "
1546 "Expected [%d]; got [%d]\n",
1547 ECRYPTFS_VERSION_MINOR, minor);
1548 rc = -EINVAL;
1549 goto out;
1550 }
1551out:
1552 return rc;
1553}
1554
1555int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key, 1627int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
1556 struct ecryptfs_auth_tok **auth_tok, 1628 struct ecryptfs_auth_tok **auth_tok,
1557 char *sig) 1629 char *sig)
@@ -1566,29 +1638,12 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
1566 (*auth_tok_key) = NULL; 1638 (*auth_tok_key) = NULL;
1567 goto out; 1639 goto out;
1568 } 1640 }
1569 (*auth_tok) = ecryptfs_get_key_payload_data(*auth_tok_key); 1641
1570 if (ecryptfs_verify_version((*auth_tok)->version)) { 1642 rc = ecryptfs_verify_auth_tok_from_key(*auth_tok_key, auth_tok);
1571 printk(KERN_ERR
1572 "Data structure version mismatch. "
1573 "Userspace tools must match eCryptfs "
1574 "kernel module with major version [%d] "
1575 "and minor version [%d]\n",
1576 ECRYPTFS_VERSION_MAJOR,
1577 ECRYPTFS_VERSION_MINOR);
1578 rc = -EINVAL;
1579 goto out_release_key;
1580 }
1581 if ((*auth_tok)->token_type != ECRYPTFS_PASSWORD
1582 && (*auth_tok)->token_type != ECRYPTFS_PRIVATE_KEY) {
1583 printk(KERN_ERR "Invalid auth_tok structure "
1584 "returned from key query\n");
1585 rc = -EINVAL;
1586 goto out_release_key;
1587 }
1588out_release_key:
1589 if (rc) { 1643 if (rc) {
1590 key_put(*auth_tok_key); 1644 key_put(*auth_tok_key);
1591 (*auth_tok_key) = NULL; 1645 (*auth_tok_key) = NULL;
1646 goto out;
1592 } 1647 }
1593out: 1648out:
1594 return rc; 1649 return rc;
@@ -2325,7 +2380,7 @@ ecryptfs_generate_key_packet_set(char *dest_base,
2325 size_t max) 2380 size_t max)
2326{ 2381{
2327 struct ecryptfs_auth_tok *auth_tok; 2382 struct ecryptfs_auth_tok *auth_tok;
2328 struct ecryptfs_global_auth_tok *global_auth_tok; 2383 struct key *auth_tok_key = NULL;
2329 struct ecryptfs_mount_crypt_stat *mount_crypt_stat = 2384 struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
2330 &ecryptfs_superblock_to_private( 2385 &ecryptfs_superblock_to_private(
2331 ecryptfs_dentry->d_sb)->mount_crypt_stat; 2386 ecryptfs_dentry->d_sb)->mount_crypt_stat;
@@ -2344,21 +2399,16 @@ ecryptfs_generate_key_packet_set(char *dest_base,
2344 list_for_each_entry(key_sig, &crypt_stat->keysig_list, 2399 list_for_each_entry(key_sig, &crypt_stat->keysig_list,
2345 crypt_stat_list) { 2400 crypt_stat_list) {
2346 memset(key_rec, 0, sizeof(*key_rec)); 2401 memset(key_rec, 0, sizeof(*key_rec));
2347 rc = ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok, 2402 rc = ecryptfs_find_global_auth_tok_for_sig(&auth_tok_key,
2403 &auth_tok,
2348 mount_crypt_stat, 2404 mount_crypt_stat,
2349 key_sig->keysig); 2405 key_sig->keysig);
2350 if (rc) { 2406 if (rc) {
2351 printk(KERN_ERR "Error attempting to get the global " 2407 printk(KERN_WARNING "Unable to retrieve auth tok with "
2352 "auth_tok; rc = [%d]\n", rc); 2408 "sig = [%s]\n", key_sig->keysig);
2409 rc = process_find_global_auth_tok_for_sig_err(rc);
2353 goto out_free; 2410 goto out_free;
2354 } 2411 }
2355 if (global_auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID) {
2356 printk(KERN_WARNING
2357 "Skipping invalid auth tok with sig = [%s]\n",
2358 global_auth_tok->sig);
2359 continue;
2360 }
2361 auth_tok = global_auth_tok->global_auth_tok;
2362 if (auth_tok->token_type == ECRYPTFS_PASSWORD) { 2412 if (auth_tok->token_type == ECRYPTFS_PASSWORD) {
2363 rc = write_tag_3_packet((dest_base + (*len)), 2413 rc = write_tag_3_packet((dest_base + (*len)),
2364 &max, auth_tok, 2414 &max, auth_tok,
@@ -2396,6 +2446,8 @@ ecryptfs_generate_key_packet_set(char *dest_base,
2396 rc = -EINVAL; 2446 rc = -EINVAL;
2397 goto out_free; 2447 goto out_free;
2398 } 2448 }
2449 key_put(auth_tok_key);
2450 auth_tok_key = NULL;
2399 } 2451 }
2400 if (likely(max > 0)) { 2452 if (likely(max > 0)) {
2401 dest_base[(*len)] = 0x00; 2453 dest_base[(*len)] = 0x00;
@@ -2408,6 +2460,9 @@ out_free:
2408out: 2460out:
2409 if (rc) 2461 if (rc)
2410 (*len) = 0; 2462 (*len) = 0;
2463 if (auth_tok_key)
2464 key_put(auth_tok_key);
2465
2411 mutex_unlock(&crypt_stat->keysig_list_mutex); 2466 mutex_unlock(&crypt_stat->keysig_list_mutex);
2412 return rc; 2467 return rc;
2413} 2468}
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 63e412cf0fa1..520d05f5ad01 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -239,14 +239,14 @@ static int ecryptfs_init_global_auth_toks(
239 struct ecryptfs_mount_crypt_stat *mount_crypt_stat) 239 struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
240{ 240{
241 struct ecryptfs_global_auth_tok *global_auth_tok; 241 struct ecryptfs_global_auth_tok *global_auth_tok;
242 struct ecryptfs_auth_tok *auth_tok;
242 int rc = 0; 243 int rc = 0;
243 244
244 list_for_each_entry(global_auth_tok, 245 list_for_each_entry(global_auth_tok,
245 &mount_crypt_stat->global_auth_tok_list, 246 &mount_crypt_stat->global_auth_tok_list,
246 mount_crypt_stat_list) { 247 mount_crypt_stat_list) {
247 rc = ecryptfs_keyring_auth_tok_for_sig( 248 rc = ecryptfs_keyring_auth_tok_for_sig(
248 &global_auth_tok->global_auth_tok_key, 249 &global_auth_tok->global_auth_tok_key, &auth_tok,
249 &global_auth_tok->global_auth_tok,
250 global_auth_tok->sig); 250 global_auth_tok->sig);
251 if (rc) { 251 if (rc) {
252 printk(KERN_ERR "Could not find valid key in user " 252 printk(KERN_ERR "Could not find valid key in user "