Re: Converting mac80211 CCMP to packet-at-a-time processing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello

i'm not expert with cryptographic modules, but i played sometime with the 
"authenc" module, which is AEAD, and i applied it to the filesystem "ecryptfs".
In the forwarded message i added a brief description of what i do and i hope 
this can be a useful example for you. 
--- Begin Message ---
Hello all

i developed a patch for ecryptfs in order to take advantage of the authenc 
module. This permits to use encryption or encryption with authentication with 
one single tfm.
In order to use authentication i made the following changes:
- Generation of an authentication key (for now only 16-bit keys are 
supported);
- Authentication algorithm tested: "hmac(sha1)" and "digest_null";
- modified the file format, adding 20 bytes after each extent;
- modified the tag 3 packet format in order to specify if authentication on 
data must be checked;
- added parameter "ecryptfs_auth" and "ecryptfs_auth_key_bytes" parameters to 
mount to specify the algorithm and the size of the key will be used to perform 
authentication on data;
- backward compatibility with the current ecryptfs code;
- no integrity verification on the header for now.

Just a remark: the patch must be applied to the latest kernel (2.6.34-rc1) 
because the 2.6.33 has a bug in the authenc module.
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 7cb0a59..d42a59d 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -33,19 +33,68 @@
 #include <linux/crypto.h>
 #include <linux/file.h>
 #include <linux/scatterlist.h>
+#include <crypto/authenc.h>
+#include <linux/rtnetlink.h>
 #include <asm/unaligned.h>
 #include "ecryptfs_kernel.h"
 
 static int
 ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
 			     struct page *dst_page, int dst_offset,
-			     struct page *src_page, int src_offset, int size,
+			     struct page *src_page, int src_offset, int size, unsigned char *auth,
 			     unsigned char *iv);
 static int
 ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
 			     struct page *dst_page, int dst_offset,
-			     struct page *src_page, int src_offset, int size,
+			     struct page *src_page, int src_offset, int size, unsigned char *auth,
 			     unsigned char *iv);
+/*
+ * struct for async completion
+ */
+struct crypto_async_completion {
+	struct completion completion;
+	int err;
+};
+
+/*
+ * callback for handling the completion of an async request
+ */
+void crypto_async_request_cb_complete(struct crypto_async_request *req, int err)
+{
+	struct crypto_async_completion *res = req->data;
+
+	if (err == -EINPROGRESS)
+		return;
+
+	res->err = err;
+	complete(&res->completion);
+}
+
+/*
+ * wait completion of async request
+ */
+int crypto_async_wait_for_completion(struct crypto_async_completion *ahash_result, int cur_ret)
+{
+	int ret = cur_ret;
+
+	switch (ret) {
+		case 0:
+			break;
+		case -EINPROGRESS:
+		case -EBUSY:
+			ret = wait_for_completion_interruptible(&ahash_result->completion);
+			if (!ret && !(ret = ahash_result->err)) {
+				INIT_COMPLETION(ahash_result->completion);
+				break;
+			}
+			/* fall through */
+		default:
+			/* error */
+			break;
+	}
+
+	return ret;
+}
 
 /**
  * ecryptfs_to_hex
@@ -144,21 +193,29 @@ out:
 
 static int ecryptfs_crypto_api_algify_cipher_name(char **algified_name,
 						  char *cipher_name,
-						  char *chaining_modifier)
+						  char *chaining_modifier, char *auth_name)
 {
 	int cipher_name_len = strlen(cipher_name);
 	int chaining_modifier_len = strlen(chaining_modifier);
+	int auth_name_len = auth_name ? strlen(auth_name) : 0;
 	int algified_name_len;
 	int rc;
 
-	algified_name_len = (chaining_modifier_len + cipher_name_len + 3);
+	if(auth_name_len)
+		algified_name_len = (7 + 3 + auth_name_len + chaining_modifier_len + cipher_name_len + 3);
+	else
+		algified_name_len = (chaining_modifier_len + cipher_name_len + 3);  
 	(*algified_name) = kmalloc(algified_name_len, GFP_KERNEL);
 	if (!(*algified_name)) {
 		rc = -ENOMEM;
 		goto out;
 	}
-	snprintf((*algified_name), algified_name_len, "%s(%s)",
-		 chaining_modifier, cipher_name);
+	if(auth_name_len)
+		snprintf((*algified_name), algified_name_len, "authenc(%s,%s(%s))", auth_name,
+			chaining_modifier, cipher_name);
+	else
+		snprintf((*algified_name), algified_name_len, "%s(%s)",
+			chaining_modifier, cipher_name);
 	rc = 0;
 out:
 	return rc;
@@ -242,7 +299,7 @@ void ecryptfs_destroy_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat)
 	struct ecryptfs_key_sig *key_sig, *key_sig_tmp;
 
 	if (crypt_stat->tfm)
-		crypto_free_blkcipher(crypt_stat->tfm);
+		crypto_free_aead(crypt_stat->tfm);
 	if (crypt_stat->hash_tfm)
 		crypto_free_hash(crypt_stat->hash_tfm);
 	list_for_each_entry_safe(key_sig, key_sig_tmp,
@@ -337,11 +394,15 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
 			       struct scatterlist *src_sg, int size,
 			       unsigned char *iv)
 {
-	struct blkcipher_desc desc = {
-		.tfm = crypt_stat->tfm,
-		.info = iv,
-		.flags = CRYPTO_TFM_REQ_MAY_SLEEP
-	};
+	struct aead_request *req = NULL;
+	struct crypto_async_completion result;
+	unsigned char *assoc = NULL;
+	struct scatterlist asg;
+	struct rtattr *rta;
+	unsigned char *p;
+	int keylen = 0;
+	unsigned char *key = NULL;
+	struct crypto_authenc_key_param *param;
 	int rc = 0;
 
 	BUG_ON(!crypt_stat || !crypt_stat->tfm
@@ -352,24 +413,102 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
 		ecryptfs_dump_hex(crypt_stat->key,
 				  crypt_stat->key_size);
 	}
+
 	/* Consider doing this once, when the file is opened */
 	mutex_lock(&crypt_stat->cs_tfm_mutex);
+	
+	init_completion(&result.completion);
+	
+	req = aead_request_alloc(crypt_stat->tfm, GFP_KERNEL);
+	if (!req) {
+		ecryptfs_printk(KERN_ERR, "Failed to allocate request; [%d]\n",
+				rc);
+		mutex_unlock(&crypt_stat->cs_tfm_mutex);
+		rc = -EINVAL;
+		return rc;
+	}
+
+	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
+				  crypto_async_request_cb_complete, &result);
+
 	if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) {
-		rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
-					     crypt_stat->key_size);
+		keylen = crypt_stat->key_size + crypt_stat->auth_key_size + RTA_SPACE(sizeof(*param));
+		key = kzalloc(keylen, GFP_KERNEL);
+		if(!key) {
+			rc = -ENOMEM;
+			ecryptfs_printk(KERN_ERR, "Out of memory\n");
+			mutex_unlock(&crypt_stat->cs_tfm_mutex);
+			goto out;
+		}
+	  
+		p = key;
+		rta = (void *)p;
+		rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM;
+		rta->rta_len = RTA_LENGTH(sizeof(*param));
+		param = RTA_DATA(rta);
+		p += RTA_SPACE(sizeof(*param));
+
+		if(crypt_stat->auth_key_size) {
+			memcpy(p, crypt_stat->key, crypt_stat->auth_key_size);
+			p += crypt_stat->auth_key_size;
+		}
+	
+		param->enckeylen = cpu_to_be32(crypt_stat->key_size);
+		memcpy(p, crypt_stat->key + crypt_stat->auth_key_size, crypt_stat->key_size);
+
+		rc = crypto_aead_setkey(crypt_stat->tfm, key, keylen);		
+		if (rc) {
+			ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n",
+					rc);
+			mutex_unlock(&crypt_stat->cs_tfm_mutex);
+			rc = -EINVAL;
+			goto out;
+		}
 		crypt_stat->flags |= ECRYPTFS_KEY_SET;
 	}
-	if (rc) {
-		ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n",
-				rc);
+
+	if(crypt_stat->authsize) {
+		rc = crypto_aead_setauthsize(crypt_stat->tfm, crypt_stat->authsize);
+		if (rc) {
+			ecryptfs_printk(KERN_ERR, "alg: aead: Failed to set "
+					"authsize to %u\n", crypt_stat->authsize);
+			mutex_unlock(&crypt_stat->cs_tfm_mutex);
+			rc = -EINVAL;
+			goto out;
+		}
+	}
+	
+	ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size);
+
+	assoc = kstrdup(ECRYPTFS_ASSOC_STRING, GFP_KERNEL);
+	if(!assoc) {
+		rc = -ENOMEM;
+		ecryptfs_printk(KERN_ERR, "Out of memory\n");
 		mutex_unlock(&crypt_stat->cs_tfm_mutex);
-		rc = -EINVAL;
 		goto out;
 	}
-	ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size);
-	crypto_blkcipher_encrypt_iv(&desc, dest_sg, src_sg, size);
+		
+	sg_init_one(&asg, assoc, ECRYPTFS_ASSOC_LEN);
+
+	aead_request_set_crypt(req, src_sg, dest_sg, size, iv);
+	aead_request_set_assoc(req, &asg, ECRYPTFS_ASSOC_LEN);
+	
+	rc = crypto_aead_encrypt(req);
+	if(rc == -EBUSY || rc == -EINPROGRESS) {
+		rc = wait_for_completion_interruptible(&result.completion);
+		if (!rc && !(rc = result.err)) {
+			INIT_COMPLETION(result.completion);
+		}
+	}
+
 	mutex_unlock(&crypt_stat->cs_tfm_mutex);
 out:
+	if(assoc)
+		kfree(assoc);
+	if(key)
+		kfree(key);
+
+	aead_request_free(req);
 	return rc;
 }
 
@@ -381,8 +520,8 @@ out:
 static void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num,
 					     struct ecryptfs_crypt_stat *crypt_stat)
 {
-	(*offset) = (crypt_stat->num_header_bytes_at_front
-		     + (crypt_stat->extent_size * extent_num));
+	(*offset) = (crypt_stat->num_header_bytes_at_front + crypt_stat->authsize
+		     + ((crypt_stat->extent_size + crypt_stat->authsize) * extent_num));
 }
 
 /**
@@ -400,7 +539,7 @@ static void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num,
  */
 static int ecryptfs_encrypt_extent(struct page *enc_extent_page,
 				   struct ecryptfs_crypt_stat *crypt_stat,
-				   struct page *page,
+				   struct page *page, unsigned char *auth,
 				   unsigned long extent_offset)
 {
 	loff_t extent_base;
@@ -432,7 +571,7 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page,
 	rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0,
 					  page, (extent_offset
 						 * crypt_stat->extent_size),
-					  crypt_stat->extent_size, extent_iv);
+					  crypt_stat->extent_size, auth, extent_iv);
 	if (rc < 0) {
 		printk(KERN_ERR "%s: Error attempting to encrypt page with "
 		       "page->index = [%ld], extent_offset = [%ld]; "
@@ -448,6 +587,8 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page,
 		ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
 				"encryption:\n");
 		ecryptfs_dump_hex((char *)(page_address(enc_extent_page)), 8);
+		ecryptfs_printk(KERN_DEBUG, "Auth: \n");
+		ecryptfs_dump_hex(auth, crypt_stat->authsize);
 	}
 out:
 	return rc;
@@ -477,7 +618,8 @@ int ecryptfs_encrypt_page(struct page *page)
 	struct page *enc_extent_page = NULL;
 	loff_t extent_offset;
 	int rc = 0;
-
+	unsigned char *auth = NULL;
+	
 	ecryptfs_inode = page->mapping->host;
 	crypt_stat =
 		&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
@@ -490,34 +632,57 @@ int ecryptfs_encrypt_page(struct page *page)
 		goto out;
 	}
 	enc_extent_virt = kmap(enc_extent_page);
+	if(crypt_stat->authsize) {
+		auth = kzalloc(crypt_stat->authsize, GFP_KERNEL);
+		if(!auth) {
+			rc = -ENOMEM;
+			ecryptfs_printk(KERN_ERR, "Error allocating memory for "
+					"auth\n");
+			goto out;
+		}
+	}
 	for (extent_offset = 0;
 	     extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size);
 	     extent_offset++) {
 		loff_t offset;
 
-		rc = ecryptfs_encrypt_extent(enc_extent_page, crypt_stat, page,
+		rc = ecryptfs_encrypt_extent(enc_extent_page, crypt_stat, page, auth,
 					     extent_offset);
 		if (rc) {
 			printk(KERN_ERR "%s: Error encrypting extent; "
 			       "rc = [%d]\n", __func__, rc);
 			goto out;
 		}
+		
 		ecryptfs_lower_offset_for_extent(
 			&offset, ((((loff_t)page->index)
 				   * (PAGE_CACHE_SIZE
 				      / crypt_stat->extent_size))
 				  + extent_offset), crypt_stat);
+
 		rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt,
-					  offset, crypt_stat->extent_size);
+					  offset, crypt_stat->extent_size);  
 		if (rc < 0) {
 			ecryptfs_printk(KERN_ERR, "Error attempting "
 					"to write lower page; rc = [%d]"
 					"\n", rc);
 			goto out;
 		}
+		if(crypt_stat->authsize) {
+			rc = ecryptfs_write_lower(ecryptfs_inode, auth,
+						offset + crypt_stat->extent_size, crypt_stat->authsize);  
+			if (rc < 0) {
+				ecryptfs_printk(KERN_ERR, "Error attempting "
+						"to write auth; rc = [%d]"
+						"\n", rc);
+				goto out;
+			}
+		}
 	}
 	rc = 0;
 out:
+	if (auth)
+		kfree(auth);
 	if (enc_extent_page) {
 		kunmap(enc_extent_page);
 		__free_page(enc_extent_page);
@@ -527,7 +692,7 @@ out:
 
 static int ecryptfs_decrypt_extent(struct page *page,
 				   struct ecryptfs_crypt_stat *crypt_stat,
-				   struct page *enc_extent_page,
+				   struct page *enc_extent_page, unsigned char *auth,
 				   unsigned long extent_offset)
 {
 	loff_t extent_base;
@@ -555,12 +720,14 @@ static int ecryptfs_decrypt_extent(struct page *page,
 				  (page_address(enc_extent_page)
 				   + (extent_offset * crypt_stat->extent_size)),
 				  8);
+		ecryptfs_printk(KERN_DEBUG, "Auth: \n");
+		ecryptfs_dump_hex(auth, crypt_stat->authsize);
 	}
 	rc = ecryptfs_decrypt_page_offset(crypt_stat, page,
 					  (extent_offset
 					   * crypt_stat->extent_size),
 					  enc_extent_page, 0,
-					  crypt_stat->extent_size, extent_iv);
+					  crypt_stat->extent_size, auth, extent_iv);
 	if (rc < 0) {
 		printk(KERN_ERR "%s: Error attempting to decrypt to page with "
 		       "page->index = [%ld], extent_offset = [%ld]; "
@@ -607,6 +774,7 @@ int ecryptfs_decrypt_page(struct page *page)
 	struct page *enc_extent_page = NULL;
 	unsigned long extent_offset;
 	int rc = 0;
+	unsigned char *auth = NULL;
 
 	ecryptfs_inode = page->mapping->host;
 	crypt_stat =
@@ -619,6 +787,15 @@ int ecryptfs_decrypt_page(struct page *page)
 				"encrypted extent\n");
 		goto out;
 	}
+	if(crypt_stat->authsize) {
+		auth = kzalloc(crypt_stat->authsize, GFP_KERNEL);
+		if(!auth) {
+			rc = -ENOMEM;
+			ecryptfs_printk(KERN_ERR, "Error allocating memory for "
+					"auth\n");
+			goto out;
+		}
+	}
 	enc_extent_virt = kmap(enc_extent_page);
 	for (extent_offset = 0;
 	     extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size);
@@ -629,6 +806,7 @@ int ecryptfs_decrypt_page(struct page *page)
 			&offset, ((page->index * (PAGE_CACHE_SIZE
 						  / crypt_stat->extent_size))
 				  + extent_offset), crypt_stat);
+
 		rc = ecryptfs_read_lower(enc_extent_virt, offset,
 					 crypt_stat->extent_size,
 					 ecryptfs_inode);
@@ -638,7 +816,22 @@ int ecryptfs_decrypt_page(struct page *page)
 					"\n", rc);
 			goto out;
 		}
-		rc = ecryptfs_decrypt_extent(page, crypt_stat, enc_extent_page,
+		if(!rc)		/* No need to decrypt extent if there's nothing to read from the lower file */
+			break;
+
+		if(crypt_stat->authsize) {
+			rc = ecryptfs_read_lower(auth, offset +
+						crypt_stat->extent_size, crypt_stat->authsize,
+						ecryptfs_inode);
+			if (rc < 0) {
+				ecryptfs_printk(KERN_ERR, "Error attempting "
+						"to read lower page auth; rc = [%d]"
+						"\n", rc);
+				goto out;
+			}
+		}
+		
+		rc = ecryptfs_decrypt_extent(page, crypt_stat, enc_extent_page, auth,
 					     extent_offset);
 		if (rc) {
 			printk(KERN_ERR "%s: Error encrypting extent; "
@@ -647,6 +840,8 @@ int ecryptfs_decrypt_page(struct page *page)
 		}
 	}
 out:
+	if (auth)
+		kfree(auth);
 	if (enc_extent_page) {
 		kunmap(enc_extent_page);
 		__free_page(enc_extent_page);
@@ -669,27 +864,101 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
 			       struct scatterlist *src_sg, int size,
 			       unsigned char *iv)
 {
-	struct blkcipher_desc desc = {
-		.tfm = crypt_stat->tfm,
-		.info = iv,
-		.flags = CRYPTO_TFM_REQ_MAY_SLEEP
-	};
+	struct aead_request *req = NULL;
+	struct crypto_async_completion result;
+	unsigned char *assoc = NULL;
+	struct scatterlist asg;
+	struct rtattr *rta;
+	unsigned char *p;
+	int keylen = 0;
+	unsigned char *key = NULL;
+	struct crypto_authenc_key_param *param;
 	int rc = 0;
 
 	/* Consider doing this once, when the file is opened */
 	mutex_lock(&crypt_stat->cs_tfm_mutex);
-	rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
-				     crypt_stat->key_size);
+
+	init_completion(&result.completion);
+	
+	req = aead_request_alloc(crypt_stat->tfm, GFP_KERNEL);
+	if (!req) {
+		rc = PTR_ERR(req);
+		ecryptfs_printk(KERN_ERR, "Failed to allocate request; [%d]\n", rc);
+		mutex_unlock(&crypt_stat->cs_tfm_mutex);
+		return rc;
+	}
+	
+	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
+				  crypto_async_request_cb_complete, &result);
+
+	keylen = crypt_stat->key_size + crypt_stat->auth_key_size + RTA_SPACE(sizeof(*param));
+
+	key = kzalloc(keylen, GFP_KERNEL);
+	if(!key) {
+		rc = -ENOMEM;
+		ecryptfs_printk(KERN_ERR, "Out of memory\n");
+		mutex_unlock(&crypt_stat->cs_tfm_mutex);
+		goto out;
+	}
+  
+	p = key;
+	rta = (void *)p;
+	rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM;
+	rta->rta_len = RTA_LENGTH(sizeof(*param));
+	param = RTA_DATA(rta);
+	p += RTA_SPACE(sizeof(*param));
+
+	if(crypt_stat->auth_key_size) {
+		memcpy(p, crypt_stat->key, crypt_stat->auth_key_size);
+		p += crypt_stat->auth_key_size;
+	}
+	
+	param->enckeylen = cpu_to_be32(crypt_stat->key_size);
+	memcpy(p, crypt_stat->key + crypt_stat->auth_key_size, crypt_stat->key_size);
+
+	rc = crypto_aead_setkey(crypt_stat->tfm, key, keylen);
 	if (rc) {
 		ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n",
 				rc);
 		mutex_unlock(&crypt_stat->cs_tfm_mutex);
-		rc = -EINVAL;
 		goto out;
 	}
+
+	if(crypt_stat->authsize) {
+		rc = crypto_aead_setauthsize(crypt_stat->tfm, crypt_stat->authsize);
+		if (rc) {
+			ecryptfs_printk(KERN_ERR, "alg: aead: Failed to set "
+					"authsize to %u\n", crypt_stat->authsize);
+			mutex_unlock(&crypt_stat->cs_tfm_mutex);
+			goto out;
+		}
+	}
+	
 	ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size);
-	rc = crypto_blkcipher_decrypt_iv(&desc, dest_sg, src_sg, size);
+
+	assoc = kstrdup(ECRYPTFS_ASSOC_STRING, GFP_KERNEL);
+	if(!assoc) {
+		rc = -ENOMEM;
+		ecryptfs_printk(KERN_ERR, "Out of memory\n");
+		mutex_unlock(&crypt_stat->cs_tfm_mutex);
+		goto out;
+	}
+		
+	sg_init_one(&asg, assoc, ECRYPTFS_ASSOC_LEN);
+
+	aead_request_set_crypt(req, src_sg, dest_sg, size + crypt_stat->authsize, iv);
+	aead_request_set_assoc(req, &asg, ECRYPTFS_ASSOC_LEN);
+
+	rc = crypto_aead_decrypt(req);
+	if(rc == -EBUSY || rc == -EINPROGRESS) {
+		rc = wait_for_completion_interruptible(&result.completion);
+		if (!rc && !(rc = result.err)) {
+			INIT_COMPLETION(result.completion);
+		}
+	}
+
 	mutex_unlock(&crypt_stat->cs_tfm_mutex);
+	
 	if (rc) {
 		ecryptfs_printk(KERN_ERR, "Error decrypting; rc = [%d]\n",
 				rc);
@@ -697,6 +966,12 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
 	}
 	rc = size;
 out:
+	if(assoc)
+		kfree(assoc);
+	if(key)
+		kfree(key);
+
+	aead_request_free(req);
 	return rc;
 }
 
@@ -715,17 +990,22 @@ out:
 static int
 ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
 			     struct page *dst_page, int dst_offset,
-			     struct page *src_page, int src_offset, int size,
+			     struct page *src_page, int src_offset, int size, unsigned char *auth,
 			     unsigned char *iv)
 {
-	struct scatterlist src_sg, dst_sg;
-
-	sg_init_table(&src_sg, 1);
-	sg_init_table(&dst_sg, 1);
-
-	sg_set_page(&src_sg, src_page, size, src_offset);
-	sg_set_page(&dst_sg, dst_page, size, dst_offset);
-	return encrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv);
+	struct scatterlist src_sg[2], dst_sg[2];
+
+	sg_init_table(src_sg, 2);
+	sg_init_table(dst_sg, 2);
+
+	sg_set_page(&src_sg[0], src_page, size, src_offset);
+	if(auth)
+		sg_set_buf(&src_sg[1], auth, crypt_stat->authsize);
+	sg_set_page(&dst_sg[0], dst_page, size, dst_offset);
+	if(auth)
+		sg_set_buf(&dst_sg[1], auth, crypt_stat->authsize);
+	
+	return encrypt_scatterlist(crypt_stat, dst_sg, src_sg, size, iv);
 }
 
 /**
@@ -743,18 +1023,22 @@ ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
 static int
 ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
 			     struct page *dst_page, int dst_offset,
-			     struct page *src_page, int src_offset, int size,
+			     struct page *src_page, int src_offset, int size, unsigned char *auth,
 			     unsigned char *iv)
 {
-	struct scatterlist src_sg, dst_sg;
-
-	sg_init_table(&src_sg, 1);
-	sg_set_page(&src_sg, src_page, size, src_offset);
-
-	sg_init_table(&dst_sg, 1);
-	sg_set_page(&dst_sg, dst_page, size, dst_offset);
-
-	return decrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv);
+	struct scatterlist src_sg[2], dst_sg[2];
+
+	sg_init_table(src_sg, 2);
+	sg_set_page(&src_sg[0], src_page, size, src_offset);
+	if(auth)
+		sg_set_buf(&src_sg[1], auth, crypt_stat->authsize);
+	
+	sg_init_table(dst_sg, 2);
+	sg_set_page(&dst_sg[0], dst_page, size, dst_offset);
+	if(auth)
+		sg_set_buf(&dst_sg[1], auth, crypt_stat->authsize);
+
+	return decrypt_scatterlist(crypt_stat, dst_sg, src_sg, size, iv);
 }
 
 #define ECRYPTFS_MAX_SCATTERLIST_LEN 4
@@ -772,7 +1056,7 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat)
 {
 	char *full_alg_name;
 	int rc = -EINVAL;
-
+	
 	if (!crypt_stat->cipher) {
 		ecryptfs_printk(KERN_ERR, "No cipher specified\n");
 		goto out;
@@ -782,17 +1066,28 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat)
 			"key_size_bits = [%d]\n",
 			crypt_stat->cipher, (int)strlen(crypt_stat->cipher),
 			crypt_stat->key_size << 3);
+
+	ecryptfs_printk(KERN_DEBUG,			
+			"Initializing auth [%s]; strlen = [%d]; "
+			"key_size_bits = [%d]\n",
+			crypt_stat->auth, (int)strlen(crypt_stat->auth),
+			crypt_stat->auth_key_size << 3
+			);
 	if (crypt_stat->tfm) {
 		rc = 0;
 		goto out;
 	}
 	mutex_lock(&crypt_stat->cs_tfm_mutex);
-	rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name,
-						    crypt_stat->cipher, "cbc");
+	if(strcmp(crypt_stat->cipher, "cipher_null") == 0)
+		rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name,
+								crypt_stat->cipher, "ecb", crypt_stat->auth);
+	else
+		rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name,
+								crypt_stat->cipher, "cbc", crypt_stat->auth);
 	if (rc)
 		goto out_unlock;
-	crypt_stat->tfm = crypto_alloc_blkcipher(full_alg_name, 0,
-						 CRYPTO_ALG_ASYNC);
+	crypt_stat->tfm = crypto_alloc_aead(full_alg_name, 0, 0);
+ 
 	kfree(full_alg_name);
 	if (IS_ERR(crypt_stat->tfm)) {
 		rc = PTR_ERR(crypt_stat->tfm);
@@ -802,7 +1097,10 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat)
 				crypt_stat->cipher);
 		goto out_unlock;
 	}
-	crypto_blkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+	crypto_aead_clear_flags(crypt_stat->tfm, ~0);
+	crypto_aead_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+	
+	crypt_stat->authsize = crypto_aead_authsize(crypt_stat->tfm);
 	rc = 0;
 out_unlock:
 	mutex_unlock(&crypt_stat->cs_tfm_mutex);
@@ -881,12 +1179,15 @@ out:
 
 static void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat)
 {
-	get_random_bytes(crypt_stat->key, crypt_stat->key_size);
+	get_random_bytes(crypt_stat->key, crypt_stat->auth_key_size + crypt_stat->key_size);
 	crypt_stat->flags |= ECRYPTFS_KEY_VALID;
 	ecryptfs_compute_root_iv(crypt_stat);
 	if (unlikely(ecryptfs_verbosity > 0)) {
-		ecryptfs_printk(KERN_DEBUG, "Generated new session key:\n");
+		ecryptfs_printk(KERN_DEBUG, "Generated new auth key:\n");
 		ecryptfs_dump_hex(crypt_stat->key,
+				  crypt_stat->auth_key_size);	  
+		ecryptfs_printk(KERN_DEBUG, "Generated new session key:\n");
+		ecryptfs_dump_hex(crypt_stat->key + crypt_stat->auth_key_size,
 				  crypt_stat->key_size);
 	}
 }
@@ -994,6 +1295,7 @@ int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry)
 	    &ecryptfs_superblock_to_private(
 		    ecryptfs_dentry->d_sb)->mount_crypt_stat;
 	int cipher_name_len;
+	int auth_name_len;
 	int rc = 0;
 
 	ecryptfs_set_default_crypt_stat_vals(crypt_stat, mount_crypt_stat);
@@ -1013,8 +1315,19 @@ int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry)
 	       mount_crypt_stat->global_default_cipher_name,
 	       cipher_name_len);
 	crypt_stat->cipher[cipher_name_len] = '\0';
+	memcpy(crypt_stat->cipher,
+	       mount_crypt_stat->global_default_cipher_name,
+	       cipher_name_len);
 	crypt_stat->key_size =
 		mount_crypt_stat->global_default_cipher_key_size;
+	auth_name_len =
+		strlen(mount_crypt_stat->global_default_auth_name);
+	memcpy(crypt_stat->auth,
+	       mount_crypt_stat->global_default_auth_name,
+	       auth_name_len);
+	crypt_stat->auth[auth_name_len] = '\0';
+	crypt_stat->auth_key_size =
+		mount_crypt_stat->global_default_auth_key_size;
 	ecryptfs_generate_new_key(crypt_stat);
 	rc = ecryptfs_init_crypt_ctx(crypt_stat);
 	if (rc)
@@ -1141,7 +1454,8 @@ ecryptfs_cipher_code_str_map[] = {
 	{"twofish", RFC2440_CIPHER_TWOFISH},
 	{"cast6", RFC2440_CIPHER_CAST_6},
 	{"aes", RFC2440_CIPHER_AES_192},
-	{"aes", RFC2440_CIPHER_AES_256}
+	{"aes", RFC2440_CIPHER_AES_256},
+	{"cipher_null", ECRYPTFS_CRYPTO_NULL_CODE}
 };
 
 /**
@@ -1314,9 +1628,14 @@ ecryptfs_write_metadata_to_contents(struct dentry *ecryptfs_dentry,
 				    char *virt, size_t virt_len)
 {
 	int rc;
-
+	char auth[ECRYPTFS_AUTHSIZE];
+	
 	rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, virt,
 				  0, virt_len);
+
+  	rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, auth,
+					  virt_len, ECRYPTFS_AUTHSIZE);
+  
 	if (rc < 0)
 		printk(KERN_ERR "%s: Error attempting to write header "
 		       "information to lower file; rc = [%d]\n", __func__, rc);
@@ -1582,6 +1901,8 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
 {
 	int rc = 0;
 	char *page_virt = NULL;
+	char auth[ECRYPTFS_AUTHSIZE];
+	
 	struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode;
 	struct ecryptfs_crypt_stat *crypt_stat =
 	    &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
@@ -1601,6 +1922,10 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
 	}
 	rc = ecryptfs_read_lower(page_virt, 0, crypt_stat->extent_size,
 				 ecryptfs_inode);
+
+	rc = ecryptfs_read_lower(auth, crypt_stat->extent_size, ECRYPTFS_AUTHSIZE,
+				 ecryptfs_inode);
+ 
 	if (rc >= 0)
 		rc = ecryptfs_read_headers_virt(page_virt, crypt_stat,
 						ecryptfs_dentry,
@@ -1759,7 +2084,7 @@ ecryptfs_process_key_cipher(struct crypto_blkcipher **key_tfm,
 		goto out;
 	}
 	rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, cipher_name,
-						    "ecb");
+						    "ecb", NULL);
 	if (rc)
 		goto out;
 	*key_tfm = crypto_alloc_blkcipher(full_alg_name, 0, CRYPTO_ALG_ASYNC);
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 542f625..73b2ab3 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -96,6 +96,9 @@
 
 #define RFC2440_CIPHER_RSA 0x01
 
+#define ECRYPTFS_HMAC_AUTH_MASK 0x10
+#define ECRYPTFS_CRYPTO_NULL_CODE 0x0c
+
 /**
  * For convenience, we may need to pass around the encrypted session
  * key between kernel and userspace because the authentication token
@@ -194,6 +197,7 @@ ecryptfs_get_key_payload_data(struct key *key)
 #define ECRYPTFS_SUPER_MAGIC 0xf15f
 #define ECRYPTFS_MAX_KEYSET_SIZE 1024
 #define ECRYPTFS_MAX_CIPHER_NAME_SIZE 32
+#define ECRYPTFS_MAX_AUTH_NAME_SIZE 32
 #define ECRYPTFS_MAX_NUM_ENC_KEYS 64
 #define ECRYPTFS_MAX_IV_BYTES 16	/* 128 bits */
 #define ECRYPTFS_SALT_BYTES 2
@@ -203,6 +207,8 @@ ecryptfs_get_key_payload_data(struct key *key)
 #define ECRYPTFS_DEFAULT_CIPHER "aes"
 #define ECRYPTFS_DEFAULT_KEY_BYTES 16
 #define ECRYPTFS_DEFAULT_HASH "md5"
+#define ECRYPTFS_DEFAULT_AUTH "digest_null"
+#define ECRYPTFS_DEFAULT_AUTH_KEY_BYTES 0
 #define ECRYPTFS_TAG_70_DIGEST ECRYPTFS_DEFAULT_HASH
 #define ECRYPTFS_TAG_1_PACKET_TYPE 0x01
 #define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C
@@ -230,6 +236,14 @@ ecryptfs_get_key_payload_data(struct key *key)
 #define ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FNEK_ENCRYPTED."
 #define ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE 24
 #define ECRYPTFS_ENCRYPTED_DENTRY_NAME_LEN (18 + 1 + 4 + 1 + 32)
+#define ECRYPTFS_ASSOC_STRING "\x49\x5c\x50\x1f\x1d\x94\xcc\x81 \
+			      \xba\xb7\xb6\x03\xaf\xa5\xc1\xa1  \
+			      \xd8\x5c\x42\x68\xe0\x6c\xda\x89  \
+			      \x05\xac\x56\xac\x1b\x2a\xd3\x86"
+#define ECRYPTFS_ASSOC_LEN 32
+#define ECRYPTFS_AUTHSIZE 20
+#define ECRYPTFS_FIXED_AUTH_KEY_SIZE 16
+#define ECRYPTFS_FIXED_AUTH_NAME "hmac(sha1)"
 
 struct ecryptfs_key_sig {
 	struct list_head crypt_stat_list;
@@ -276,13 +290,16 @@ struct ecryptfs_crypt_stat {
 	size_t num_header_bytes_at_front;
 	size_t extent_size; /* Data extent size; default is 4096 */
 	size_t key_size;
+	size_t auth_key_size;
+	size_t authsize;
 	size_t extent_shift;
 	unsigned int extent_mask;
 	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
-	struct crypto_blkcipher *tfm;
+	struct crypto_aead *tfm;
 	struct crypto_hash *hash_tfm; /* Crypto context for generating
 				       * the initialization vectors */
 	unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE];
+	unsigned char auth[ECRYPTFS_MAX_AUTH_NAME_SIZE];
 	unsigned char key[ECRYPTFS_MAX_KEY_BYTES];
 	unsigned char root_iv[ECRYPTFS_MAX_IV_BYTES];
 	struct list_head keysig_list;
@@ -381,11 +398,14 @@ struct ecryptfs_mount_crypt_stat {
 	struct mutex global_auth_tok_list_mutex;
 	size_t num_global_auth_toks;
 	size_t global_default_cipher_key_size;
+	size_t global_default_auth_key_size;
 	size_t global_default_fn_cipher_key_bytes;
 	unsigned char global_default_cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE
 						 + 1];
 	unsigned char global_default_fn_cipher_name[
 		ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1];
+	unsigned char global_default_auth_name[ECRYPTFS_MAX_AUTH_NAME_SIZE
+						 + 1];
 	char global_default_fnek_sig[ECRYPTFS_SIG_SIZE_HEX + 1];
 };
 
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 678172b..8ba50d8 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -296,6 +296,7 @@ static int ecryptfs_fasync(int fd, struct file *file, int flag)
 static int ecryptfs_ioctl(struct inode *inode, struct file *file,
 			  unsigned int cmd, unsigned long arg);
 
+
 const struct file_operations ecryptfs_dir_fops = {
 	.readdir = ecryptfs_readdir,
 	.ioctl = ecryptfs_ioctl,
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index a0a7847..adc0835 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -1328,6 +1328,16 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
 		rc = -EINVAL;
 		goto out_free;
 	}
+	if((u16)data[(*packet_size)] & ECRYPTFS_HMAC_AUTH_MASK) {
+		crypt_stat->auth_key_size = ECRYPTFS_FIXED_AUTH_KEY_SIZE;
+		memcpy(crypt_stat->auth, ECRYPTFS_FIXED_AUTH_NAME, strlen(ECRYPTFS_FIXED_AUTH_NAME));
+		crypt_stat->auth[strlen(ECRYPTFS_FIXED_AUTH_NAME)]='\0';
+		data[(*packet_size)] &= ~ECRYPTFS_HMAC_AUTH_MASK;
+	} else {
+		memcpy(crypt_stat->auth, ECRYPTFS_DEFAULT_AUTH, strlen(ECRYPTFS_DEFAULT_AUTH));
+		crypt_stat->auth[strlen(ECRYPTFS_DEFAULT_AUTH)]='\0';	  
+	}
+	  
 	rc = ecryptfs_cipher_code_to_string(crypt_stat->cipher,
 					    (u16)data[(*packet_size)]);
 	if (rc)
@@ -1340,7 +1350,7 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
 		break;
 	default:
 		crypt_stat->key_size =
-			(*new_auth_tok)->session_key.encrypted_key_size;
+			(*new_auth_tok)->session_key.encrypted_key_size - crypt_stat->auth_key_size;
 	}
 	rc = ecryptfs_init_crypt_ctx(crypt_stat);
 	if (rc)
@@ -2118,13 +2128,13 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,
 			mount_crypt_stat->global_default_cipher_key_size;
 	if (auth_tok->session_key.encrypted_key_size == 0)
 		auth_tok->session_key.encrypted_key_size =
-			crypt_stat->key_size;
+			crypt_stat->auth_key_size + crypt_stat->key_size;
 	if (crypt_stat->key_size == 24
 	    && strcmp("aes", crypt_stat->cipher) == 0) {
 		memset((crypt_stat->key + 24), 0, 8);
-		auth_tok->session_key.encrypted_key_size = 32;
+		auth_tok->session_key.encrypted_key_size = crypt_stat->auth_key_size + 32;
 	} else
-		auth_tok->session_key.encrypted_key_size = crypt_stat->key_size;
+		auth_tok->session_key.encrypted_key_size = crypt_stat->auth_key_size + crypt_stat->key_size;
 	key_rec->enc_key_size =
 		auth_tok->session_key.encrypted_key_size;
 	encrypted_session_key_valid = 0;
@@ -2149,7 +2159,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,
 				session_key_encryption_key_bytes);
 		memcpy(session_key_encryption_key,
 		       auth_tok->token.password.session_key_encryption_key,
-		       crypt_stat->key_size);
+		         crypt_stat->key_size);
 		ecryptfs_printk(KERN_DEBUG,
 				"Cached session key " "encryption key: \n");
 		if (ecryptfs_verbosity > 0)
@@ -2217,7 +2227,7 @@ encrypted_session_key_set:
 			   + 1                       /* Hash identifier */
 			   + ECRYPTFS_SALT_SIZE      /* Salt */
 			   + 1                       /* Hash iterations */
-			   + key_rec->enc_key_size); /* Encrypted key size */
+			   + key_rec->enc_key_size); /* Encrypted key size (cipher) */
 	if (max_packet_size > (*remaining_bytes)) {
 		printk(KERN_ERR "Packet too large; need up to [%td] bytes, but "
 		       "there are only [%td] available\n", max_packet_size,
@@ -2241,13 +2251,16 @@ encrypted_session_key_set:
 	/* TODO: Break from RFC2440 so that arbitrary ciphers can be
 	 * specified with strings */
 	cipher_code = ecryptfs_code_for_cipher_string(crypt_stat->cipher,
-						      crypt_stat->key_size);
+						      crypt_stat->key_size);	
 	if (cipher_code == 0) {
 		ecryptfs_printk(KERN_WARNING, "Unable to generate code for "
 				"cipher [%s]\n", crypt_stat->cipher);
 		rc = -EINVAL;
 		goto out;
 	}
+	/* WARNING: the following code is not standard */
+	if(crypt_stat->auth_key_size)
+		cipher_code |= ECRYPTFS_HMAC_AUTH_MASK;
 	dest[(*packet_size)++] = cipher_code;
 	dest[(*packet_size)++] = 0x03;	/* S2K */
 	dest[(*packet_size)++] = 0x01;	/* MD5 (TODO: parameterize) */
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index ea2f921..51dc3cd 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -207,7 +207,9 @@ enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig,
        ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata,
        ecryptfs_opt_encrypted_view, ecryptfs_opt_fnek_sig,
        ecryptfs_opt_fn_cipher, ecryptfs_opt_fn_cipher_key_bytes,
-       ecryptfs_opt_unlink_sigs, ecryptfs_opt_err };
+       ecryptfs_opt_unlink_sigs, ecryptfs_opt_auth,
+       ecryptfs_opt_auth_key_bytes,ecryptfs_opt_err
+       };
 
 static const match_table_t tokens = {
 	{ecryptfs_opt_sig, "sig=%s"},
@@ -222,7 +224,9 @@ static const match_table_t tokens = {
 	{ecryptfs_opt_fn_cipher, "ecryptfs_fn_cipher=%s"},
 	{ecryptfs_opt_fn_cipher_key_bytes, "ecryptfs_fn_key_bytes=%u"},
 	{ecryptfs_opt_unlink_sigs, "ecryptfs_unlink_sigs"},
-	{ecryptfs_opt_err, NULL}
+	{ecryptfs_opt_auth, "ecryptfs_auth=%s"},
+	{ecryptfs_opt_auth_key_bytes, "ecryptfs_auth_key_bytes=%u"},	
+	{ecryptfs_opt_err, NULL},
 };
 
 static int ecryptfs_init_global_auth_toks(
@@ -304,7 +308,13 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
 	char *fnek_src;
 	char *cipher_key_bytes_src;
 	char *fn_cipher_key_bytes_src;
-
+	char *auth_key_bytes_src;
+	char *auth_name_dst;
+	char *auth_name_src;
+	int auth_key_bytes;
+	int auth_name_set = 0;
+	int auth_key_bytes_set = 0;
+	
 	if (!options) {
 		rc = -EINVAL;
 		goto out;
@@ -405,6 +415,31 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
 		case ecryptfs_opt_unlink_sigs:
 			mount_crypt_stat->flags |= ECRYPTFS_UNLINK_SIGS;
 			break;
+		case ecryptfs_opt_auth:
+			auth_name_src = args[0].from;
+			auth_name_dst =
+				mount_crypt_stat->
+				global_default_auth_name;
+			strncpy(auth_name_dst, auth_name_src,
+				ECRYPTFS_MAX_AUTH_NAME_SIZE);
+			auth_name_dst[ECRYPTFS_MAX_AUTH_NAME_SIZE] = '\0';
+			auth_name_set = 1;
+			break;
+		case ecryptfs_opt_auth_key_bytes:
+			auth_key_bytes_src = args[0].from;
+			auth_key_bytes =
+				(int)simple_strtol(auth_key_bytes_src,
+						   &auth_key_bytes_src, 0);
+			if(auth_key_bytes != ECRYPTFS_FIXED_AUTH_KEY_SIZE) {
+				ecryptfs_printk(KERN_ERR, "Only %d-bit long hmac keys are"
+							  "currently supported; auth_key_size"
+							  "will be set to %d\n", ECRYPTFS_FIXED_AUTH_KEY_SIZE, 
+							  ECRYPTFS_FIXED_AUTH_KEY_SIZE);
+			}
+			mount_crypt_stat->global_default_auth_key_size =
+				auth_key_bytes;
+			auth_key_bytes_set = 1;
+			break;
 		case ecryptfs_opt_err:
 		default:
 			printk(KERN_WARNING
@@ -426,12 +461,25 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
 		strcpy(mount_crypt_stat->global_default_cipher_name,
 		       ECRYPTFS_DEFAULT_CIPHER);
 	}
+	if (!auth_name_set) {
+		int auth_name_len = strlen(ECRYPTFS_DEFAULT_AUTH);
+		
+		BUG_ON(auth_name_len >= ECRYPTFS_MAX_AUTH_NAME_SIZE);
+		strcpy(mount_crypt_stat->global_default_auth_name,
+		       ECRYPTFS_DEFAULT_AUTH);  
+	}
 	if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)
 	    && !fn_cipher_name_set)
 		strcpy(mount_crypt_stat->global_default_fn_cipher_name,
 		       mount_crypt_stat->global_default_cipher_name);
 	if (!cipher_key_bytes_set)
 		mount_crypt_stat->global_default_cipher_key_size = 0;
+	if (!auth_key_bytes_set) {
+		if(auth_name_set && strcmp(mount_crypt_stat-> global_default_auth_name, ECRYPTFS_DEFAULT_AUTH)) 
+			mount_crypt_stat->global_default_auth_key_size = ECRYPTFS_FIXED_AUTH_KEY_SIZE;
+		else
+			mount_crypt_stat->global_default_auth_key_size = 0;
+	}
 	if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)
 	    && !fn_cipher_key_bytes_set)
 		mount_crypt_stat->global_default_fn_cipher_key_bytes =
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index df4ce99..48306fa 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -521,6 +521,7 @@ static int ecryptfs_write_end(struct file *file,
 		ecryptfs_printk(KERN_DEBUG, "Expanded file size to "
 				"[0x%.16x]\n", i_size_read(ecryptfs_inode));
 	}
+
 	rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode);
 	if (rc)
 		printk(KERN_ERR "Error writing inode size to metadata; "

Attachment: smime.p7s
Description: S/MIME cryptographic signature


--- End Message ---

Attachment: smime.p7s
Description: S/MIME cryptographic signature


[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]

  Powered by Linux