diff options
author | Michael Halcrow <mhalcrow@us.ibm.com> | 2007-10-16 04:27:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:43:11 -0400 |
commit | c59becfceea8de57c35a3de5ee45a7bb883cf90a (patch) | |
tree | 1e3721371ddf6d37ba08f528a21595a2ace1dd31 /fs/ecryptfs | |
parent | 132181796af08273ab9fa835420b9f5f78d70234 (diff) |
eCryptfs: fix Tag 3 parsing code
Fix up the Tag 3 parsing code to handle size limits and boundaries more
explicitly.
Signed-off-by: Michael Halcrow <mhalcrow@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r-- | fs/ecryptfs/keystore.c | 89 |
1 files changed, 35 insertions, 54 deletions
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index f7debe6961d1..72086141a6e8 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c | |||
@@ -643,22 +643,30 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat, | |||
643 | 643 | ||
644 | (*packet_size) = 0; | 644 | (*packet_size) = 0; |
645 | (*new_auth_tok) = NULL; | 645 | (*new_auth_tok) = NULL; |
646 | 646 | /** | |
647 | /* we check that: | 647 | *This format is inspired by OpenPGP; see RFC 2440 |
648 | * one byte for the Tag 3 ID flag | 648 | * packet tag 3 |
649 | * two bytes for the body size | 649 | * |
650 | * do not exceed the maximum_packet_size | 650 | * Tag 3 identifier (1 byte) |
651 | * Max Tag 3 packet size (max 3 bytes) | ||
652 | * Version (1 byte) | ||
653 | * Cipher code (1 byte) | ||
654 | * S2K specifier (1 byte) | ||
655 | * Hash identifier (1 byte) | ||
656 | * Salt (ECRYPTFS_SALT_SIZE) | ||
657 | * Hash iterations (1 byte) | ||
658 | * Encrypted key (arbitrary) | ||
659 | * | ||
660 | * (ECRYPTFS_SALT_SIZE + 7) minimum packet size | ||
651 | */ | 661 | */ |
652 | if (unlikely((*packet_size) + 3 > max_packet_size)) { | 662 | if (max_packet_size < (ECRYPTFS_SALT_SIZE + 7)) { |
653 | ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n"); | 663 | printk(KERN_ERR "Max packet size too large\n"); |
654 | rc = -EINVAL; | 664 | rc = -EINVAL; |
655 | goto out; | 665 | goto out; |
656 | } | 666 | } |
657 | |||
658 | /* check for Tag 3 identifyer - one byte */ | ||
659 | if (data[(*packet_size)++] != ECRYPTFS_TAG_3_PACKET_TYPE) { | 667 | if (data[(*packet_size)++] != ECRYPTFS_TAG_3_PACKET_TYPE) { |
660 | ecryptfs_printk(KERN_ERR, "Enter w/ first byte != 0x%.2x\n", | 668 | printk(KERN_ERR "First byte != 0x%.2x; invalid packet\n", |
661 | ECRYPTFS_TAG_3_PACKET_TYPE); | 669 | ECRYPTFS_TAG_3_PACKET_TYPE); |
662 | rc = -EINVAL; | 670 | rc = -EINVAL; |
663 | goto out; | 671 | goto out; |
664 | } | 672 | } |
@@ -667,56 +675,36 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat, | |||
667 | auth_tok_list_item = | 675 | auth_tok_list_item = |
668 | kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache, GFP_KERNEL); | 676 | kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache, GFP_KERNEL); |
669 | if (!auth_tok_list_item) { | 677 | if (!auth_tok_list_item) { |
670 | ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n"); | 678 | printk(KERN_ERR "Unable to allocate memory\n"); |
671 | rc = -ENOMEM; | 679 | rc = -ENOMEM; |
672 | goto out; | 680 | goto out; |
673 | } | 681 | } |
674 | (*new_auth_tok) = &auth_tok_list_item->auth_tok; | 682 | (*new_auth_tok) = &auth_tok_list_item->auth_tok; |
675 | 683 | if ((rc = parse_packet_length(&data[(*packet_size)], &body_size, | |
676 | /* check for body size - one to two bytes */ | 684 | &length_size))) { |
677 | rc = parse_packet_length(&data[(*packet_size)], &body_size, | 685 | printk(KERN_WARNING "Error parsing packet length; rc = [%d]\n", |
678 | &length_size); | 686 | rc); |
679 | if (rc) { | ||
680 | ecryptfs_printk(KERN_WARNING, "Error parsing packet length; " | ||
681 | "rc = [%d]\n", rc); | ||
682 | goto out_free; | 687 | goto out_free; |
683 | } | 688 | } |
684 | if (unlikely(body_size < (0x05 + ECRYPTFS_SALT_SIZE))) { | 689 | if (unlikely(body_size < (ECRYPTFS_SALT_SIZE + 5))) { |
685 | ecryptfs_printk(KERN_WARNING, "Invalid body size ([%d])\n", | 690 | printk(KERN_WARNING "Invalid body size ([%d])\n", body_size); |
686 | body_size); | ||
687 | rc = -EINVAL; | 691 | rc = -EINVAL; |
688 | goto out_free; | 692 | goto out_free; |
689 | } | 693 | } |
690 | (*packet_size) += length_size; | 694 | (*packet_size) += length_size; |
691 | |||
692 | /* now we know the length of the remainting Tag 3 packet size: | ||
693 | * 5 fix bytes for: version string, cipher, S2K ID, hash algo, | ||
694 | * number of hash iterations | ||
695 | * ECRYPTFS_SALT_SIZE bytes for salt | ||
696 | * body_size bytes minus the stuff above is the encrypted key size | ||
697 | */ | ||
698 | if (unlikely((*packet_size) + body_size > max_packet_size)) { | 695 | if (unlikely((*packet_size) + body_size > max_packet_size)) { |
699 | ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n"); | 696 | printk(KERN_ERR "Packet size exceeds max\n"); |
700 | rc = -EINVAL; | 697 | rc = -EINVAL; |
701 | goto out_free; | 698 | goto out_free; |
702 | } | 699 | } |
703 | |||
704 | /* There are 5 characters of additional information in the | ||
705 | * packet */ | ||
706 | (*new_auth_tok)->session_key.encrypted_key_size = | 700 | (*new_auth_tok)->session_key.encrypted_key_size = |
707 | body_size - (0x05 + ECRYPTFS_SALT_SIZE); | 701 | (body_size - (ECRYPTFS_SALT_SIZE + 5)); |
708 | ecryptfs_printk(KERN_DEBUG, "Encrypted key size = [%d]\n", | ||
709 | (*new_auth_tok)->session_key.encrypted_key_size); | ||
710 | |||
711 | /* Version 4 (from RFC2440) - one byte */ | ||
712 | if (unlikely(data[(*packet_size)++] != 0x04)) { | 702 | if (unlikely(data[(*packet_size)++] != 0x04)) { |
713 | ecryptfs_printk(KERN_DEBUG, "Unknown version number " | 703 | printk(KERN_WARNING "Unknown version number [%d]\n", |
714 | "[%d]\n", data[(*packet_size) - 1]); | 704 | data[(*packet_size) - 1]); |
715 | rc = -EINVAL; | 705 | rc = -EINVAL; |
716 | goto out_free; | 706 | goto out_free; |
717 | } | 707 | } |
718 | |||
719 | /* cipher - one byte */ | ||
720 | ecryptfs_cipher_code_to_string(crypt_stat->cipher, | 708 | ecryptfs_cipher_code_to_string(crypt_stat->cipher, |
721 | (u16)data[(*packet_size)]); | 709 | (u16)data[(*packet_size)]); |
722 | /* A little extra work to differentiate among the AES key | 710 | /* A little extra work to differentiate among the AES key |
@@ -730,33 +718,26 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat, | |||
730 | (*new_auth_tok)->session_key.encrypted_key_size; | 718 | (*new_auth_tok)->session_key.encrypted_key_size; |
731 | } | 719 | } |
732 | ecryptfs_init_crypt_ctx(crypt_stat); | 720 | ecryptfs_init_crypt_ctx(crypt_stat); |
733 | /* S2K identifier 3 (from RFC2440) */ | ||
734 | if (unlikely(data[(*packet_size)++] != 0x03)) { | 721 | if (unlikely(data[(*packet_size)++] != 0x03)) { |
735 | ecryptfs_printk(KERN_ERR, "Only S2K ID 3 is currently " | 722 | printk(KERN_WARNING "Only S2K ID 3 is currently supported\n"); |
736 | "supported\n"); | ||
737 | rc = -ENOSYS; | 723 | rc = -ENOSYS; |
738 | goto out_free; | 724 | goto out_free; |
739 | } | 725 | } |
740 | |||
741 | /* TODO: finish the hash mapping */ | 726 | /* TODO: finish the hash mapping */ |
742 | /* hash algorithm - one byte */ | ||
743 | switch (data[(*packet_size)++]) { | 727 | switch (data[(*packet_size)++]) { |
744 | case 0x01: /* See RFC2440 for these numbers and their mappings */ | 728 | case 0x01: /* See RFC2440 for these numbers and their mappings */ |
745 | /* Choose MD5 */ | 729 | /* Choose MD5 */ |
746 | /* salt - ECRYPTFS_SALT_SIZE bytes */ | ||
747 | memcpy((*new_auth_tok)->token.password.salt, | 730 | memcpy((*new_auth_tok)->token.password.salt, |
748 | &data[(*packet_size)], ECRYPTFS_SALT_SIZE); | 731 | &data[(*packet_size)], ECRYPTFS_SALT_SIZE); |
749 | (*packet_size) += ECRYPTFS_SALT_SIZE; | 732 | (*packet_size) += ECRYPTFS_SALT_SIZE; |
750 | |||
751 | /* This conversion was taken straight from RFC2440 */ | 733 | /* This conversion was taken straight from RFC2440 */ |
752 | /* number of hash iterations - one byte */ | ||
753 | (*new_auth_tok)->token.password.hash_iterations = | 734 | (*new_auth_tok)->token.password.hash_iterations = |
754 | ((u32) 16 + (data[(*packet_size)] & 15)) | 735 | ((u32) 16 + (data[(*packet_size)] & 15)) |
755 | << ((data[(*packet_size)] >> 4) + 6); | 736 | << ((data[(*packet_size)] >> 4) + 6); |
756 | (*packet_size)++; | 737 | (*packet_size)++; |
757 | 738 | /* Friendly reminder: | |
758 | /* encrypted session key - | 739 | * (*new_auth_tok)->session_key.encrypted_key_size = |
759 | * (body_size-5-ECRYPTFS_SALT_SIZE) bytes */ | 740 | * (body_size - (ECRYPTFS_SALT_SIZE + 5)); */ |
760 | memcpy((*new_auth_tok)->session_key.encrypted_key, | 741 | memcpy((*new_auth_tok)->session_key.encrypted_key, |
761 | &data[(*packet_size)], | 742 | &data[(*packet_size)], |
762 | (*new_auth_tok)->session_key.encrypted_key_size); | 743 | (*new_auth_tok)->session_key.encrypted_key_size); |
@@ -766,7 +747,7 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat, | |||
766 | ~ECRYPTFS_CONTAINS_DECRYPTED_KEY; | 747 | ~ECRYPTFS_CONTAINS_DECRYPTED_KEY; |
767 | (*new_auth_tok)->session_key.flags |= | 748 | (*new_auth_tok)->session_key.flags |= |
768 | ECRYPTFS_CONTAINS_ENCRYPTED_KEY; | 749 | ECRYPTFS_CONTAINS_ENCRYPTED_KEY; |
769 | (*new_auth_tok)->token.password.hash_algo = 0x01; | 750 | (*new_auth_tok)->token.password.hash_algo = 0x01; /* MD5 */ |
770 | break; | 751 | break; |
771 | default: | 752 | default: |
772 | ecryptfs_printk(KERN_ERR, "Unsupported hash algorithm: " | 753 | ecryptfs_printk(KERN_ERR, "Unsupported hash algorithm: " |