Commit 13218179 authored by Michael Halcrow's avatar Michael Halcrow Committed by Linus Torvalds

eCryptfs: fix Tag 1 parsing code

Fix up the Tag 1 parsing code to handle size limits and boundaries more
explicitly.  Initialize the new auth_tok's flags.
Signed-off-by: default avatarMichael Halcrow <mhalcrow@us.ibm.com>
Cc: Josef Sipek <jsipek@fsl.cs.sunysb.edu>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 956159c3
...@@ -512,72 +512,64 @@ parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat, ...@@ -512,72 +512,64 @@ parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat,
(*packet_size) = 0; (*packet_size) = 0;
(*new_auth_tok) = NULL; (*new_auth_tok) = NULL;
/**
/* we check that: * This format is inspired by OpenPGP; see RFC 2440
* one byte for the Tag 1 ID flag * packet tag 1
* two bytes for the body size *
* do not exceed the maximum_packet_size * Tag 1 identifier (1 byte)
* Max Tag 1 packet size (max 3 bytes)
* Version (1 byte)
* Key identifier (8 bytes; ECRYPTFS_SIG_SIZE)
* Cipher identifier (1 byte)
* Encrypted key size (arbitrary)
*
* 12 bytes minimum packet size
*/ */
if (unlikely((*packet_size) + 3 > max_packet_size)) { if (unlikely(max_packet_size < 12)) {
ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n"); printk(KERN_ERR "Invalid max packet size; must be >=12\n");
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
/* check for Tag 1 identifier - one byte */
if (data[(*packet_size)++] != ECRYPTFS_TAG_1_PACKET_TYPE) { if (data[(*packet_size)++] != ECRYPTFS_TAG_1_PACKET_TYPE) {
ecryptfs_printk(KERN_ERR, "Enter w/ first byte != 0x%.2x\n", printk(KERN_ERR "Enter w/ first byte != 0x%.2x\n",
ECRYPTFS_TAG_1_PACKET_TYPE); ECRYPTFS_TAG_1_PACKET_TYPE);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
/* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or /* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or
* at end of function upon failure */ * at end of function upon failure */
auth_tok_list_item = auth_tok_list_item =
kmem_cache_alloc(ecryptfs_auth_tok_list_item_cache, kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache,
GFP_KERNEL); GFP_KERNEL);
if (!auth_tok_list_item) { if (!auth_tok_list_item) {
ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n"); printk(KERN_ERR "Unable to allocate memory\n");
rc = -ENOMEM; rc = -ENOMEM;
goto out; goto out;
} }
memset(auth_tok_list_item, 0,
sizeof(struct ecryptfs_auth_tok_list_item));
(*new_auth_tok) = &auth_tok_list_item->auth_tok; (*new_auth_tok) = &auth_tok_list_item->auth_tok;
/* check for body size - one to two bytes if ((rc = parse_packet_length(&data[(*packet_size)], &body_size,
* &length_size))) {
* ***** TAG 1 Packet Format ***** printk(KERN_WARNING "Error parsing packet length; "
* | version number | 1 byte | "rc = [%d]\n", rc);
* | key ID | 8 bytes |
* | public key algorithm | 1 byte |
* | encrypted session key | arbitrary |
*/
rc = parse_packet_length(&data[(*packet_size)], &body_size,
&length_size);
if (rc) {
ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
"rc = [%d]\n", rc);
goto out_free; goto out_free;
} }
if (unlikely(body_size < (0x02 + ECRYPTFS_SIG_SIZE))) { if (unlikely(body_size < (ECRYPTFS_SIG_SIZE + 2))) {
ecryptfs_printk(KERN_WARNING, "Invalid body size ([%d])\n", printk(KERN_WARNING "Invalid body size ([%d])\n", body_size);
body_size);
rc = -EINVAL; rc = -EINVAL;
goto out_free; goto out_free;
} }
(*packet_size) += length_size; (*packet_size) += length_size;
if (unlikely((*packet_size) + body_size > max_packet_size)) { if (unlikely((*packet_size) + body_size > max_packet_size)) {
ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n"); printk(KERN_WARNING "Packet size exceeds max\n");
rc = -EINVAL; rc = -EINVAL;
goto out_free; goto out_free;
} }
/* Version 3 (from RFC2440) - one byte */
if (unlikely(data[(*packet_size)++] != 0x03)) { if (unlikely(data[(*packet_size)++] != 0x03)) {
ecryptfs_printk(KERN_DEBUG, "Unknown version number " printk(KERN_WARNING "Unknown version number [%d]\n",
"[%d]\n", data[(*packet_size) - 1]); data[(*packet_size) - 1]);
rc = -EINVAL; rc = -EINVAL;
goto out_free; goto out_free;
} }
/* Read Signature */
ecryptfs_to_hex((*new_auth_tok)->token.private_key.signature, ecryptfs_to_hex((*new_auth_tok)->token.private_key.signature,
&data[(*packet_size)], ECRYPTFS_SIG_SIZE); &data[(*packet_size)], ECRYPTFS_SIG_SIZE);
*packet_size += ECRYPTFS_SIG_SIZE; *packet_size += ECRYPTFS_SIG_SIZE;
...@@ -585,27 +577,23 @@ parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat, ...@@ -585,27 +577,23 @@ parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat,
* know which public key encryption algorithm was used */ * know which public key encryption algorithm was used */
(*packet_size)++; (*packet_size)++;
(*new_auth_tok)->session_key.encrypted_key_size = (*new_auth_tok)->session_key.encrypted_key_size =
body_size - (0x02 + ECRYPTFS_SIG_SIZE); body_size - (ECRYPTFS_SIG_SIZE + 2);
if ((*new_auth_tok)->session_key.encrypted_key_size if ((*new_auth_tok)->session_key.encrypted_key_size
> ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) { > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
ecryptfs_printk(KERN_ERR, "Tag 1 packet contains key larger " printk(KERN_WARNING "Tag 1 packet contains key larger "
"than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES"); "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES");
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
ecryptfs_printk(KERN_DEBUG, "Encrypted key size = [%d]\n",
(*new_auth_tok)->session_key.encrypted_key_size);
memcpy((*new_auth_tok)->session_key.encrypted_key, memcpy((*new_auth_tok)->session_key.encrypted_key,
&data[(*packet_size)], (body_size - 0x02 - ECRYPTFS_SIG_SIZE)); &data[(*packet_size)], (body_size - (ECRYPTFS_SIG_SIZE + 2)));
(*packet_size) += (*new_auth_tok)->session_key.encrypted_key_size; (*packet_size) += (*new_auth_tok)->session_key.encrypted_key_size;
(*new_auth_tok)->session_key.flags &= (*new_auth_tok)->session_key.flags &=
~ECRYPTFS_CONTAINS_DECRYPTED_KEY; ~ECRYPTFS_CONTAINS_DECRYPTED_KEY;
(*new_auth_tok)->session_key.flags |= (*new_auth_tok)->session_key.flags |=
ECRYPTFS_CONTAINS_ENCRYPTED_KEY; ECRYPTFS_CONTAINS_ENCRYPTED_KEY;
(*new_auth_tok)->token_type = ECRYPTFS_PRIVATE_KEY; (*new_auth_tok)->token_type = ECRYPTFS_PRIVATE_KEY;
(*new_auth_tok)->flags |= ECRYPTFS_PRIVATE_KEY; (*new_auth_tok)->flags = 0;
/* TODO: Why are we setting this flag here? Don't we want the
* userspace to decrypt the session key? */
(*new_auth_tok)->session_key.flags &= (*new_auth_tok)->session_key.flags &=
~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT); ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
(*new_auth_tok)->session_key.flags &= (*new_auth_tok)->session_key.flags &=
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment