diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-01-10 20:42:53 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-01-10 20:42:53 -0500 |
commit | 506c10f26c481b7f8ef27c1c79290f68989b2e9e (patch) | |
tree | 03de82e812f00957aa6276dac2fe51c3358e88d7 /fs/ecryptfs/keystore.c | |
parent | e1df957670aef74ffd9a4ad93e6d2c90bf6b4845 (diff) | |
parent | c59765042f53a79a7a65585042ff463b69cb248c (diff) |
Merge commit 'v2.6.29-rc1' into perfcounters/core
Conflicts:
include/linux/kernel_stat.h
Diffstat (limited to 'fs/ecryptfs/keystore.c')
-rw-r--r-- | fs/ecryptfs/keystore.c | 651 |
1 files changed, 584 insertions, 67 deletions
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 0d713b691941..ff539420cc6f 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c | |||
@@ -358,7 +358,7 @@ parse_tag_67_packet(struct ecryptfs_key_record *key_rec, | |||
358 | /* verify that everything through the encrypted FEK size is present */ | 358 | /* verify that everything through the encrypted FEK size is present */ |
359 | if (message_len < 4) { | 359 | if (message_len < 4) { |
360 | rc = -EIO; | 360 | rc = -EIO; |
361 | printk(KERN_ERR "%s: message_len is [%Zd]; minimum acceptable " | 361 | printk(KERN_ERR "%s: message_len is [%zd]; minimum acceptable " |
362 | "message length is [%d]\n", __func__, message_len, 4); | 362 | "message length is [%d]\n", __func__, message_len, 4); |
363 | goto out; | 363 | goto out; |
364 | } | 364 | } |
@@ -385,13 +385,13 @@ parse_tag_67_packet(struct ecryptfs_key_record *key_rec, | |||
385 | i += data_len; | 385 | i += data_len; |
386 | if (message_len < (i + key_rec->enc_key_size)) { | 386 | if (message_len < (i + key_rec->enc_key_size)) { |
387 | rc = -EIO; | 387 | rc = -EIO; |
388 | printk(KERN_ERR "%s: message_len [%Zd]; max len is [%Zd]\n", | 388 | printk(KERN_ERR "%s: message_len [%zd]; max len is [%zd]\n", |
389 | __func__, message_len, (i + key_rec->enc_key_size)); | 389 | __func__, message_len, (i + key_rec->enc_key_size)); |
390 | goto out; | 390 | goto out; |
391 | } | 391 | } |
392 | if (key_rec->enc_key_size > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) { | 392 | if (key_rec->enc_key_size > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) { |
393 | rc = -EIO; | 393 | rc = -EIO; |
394 | printk(KERN_ERR "%s: Encrypted key_size [%Zd] larger than " | 394 | printk(KERN_ERR "%s: Encrypted key_size [%zd] larger than " |
395 | "the maximum key size [%d]\n", __func__, | 395 | "the maximum key size [%d]\n", __func__, |
396 | key_rec->enc_key_size, | 396 | key_rec->enc_key_size, |
397 | ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES); | 397 | ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES); |
@@ -403,6 +403,580 @@ out: | |||
403 | } | 403 | } |
404 | 404 | ||
405 | static int | 405 | static int |
406 | ecryptfs_find_global_auth_tok_for_sig( | ||
407 | struct ecryptfs_global_auth_tok **global_auth_tok, | ||
408 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig) | ||
409 | { | ||
410 | struct ecryptfs_global_auth_tok *walker; | ||
411 | int rc = 0; | ||
412 | |||
413 | (*global_auth_tok) = NULL; | ||
414 | mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); | ||
415 | list_for_each_entry(walker, | ||
416 | &mount_crypt_stat->global_auth_tok_list, | ||
417 | mount_crypt_stat_list) { | ||
418 | if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX) == 0) { | ||
419 | (*global_auth_tok) = walker; | ||
420 | goto out; | ||
421 | } | ||
422 | } | ||
423 | rc = -EINVAL; | ||
424 | out: | ||
425 | mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); | ||
426 | return rc; | ||
427 | } | ||
428 | |||
429 | /** | ||
430 | * ecryptfs_find_auth_tok_for_sig | ||
431 | * @auth_tok: Set to the matching auth_tok; NULL if not found | ||
432 | * @crypt_stat: inode crypt_stat crypto context | ||
433 | * @sig: Sig of auth_tok to find | ||
434 | * | ||
435 | * For now, this function simply looks at the registered auth_tok's | ||
436 | * linked off the mount_crypt_stat, so all the auth_toks that can be | ||
437 | * used must be registered at mount time. This function could | ||
438 | * potentially try a lot harder to find auth_tok's (e.g., by calling | ||
439 | * out to ecryptfsd to dynamically retrieve an auth_tok object) so | ||
440 | * that static registration of auth_tok's will no longer be necessary. | ||
441 | * | ||
442 | * Returns zero on no error; non-zero on error | ||
443 | */ | ||
444 | static int | ||
445 | ecryptfs_find_auth_tok_for_sig( | ||
446 | struct ecryptfs_auth_tok **auth_tok, | ||
447 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat, | ||
448 | char *sig) | ||
449 | { | ||
450 | struct ecryptfs_global_auth_tok *global_auth_tok; | ||
451 | int rc = 0; | ||
452 | |||
453 | (*auth_tok) = NULL; | ||
454 | if (ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok, | ||
455 | mount_crypt_stat, sig)) { | ||
456 | struct key *auth_tok_key; | ||
457 | |||
458 | rc = ecryptfs_keyring_auth_tok_for_sig(&auth_tok_key, auth_tok, | ||
459 | sig); | ||
460 | } else | ||
461 | (*auth_tok) = global_auth_tok->global_auth_tok; | ||
462 | return rc; | ||
463 | } | ||
464 | |||
465 | /** | ||
466 | * write_tag_70_packet can gobble a lot of stack space. We stuff most | ||
467 | * of the function's parameters in a kmalloc'd struct to help reduce | ||
468 | * eCryptfs' overall stack usage. | ||
469 | */ | ||
470 | struct ecryptfs_write_tag_70_packet_silly_stack { | ||
471 | u8 cipher_code; | ||
472 | size_t max_packet_size; | ||
473 | size_t packet_size_len; | ||
474 | size_t block_aligned_filename_size; | ||
475 | size_t block_size; | ||
476 | size_t i; | ||
477 | size_t j; | ||
478 | size_t num_rand_bytes; | ||
479 | struct mutex *tfm_mutex; | ||
480 | char *block_aligned_filename; | ||
481 | struct ecryptfs_auth_tok *auth_tok; | ||
482 | struct scatterlist src_sg; | ||
483 | struct scatterlist dst_sg; | ||
484 | struct blkcipher_desc desc; | ||
485 | char iv[ECRYPTFS_MAX_IV_BYTES]; | ||
486 | char hash[ECRYPTFS_TAG_70_DIGEST_SIZE]; | ||
487 | char tmp_hash[ECRYPTFS_TAG_70_DIGEST_SIZE]; | ||
488 | struct hash_desc hash_desc; | ||
489 | struct scatterlist hash_sg; | ||
490 | }; | ||
491 | |||
492 | /** | ||
493 | * write_tag_70_packet - Write encrypted filename (EFN) packet against FNEK | ||
494 | * @filename: NULL-terminated filename string | ||
495 | * | ||
496 | * This is the simplest mechanism for achieving filename encryption in | ||
497 | * eCryptfs. It encrypts the given filename with the mount-wide | ||
498 | * filename encryption key (FNEK) and stores it in a packet to @dest, | ||
499 | * which the callee will encode and write directly into the dentry | ||
500 | * name. | ||
501 | */ | ||
502 | int | ||
503 | ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, | ||
504 | size_t *packet_size, | ||
505 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat, | ||
506 | char *filename, size_t filename_size) | ||
507 | { | ||
508 | struct ecryptfs_write_tag_70_packet_silly_stack *s; | ||
509 | int rc = 0; | ||
510 | |||
511 | s = kmalloc(sizeof(*s), GFP_KERNEL); | ||
512 | if (!s) { | ||
513 | printk(KERN_ERR "%s: Out of memory whilst trying to kmalloc " | ||
514 | "[%zd] bytes of kernel memory\n", __func__, sizeof(*s)); | ||
515 | goto out; | ||
516 | } | ||
517 | s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; | ||
518 | (*packet_size) = 0; | ||
519 | rc = ecryptfs_get_tfm_and_mutex_for_cipher_name( | ||
520 | &s->desc.tfm, | ||
521 | &s->tfm_mutex, mount_crypt_stat->global_default_fn_cipher_name); | ||
522 | if (unlikely(rc)) { | ||
523 | printk(KERN_ERR "Internal error whilst attempting to get " | ||
524 | "tfm and mutex for cipher name [%s]; rc = [%d]\n", | ||
525 | mount_crypt_stat->global_default_fn_cipher_name, rc); | ||
526 | goto out; | ||
527 | } | ||
528 | mutex_lock(s->tfm_mutex); | ||
529 | s->block_size = crypto_blkcipher_blocksize(s->desc.tfm); | ||
530 | /* Plus one for the \0 separator between the random prefix | ||
531 | * and the plaintext filename */ | ||
532 | s->num_rand_bytes = (ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES + 1); | ||
533 | s->block_aligned_filename_size = (s->num_rand_bytes + filename_size); | ||
534 | if ((s->block_aligned_filename_size % s->block_size) != 0) { | ||
535 | s->num_rand_bytes += (s->block_size | ||
536 | - (s->block_aligned_filename_size | ||
537 | % s->block_size)); | ||
538 | s->block_aligned_filename_size = (s->num_rand_bytes | ||
539 | + filename_size); | ||
540 | } | ||
541 | /* Octet 0: Tag 70 identifier | ||
542 | * Octets 1-N1: Tag 70 packet size (includes cipher identifier | ||
543 | * and block-aligned encrypted filename size) | ||
544 | * Octets N1-N2: FNEK sig (ECRYPTFS_SIG_SIZE) | ||
545 | * Octet N2-N3: Cipher identifier (1 octet) | ||
546 | * Octets N3-N4: Block-aligned encrypted filename | ||
547 | * - Consists of a minimum number of random characters, a \0 | ||
548 | * separator, and then the filename */ | ||
549 | s->max_packet_size = (1 /* Tag 70 identifier */ | ||
550 | + 3 /* Max Tag 70 packet size */ | ||
551 | + ECRYPTFS_SIG_SIZE /* FNEK sig */ | ||
552 | + 1 /* Cipher identifier */ | ||
553 | + s->block_aligned_filename_size); | ||
554 | if (dest == NULL) { | ||
555 | (*packet_size) = s->max_packet_size; | ||
556 | goto out_unlock; | ||
557 | } | ||
558 | if (s->max_packet_size > (*remaining_bytes)) { | ||
559 | printk(KERN_WARNING "%s: Require [%zd] bytes to write; only " | ||
560 | "[%zd] available\n", __func__, s->max_packet_size, | ||
561 | (*remaining_bytes)); | ||
562 | rc = -EINVAL; | ||
563 | goto out_unlock; | ||
564 | } | ||
565 | s->block_aligned_filename = kzalloc(s->block_aligned_filename_size, | ||
566 | GFP_KERNEL); | ||
567 | if (!s->block_aligned_filename) { | ||
568 | printk(KERN_ERR "%s: Out of kernel memory whilst attempting to " | ||
569 | "kzalloc [%zd] bytes\n", __func__, | ||
570 | s->block_aligned_filename_size); | ||
571 | rc = -ENOMEM; | ||
572 | goto out_unlock; | ||
573 | } | ||
574 | s->i = 0; | ||
575 | dest[s->i++] = ECRYPTFS_TAG_70_PACKET_TYPE; | ||
576 | rc = ecryptfs_write_packet_length(&dest[s->i], | ||
577 | (ECRYPTFS_SIG_SIZE | ||
578 | + 1 /* Cipher code */ | ||
579 | + s->block_aligned_filename_size), | ||
580 | &s->packet_size_len); | ||
581 | if (rc) { | ||
582 | printk(KERN_ERR "%s: Error generating tag 70 packet " | ||
583 | "header; cannot generate packet length; rc = [%d]\n", | ||
584 | __func__, rc); | ||
585 | goto out_free_unlock; | ||
586 | } | ||
587 | s->i += s->packet_size_len; | ||
588 | ecryptfs_from_hex(&dest[s->i], | ||
589 | mount_crypt_stat->global_default_fnek_sig, | ||
590 | ECRYPTFS_SIG_SIZE); | ||
591 | s->i += ECRYPTFS_SIG_SIZE; | ||
592 | s->cipher_code = ecryptfs_code_for_cipher_string( | ||
593 | mount_crypt_stat->global_default_fn_cipher_name, | ||
594 | mount_crypt_stat->global_default_fn_cipher_key_bytes); | ||
595 | if (s->cipher_code == 0) { | ||
596 | printk(KERN_WARNING "%s: Unable to generate code for " | ||
597 | "cipher [%s] with key bytes [%zd]\n", __func__, | ||
598 | mount_crypt_stat->global_default_fn_cipher_name, | ||
599 | mount_crypt_stat->global_default_fn_cipher_key_bytes); | ||
600 | rc = -EINVAL; | ||
601 | goto out_free_unlock; | ||
602 | } | ||
603 | dest[s->i++] = s->cipher_code; | ||
604 | rc = ecryptfs_find_auth_tok_for_sig( | ||
605 | &s->auth_tok, mount_crypt_stat, | ||
606 | mount_crypt_stat->global_default_fnek_sig); | ||
607 | if (rc) { | ||
608 | printk(KERN_ERR "%s: Error attempting to find auth tok for " | ||
609 | "fnek sig [%s]; rc = [%d]\n", __func__, | ||
610 | mount_crypt_stat->global_default_fnek_sig, rc); | ||
611 | goto out_free_unlock; | ||
612 | } | ||
613 | /* TODO: Support other key modules than passphrase for | ||
614 | * filename encryption */ | ||
615 | BUG_ON(s->auth_tok->token_type != ECRYPTFS_PASSWORD); | ||
616 | sg_init_one( | ||
617 | &s->hash_sg, | ||
618 | (u8 *)s->auth_tok->token.password.session_key_encryption_key, | ||
619 | s->auth_tok->token.password.session_key_encryption_key_bytes); | ||
620 | s->hash_desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; | ||
621 | s->hash_desc.tfm = crypto_alloc_hash(ECRYPTFS_TAG_70_DIGEST, 0, | ||
622 | CRYPTO_ALG_ASYNC); | ||
623 | if (IS_ERR(s->hash_desc.tfm)) { | ||
624 | rc = PTR_ERR(s->hash_desc.tfm); | ||
625 | printk(KERN_ERR "%s: Error attempting to " | ||
626 | "allocate hash crypto context; rc = [%d]\n", | ||
627 | __func__, rc); | ||
628 | goto out_free_unlock; | ||
629 | } | ||
630 | rc = crypto_hash_init(&s->hash_desc); | ||
631 | if (rc) { | ||
632 | printk(KERN_ERR | ||
633 | "%s: Error initializing crypto hash; rc = [%d]\n", | ||
634 | __func__, rc); | ||
635 | goto out_release_free_unlock; | ||
636 | } | ||
637 | rc = crypto_hash_update( | ||
638 | &s->hash_desc, &s->hash_sg, | ||
639 | s->auth_tok->token.password.session_key_encryption_key_bytes); | ||
640 | if (rc) { | ||
641 | printk(KERN_ERR | ||
642 | "%s: Error updating crypto hash; rc = [%d]\n", | ||
643 | __func__, rc); | ||
644 | goto out_release_free_unlock; | ||
645 | } | ||
646 | rc = crypto_hash_final(&s->hash_desc, s->hash); | ||
647 | if (rc) { | ||
648 | printk(KERN_ERR | ||
649 | "%s: Error finalizing crypto hash; rc = [%d]\n", | ||
650 | __func__, rc); | ||
651 | goto out_release_free_unlock; | ||
652 | } | ||
653 | for (s->j = 0; s->j < (s->num_rand_bytes - 1); s->j++) { | ||
654 | s->block_aligned_filename[s->j] = | ||
655 | s->hash[(s->j % ECRYPTFS_TAG_70_DIGEST_SIZE)]; | ||
656 | if ((s->j % ECRYPTFS_TAG_70_DIGEST_SIZE) | ||
657 | == (ECRYPTFS_TAG_70_DIGEST_SIZE - 1)) { | ||
658 | sg_init_one(&s->hash_sg, (u8 *)s->hash, | ||
659 | ECRYPTFS_TAG_70_DIGEST_SIZE); | ||
660 | rc = crypto_hash_init(&s->hash_desc); | ||
661 | if (rc) { | ||
662 | printk(KERN_ERR | ||
663 | "%s: Error initializing crypto hash; " | ||
664 | "rc = [%d]\n", __func__, rc); | ||
665 | goto out_release_free_unlock; | ||
666 | } | ||
667 | rc = crypto_hash_update(&s->hash_desc, &s->hash_sg, | ||
668 | ECRYPTFS_TAG_70_DIGEST_SIZE); | ||
669 | if (rc) { | ||
670 | printk(KERN_ERR | ||
671 | "%s: Error updating crypto hash; " | ||
672 | "rc = [%d]\n", __func__, rc); | ||
673 | goto out_release_free_unlock; | ||
674 | } | ||
675 | rc = crypto_hash_final(&s->hash_desc, s->tmp_hash); | ||
676 | if (rc) { | ||
677 | printk(KERN_ERR | ||
678 | "%s: Error finalizing crypto hash; " | ||
679 | "rc = [%d]\n", __func__, rc); | ||
680 | goto out_release_free_unlock; | ||
681 | } | ||
682 | memcpy(s->hash, s->tmp_hash, | ||
683 | ECRYPTFS_TAG_70_DIGEST_SIZE); | ||
684 | } | ||
685 | if (s->block_aligned_filename[s->j] == '\0') | ||
686 | s->block_aligned_filename[s->j] = ECRYPTFS_NON_NULL; | ||
687 | } | ||
688 | memcpy(&s->block_aligned_filename[s->num_rand_bytes], filename, | ||
689 | filename_size); | ||
690 | rc = virt_to_scatterlist(s->block_aligned_filename, | ||
691 | s->block_aligned_filename_size, &s->src_sg, 1); | ||
692 | if (rc != 1) { | ||
693 | printk(KERN_ERR "%s: Internal error whilst attempting to " | ||
694 | "convert filename memory to scatterlist; " | ||
695 | "expected rc = 1; got rc = [%d]. " | ||
696 | "block_aligned_filename_size = [%zd]\n", __func__, rc, | ||
697 | s->block_aligned_filename_size); | ||
698 | goto out_release_free_unlock; | ||
699 | } | ||
700 | rc = virt_to_scatterlist(&dest[s->i], s->block_aligned_filename_size, | ||
701 | &s->dst_sg, 1); | ||
702 | if (rc != 1) { | ||
703 | printk(KERN_ERR "%s: Internal error whilst attempting to " | ||
704 | "convert encrypted filename memory to scatterlist; " | ||
705 | "expected rc = 1; got rc = [%d]. " | ||
706 | "block_aligned_filename_size = [%zd]\n", __func__, rc, | ||
707 | s->block_aligned_filename_size); | ||
708 | goto out_release_free_unlock; | ||
709 | } | ||
710 | /* The characters in the first block effectively do the job | ||
711 | * of the IV here, so we just use 0's for the IV. Note the | ||
712 | * constraint that ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES | ||
713 | * >= ECRYPTFS_MAX_IV_BYTES. */ | ||
714 | memset(s->iv, 0, ECRYPTFS_MAX_IV_BYTES); | ||
715 | s->desc.info = s->iv; | ||
716 | rc = crypto_blkcipher_setkey( | ||
717 | s->desc.tfm, | ||
718 | s->auth_tok->token.password.session_key_encryption_key, | ||
719 | mount_crypt_stat->global_default_fn_cipher_key_bytes); | ||
720 | if (rc < 0) { | ||
721 | printk(KERN_ERR "%s: Error setting key for crypto context; " | ||
722 | "rc = [%d]. s->auth_tok->token.password.session_key_" | ||
723 | "encryption_key = [0x%p]; mount_crypt_stat->" | ||
724 | "global_default_fn_cipher_key_bytes = [%zd]\n", __func__, | ||
725 | rc, | ||
726 | s->auth_tok->token.password.session_key_encryption_key, | ||
727 | mount_crypt_stat->global_default_fn_cipher_key_bytes); | ||
728 | goto out_release_free_unlock; | ||
729 | } | ||
730 | rc = crypto_blkcipher_encrypt_iv(&s->desc, &s->dst_sg, &s->src_sg, | ||
731 | s->block_aligned_filename_size); | ||
732 | if (rc) { | ||
733 | printk(KERN_ERR "%s: Error attempting to encrypt filename; " | ||
734 | "rc = [%d]\n", __func__, rc); | ||
735 | goto out_release_free_unlock; | ||
736 | } | ||
737 | s->i += s->block_aligned_filename_size; | ||
738 | (*packet_size) = s->i; | ||
739 | (*remaining_bytes) -= (*packet_size); | ||
740 | out_release_free_unlock: | ||
741 | crypto_free_hash(s->hash_desc.tfm); | ||
742 | out_free_unlock: | ||
743 | memset(s->block_aligned_filename, 0, s->block_aligned_filename_size); | ||
744 | kfree(s->block_aligned_filename); | ||
745 | out_unlock: | ||
746 | mutex_unlock(s->tfm_mutex); | ||
747 | out: | ||
748 | kfree(s); | ||
749 | return rc; | ||
750 | } | ||
751 | |||
752 | struct ecryptfs_parse_tag_70_packet_silly_stack { | ||
753 | u8 cipher_code; | ||
754 | size_t max_packet_size; | ||
755 | size_t packet_size_len; | ||
756 | size_t parsed_tag_70_packet_size; | ||
757 | size_t block_aligned_filename_size; | ||
758 | size_t block_size; | ||
759 | size_t i; | ||
760 | struct mutex *tfm_mutex; | ||
761 | char *decrypted_filename; | ||
762 | struct ecryptfs_auth_tok *auth_tok; | ||
763 | struct scatterlist src_sg; | ||
764 | struct scatterlist dst_sg; | ||
765 | struct blkcipher_desc desc; | ||
766 | char fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX + 1]; | ||
767 | char iv[ECRYPTFS_MAX_IV_BYTES]; | ||
768 | char cipher_string[ECRYPTFS_MAX_CIPHER_NAME_SIZE]; | ||
769 | }; | ||
770 | |||
771 | /** | ||
772 | * parse_tag_70_packet - Parse and process FNEK-encrypted passphrase packet | ||
773 | * @filename: This function kmalloc's the memory for the filename | ||
774 | * @filename_size: This function sets this to the amount of memory | ||
775 | * kmalloc'd for the filename | ||
776 | * @packet_size: This function sets this to the the number of octets | ||
777 | * in the packet parsed | ||
778 | * @mount_crypt_stat: The mount-wide cryptographic context | ||
779 | * @data: The memory location containing the start of the tag 70 | ||
780 | * packet | ||
781 | * @max_packet_size: The maximum legal size of the packet to be parsed | ||
782 | * from @data | ||
783 | * | ||
784 | * Returns zero on success; non-zero otherwise | ||
785 | */ | ||
786 | int | ||
787 | ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, | ||
788 | size_t *packet_size, | ||
789 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat, | ||
790 | char *data, size_t max_packet_size) | ||
791 | { | ||
792 | struct ecryptfs_parse_tag_70_packet_silly_stack *s; | ||
793 | int rc = 0; | ||
794 | |||
795 | (*packet_size) = 0; | ||
796 | (*filename_size) = 0; | ||
797 | (*filename) = NULL; | ||
798 | s = kmalloc(sizeof(*s), GFP_KERNEL); | ||
799 | if (!s) { | ||
800 | printk(KERN_ERR "%s: Out of memory whilst trying to kmalloc " | ||
801 | "[%zd] bytes of kernel memory\n", __func__, sizeof(*s)); | ||
802 | goto out; | ||
803 | } | ||
804 | s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; | ||
805 | if (max_packet_size < (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1)) { | ||
806 | printk(KERN_WARNING "%s: max_packet_size is [%zd]; it must be " | ||
807 | "at least [%d]\n", __func__, max_packet_size, | ||
808 | (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1)); | ||
809 | rc = -EINVAL; | ||
810 | goto out; | ||
811 | } | ||
812 | /* Octet 0: Tag 70 identifier | ||
813 | * Octets 1-N1: Tag 70 packet size (includes cipher identifier | ||
814 | * and block-aligned encrypted filename size) | ||
815 | * Octets N1-N2: FNEK sig (ECRYPTFS_SIG_SIZE) | ||
816 | * Octet N2-N3: Cipher identifier (1 octet) | ||
817 | * Octets N3-N4: Block-aligned encrypted filename | ||
818 | * - Consists of a minimum number of random numbers, a \0 | ||
819 | * separator, and then the filename */ | ||
820 | if (data[(*packet_size)++] != ECRYPTFS_TAG_70_PACKET_TYPE) { | ||
821 | printk(KERN_WARNING "%s: Invalid packet tag [0x%.2x]; must be " | ||
822 | "tag [0x%.2x]\n", __func__, | ||
823 | data[((*packet_size) - 1)], ECRYPTFS_TAG_70_PACKET_TYPE); | ||
824 | rc = -EINVAL; | ||
825 | goto out; | ||
826 | } | ||
827 | rc = ecryptfs_parse_packet_length(&data[(*packet_size)], | ||
828 | &s->parsed_tag_70_packet_size, | ||
829 | &s->packet_size_len); | ||
830 | if (rc) { | ||
831 | printk(KERN_WARNING "%s: Error parsing packet length; " | ||
832 | "rc = [%d]\n", __func__, rc); | ||
833 | goto out; | ||
834 | } | ||
835 | s->block_aligned_filename_size = (s->parsed_tag_70_packet_size | ||
836 | - ECRYPTFS_SIG_SIZE - 1); | ||
837 | if ((1 + s->packet_size_len + s->parsed_tag_70_packet_size) | ||
838 | > max_packet_size) { | ||
839 | printk(KERN_WARNING "%s: max_packet_size is [%zd]; real packet " | ||
840 | "size is [%zd]\n", __func__, max_packet_size, | ||
841 | (1 + s->packet_size_len + 1 | ||
842 | + s->block_aligned_filename_size)); | ||
843 | rc = -EINVAL; | ||
844 | goto out; | ||
845 | } | ||
846 | (*packet_size) += s->packet_size_len; | ||
847 | ecryptfs_to_hex(s->fnek_sig_hex, &data[(*packet_size)], | ||
848 | ECRYPTFS_SIG_SIZE); | ||
849 | s->fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX] = '\0'; | ||
850 | (*packet_size) += ECRYPTFS_SIG_SIZE; | ||
851 | s->cipher_code = data[(*packet_size)++]; | ||
852 | rc = ecryptfs_cipher_code_to_string(s->cipher_string, s->cipher_code); | ||
853 | if (rc) { | ||
854 | printk(KERN_WARNING "%s: Cipher code [%d] is invalid\n", | ||
855 | __func__, s->cipher_code); | ||
856 | goto out; | ||
857 | } | ||
858 | rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&s->desc.tfm, | ||
859 | &s->tfm_mutex, | ||
860 | s->cipher_string); | ||
861 | if (unlikely(rc)) { | ||
862 | printk(KERN_ERR "Internal error whilst attempting to get " | ||
863 | "tfm and mutex for cipher name [%s]; rc = [%d]\n", | ||
864 | s->cipher_string, rc); | ||
865 | goto out; | ||
866 | } | ||
867 | mutex_lock(s->tfm_mutex); | ||
868 | rc = virt_to_scatterlist(&data[(*packet_size)], | ||
869 | s->block_aligned_filename_size, &s->src_sg, 1); | ||
870 | if (rc != 1) { | ||
871 | printk(KERN_ERR "%s: Internal error whilst attempting to " | ||
872 | "convert encrypted filename memory to scatterlist; " | ||
873 | "expected rc = 1; got rc = [%d]. " | ||
874 | "block_aligned_filename_size = [%zd]\n", __func__, rc, | ||
875 | s->block_aligned_filename_size); | ||
876 | goto out_unlock; | ||
877 | } | ||
878 | (*packet_size) += s->block_aligned_filename_size; | ||
879 | s->decrypted_filename = kmalloc(s->block_aligned_filename_size, | ||
880 | GFP_KERNEL); | ||
881 | if (!s->decrypted_filename) { | ||
882 | printk(KERN_ERR "%s: Out of memory whilst attempting to " | ||
883 | "kmalloc [%zd] bytes\n", __func__, | ||
884 | s->block_aligned_filename_size); | ||
885 | rc = -ENOMEM; | ||
886 | goto out_unlock; | ||
887 | } | ||
888 | rc = virt_to_scatterlist(s->decrypted_filename, | ||
889 | s->block_aligned_filename_size, &s->dst_sg, 1); | ||
890 | if (rc != 1) { | ||
891 | printk(KERN_ERR "%s: Internal error whilst attempting to " | ||
892 | "convert decrypted filename memory to scatterlist; " | ||
893 | "expected rc = 1; got rc = [%d]. " | ||
894 | "block_aligned_filename_size = [%zd]\n", __func__, rc, | ||
895 | s->block_aligned_filename_size); | ||
896 | goto out_free_unlock; | ||
897 | } | ||
898 | /* The characters in the first block effectively do the job of | ||
899 | * the IV here, so we just use 0's for the IV. Note the | ||
900 | * constraint that ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES | ||
901 | * >= ECRYPTFS_MAX_IV_BYTES. */ | ||
902 | memset(s->iv, 0, ECRYPTFS_MAX_IV_BYTES); | ||
903 | s->desc.info = s->iv; | ||
904 | rc = ecryptfs_find_auth_tok_for_sig(&s->auth_tok, mount_crypt_stat, | ||
905 | s->fnek_sig_hex); | ||
906 | if (rc) { | ||
907 | printk(KERN_ERR "%s: Error attempting to find auth tok for " | ||
908 | "fnek sig [%s]; rc = [%d]\n", __func__, s->fnek_sig_hex, | ||
909 | rc); | ||
910 | goto out_free_unlock; | ||
911 | } | ||
912 | /* TODO: Support other key modules than passphrase for | ||
913 | * filename encryption */ | ||
914 | BUG_ON(s->auth_tok->token_type != ECRYPTFS_PASSWORD); | ||
915 | rc = crypto_blkcipher_setkey( | ||
916 | s->desc.tfm, | ||
917 | s->auth_tok->token.password.session_key_encryption_key, | ||
918 | mount_crypt_stat->global_default_fn_cipher_key_bytes); | ||
919 | if (rc < 0) { | ||
920 | printk(KERN_ERR "%s: Error setting key for crypto context; " | ||
921 | "rc = [%d]. s->auth_tok->token.password.session_key_" | ||
922 | "encryption_key = [0x%p]; mount_crypt_stat->" | ||
923 | "global_default_fn_cipher_key_bytes = [%zd]\n", __func__, | ||
924 | rc, | ||
925 | s->auth_tok->token.password.session_key_encryption_key, | ||
926 | mount_crypt_stat->global_default_fn_cipher_key_bytes); | ||
927 | goto out_free_unlock; | ||
928 | } | ||
929 | rc = crypto_blkcipher_decrypt_iv(&s->desc, &s->dst_sg, &s->src_sg, | ||
930 | s->block_aligned_filename_size); | ||
931 | if (rc) { | ||
932 | printk(KERN_ERR "%s: Error attempting to decrypt filename; " | ||
933 | "rc = [%d]\n", __func__, rc); | ||
934 | goto out_free_unlock; | ||
935 | } | ||
936 | s->i = 0; | ||
937 | while (s->decrypted_filename[s->i] != '\0' | ||
938 | && s->i < s->block_aligned_filename_size) | ||
939 | s->i++; | ||
940 | if (s->i == s->block_aligned_filename_size) { | ||
941 | printk(KERN_WARNING "%s: Invalid tag 70 packet; could not " | ||
942 | "find valid separator between random characters and " | ||
943 | "the filename\n", __func__); | ||
944 | rc = -EINVAL; | ||
945 | goto out_free_unlock; | ||
946 | } | ||
947 | s->i++; | ||
948 | (*filename_size) = (s->block_aligned_filename_size - s->i); | ||
949 | if (!((*filename_size) > 0 && (*filename_size < PATH_MAX))) { | ||
950 | printk(KERN_WARNING "%s: Filename size is [%zd], which is " | ||
951 | "invalid\n", __func__, (*filename_size)); | ||
952 | rc = -EINVAL; | ||
953 | goto out_free_unlock; | ||
954 | } | ||
955 | (*filename) = kmalloc(((*filename_size) + 1), GFP_KERNEL); | ||
956 | if (!(*filename)) { | ||
957 | printk(KERN_ERR "%s: Out of memory whilst attempting to " | ||
958 | "kmalloc [%zd] bytes\n", __func__, | ||
959 | ((*filename_size) + 1)); | ||
960 | rc = -ENOMEM; | ||
961 | goto out_free_unlock; | ||
962 | } | ||
963 | memcpy((*filename), &s->decrypted_filename[s->i], (*filename_size)); | ||
964 | (*filename)[(*filename_size)] = '\0'; | ||
965 | out_free_unlock: | ||
966 | kfree(s->decrypted_filename); | ||
967 | out_unlock: | ||
968 | mutex_unlock(s->tfm_mutex); | ||
969 | out: | ||
970 | if (rc) { | ||
971 | (*packet_size) = 0; | ||
972 | (*filename_size) = 0; | ||
973 | (*filename) = NULL; | ||
974 | } | ||
975 | kfree(s); | ||
976 | return rc; | ||
977 | } | ||
978 | |||
979 | static int | ||
406 | ecryptfs_get_auth_tok_sig(char **sig, struct ecryptfs_auth_tok *auth_tok) | 980 | ecryptfs_get_auth_tok_sig(char **sig, struct ecryptfs_auth_tok *auth_tok) |
407 | { | 981 | { |
408 | int rc = 0; | 982 | int rc = 0; |
@@ -897,30 +1471,6 @@ out: | |||
897 | return rc; | 1471 | return rc; |
898 | } | 1472 | } |
899 | 1473 | ||
900 | static int | ||
901 | ecryptfs_find_global_auth_tok_for_sig( | ||
902 | struct ecryptfs_global_auth_tok **global_auth_tok, | ||
903 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig) | ||
904 | { | ||
905 | struct ecryptfs_global_auth_tok *walker; | ||
906 | int rc = 0; | ||
907 | |||
908 | (*global_auth_tok) = NULL; | ||
909 | mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); | ||
910 | list_for_each_entry(walker, | ||
911 | &mount_crypt_stat->global_auth_tok_list, | ||
912 | mount_crypt_stat_list) { | ||
913 | if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX) == 0) { | ||
914 | (*global_auth_tok) = walker; | ||
915 | goto out; | ||
916 | } | ||
917 | } | ||
918 | rc = -EINVAL; | ||
919 | out: | ||
920 | mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); | ||
921 | return rc; | ||
922 | } | ||
923 | |||
924 | /** | 1474 | /** |
925 | * ecryptfs_verify_version | 1475 | * ecryptfs_verify_version |
926 | * @version: The version number to confirm | 1476 | * @version: The version number to confirm |
@@ -990,43 +1540,6 @@ out: | |||
990 | } | 1540 | } |
991 | 1541 | ||
992 | /** | 1542 | /** |
993 | * ecryptfs_find_auth_tok_for_sig | ||
994 | * @auth_tok: Set to the matching auth_tok; NULL if not found | ||
995 | * @crypt_stat: inode crypt_stat crypto context | ||
996 | * @sig: Sig of auth_tok to find | ||
997 | * | ||
998 | * For now, this function simply looks at the registered auth_tok's | ||
999 | * linked off the mount_crypt_stat, so all the auth_toks that can be | ||
1000 | * used must be registered at mount time. This function could | ||
1001 | * potentially try a lot harder to find auth_tok's (e.g., by calling | ||
1002 | * out to ecryptfsd to dynamically retrieve an auth_tok object) so | ||
1003 | * that static registration of auth_tok's will no longer be necessary. | ||
1004 | * | ||
1005 | * Returns zero on no error; non-zero on error | ||
1006 | */ | ||
1007 | static int | ||
1008 | ecryptfs_find_auth_tok_for_sig( | ||
1009 | struct ecryptfs_auth_tok **auth_tok, | ||
1010 | struct ecryptfs_crypt_stat *crypt_stat, char *sig) | ||
1011 | { | ||
1012 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat = | ||
1013 | crypt_stat->mount_crypt_stat; | ||
1014 | struct ecryptfs_global_auth_tok *global_auth_tok; | ||
1015 | int rc = 0; | ||
1016 | |||
1017 | (*auth_tok) = NULL; | ||
1018 | if (ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok, | ||
1019 | mount_crypt_stat, sig)) { | ||
1020 | struct key *auth_tok_key; | ||
1021 | |||
1022 | rc = ecryptfs_keyring_auth_tok_for_sig(&auth_tok_key, auth_tok, | ||
1023 | sig); | ||
1024 | } else | ||
1025 | (*auth_tok) = global_auth_tok->global_auth_tok; | ||
1026 | return rc; | ||
1027 | } | ||
1028 | |||
1029 | /** | ||
1030 | * decrypt_passphrase_encrypted_session_key - Decrypt the session key with the given auth_tok. | 1543 | * decrypt_passphrase_encrypted_session_key - Decrypt the session key with the given auth_tok. |
1031 | * @auth_tok: The passphrase authentication token to use to encrypt the FEK | 1544 | * @auth_tok: The passphrase authentication token to use to encrypt the FEK |
1032 | * @crypt_stat: The cryptographic context | 1545 | * @crypt_stat: The cryptographic context |
@@ -1256,7 +1769,8 @@ find_next_matching_auth_tok: | |||
1256 | rc = -EINVAL; | 1769 | rc = -EINVAL; |
1257 | goto out_wipe_list; | 1770 | goto out_wipe_list; |
1258 | } | 1771 | } |
1259 | ecryptfs_find_auth_tok_for_sig(&matching_auth_tok, crypt_stat, | 1772 | ecryptfs_find_auth_tok_for_sig(&matching_auth_tok, |
1773 | crypt_stat->mount_crypt_stat, | ||
1260 | candidate_auth_tok_sig); | 1774 | candidate_auth_tok_sig); |
1261 | if (matching_auth_tok) { | 1775 | if (matching_auth_tok) { |
1262 | found_auth_tok = 1; | 1776 | found_auth_tok = 1; |
@@ -1336,7 +1850,9 @@ pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok, | |||
1336 | int rc; | 1850 | int rc; |
1337 | 1851 | ||
1338 | rc = write_tag_66_packet(auth_tok->token.private_key.signature, | 1852 | rc = write_tag_66_packet(auth_tok->token.private_key.signature, |
1339 | ecryptfs_code_for_cipher_string(crypt_stat), | 1853 | ecryptfs_code_for_cipher_string( |
1854 | crypt_stat->cipher, | ||
1855 | crypt_stat->key_size), | ||
1340 | crypt_stat, &payload, &payload_len); | 1856 | crypt_stat, &payload, &payload_len); |
1341 | if (rc) { | 1857 | if (rc) { |
1342 | ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet\n"); | 1858 | ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet\n"); |
@@ -1696,7 +2212,8 @@ encrypted_session_key_set: | |||
1696 | dest[(*packet_size)++] = 0x04; /* version 4 */ | 2212 | dest[(*packet_size)++] = 0x04; /* version 4 */ |
1697 | /* TODO: Break from RFC2440 so that arbitrary ciphers can be | 2213 | /* TODO: Break from RFC2440 so that arbitrary ciphers can be |
1698 | * specified with strings */ | 2214 | * specified with strings */ |
1699 | cipher_code = ecryptfs_code_for_cipher_string(crypt_stat); | 2215 | cipher_code = ecryptfs_code_for_cipher_string(crypt_stat->cipher, |
2216 | crypt_stat->key_size); | ||
1700 | if (cipher_code == 0) { | 2217 | if (cipher_code == 0) { |
1701 | ecryptfs_printk(KERN_WARNING, "Unable to generate code for " | 2218 | ecryptfs_printk(KERN_WARNING, "Unable to generate code for " |
1702 | "cipher [%s]\n", crypt_stat->cipher); | 2219 | "cipher [%s]\n", crypt_stat->cipher); |