* Converting mac80211 CCMP to packet-at-a-time processing
@ 2010-03-12 5:29 Pavel Roskin
0 siblings, 0 replies; 6+ messages in thread
From: Pavel Roskin @ 2010-03-12 5:29 UTC (permalink / raw)
To: linux-crypto
Hello!
The CCMP encryption in mac80211 uses crypto API to encrypt 16 bytes at a
time. I believe this is not the best approach if hardware acceleration
is used. The ixp4xx_crypto driver doesn't even provide the "aes"
ciphers. It only provides block ciphers, such as "cbc(des)".
It would be much better if mac80211 could encrypt the whole packet at a
time. Actually, that's what the WEP code is doing.
I realize that CCMP is a more sophisticated cipher, so maybe it's not so
easy. "ccm(aes)" is probably the closest thing to what is needed, but
it's not even a block cipher, it's an AEAD.
Unfortunately, I don't see any examples of AEAD use in the kernel other
than the crypto testing module. And I'm not even sure if "ccm(aes)" is
the right choice for CCMP.
I'll appreciate if somebody with a cryptographic background could have a
look at net/mac80211/aes_ccm.c and suggest whether it could be converted
to packet-at-a-time processing.
--
Regards,
Pavel Roskin
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Converting mac80211 CCMP to packet-at-a-time processing
@ 2010-03-12 10:49 Roberto Sassu
2010-03-13 3:42 ` Pavel Roskin
0 siblings, 1 reply; 6+ messages in thread
From: Roberto Sassu @ 2010-03-12 10:49 UTC (permalink / raw)
To: Pavel Roskin, linux-crypto
[-- Attachment #1.1: Type: text/plain, Size: 285 bytes --]
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.
[-- Attachment #1.2: Roberto Sassu <roberto.sassu@polito.it>: Authenc support for ecryptfs --]
[-- Type: message/rfc822, Size: 42368 bytes --]
[-- Attachment #1.2.1.1.1: Type: Text/Plain, Size: 993 bytes --]
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.
[-- Attachment #1.2.1.1.2: ecryptfs_authenc_patch.diff --]
[-- Type: text/x-patch, Size: 37410 bytes --]
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 #1.2.1.2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 2153 bytes --]
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 2153 bytes --]
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: Converting mac80211 CCMP to packet-at-a-time processing
2010-03-12 10:49 Roberto Sassu
@ 2010-03-13 3:42 ` Pavel Roskin
2010-03-13 12:28 ` Herbert Xu
0 siblings, 1 reply; 6+ messages in thread
From: Pavel Roskin @ 2010-03-13 3:42 UTC (permalink / raw)
To: Roberto Sassu; +Cc: linux-crypto
On Fri, 2010-03-12 at 11:49 +0100, Roberto Sassu wrote:
> 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.
Thank you! That's indeed a useful example.
However, it's disappointing that the caller needs to deal explicitly
with completions. The blkcipher API is much simpler. I would have hard
time advocating a patch to CCMP that makes the code more complicated.
--
Regards,
Pavel Roskin
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Converting mac80211 CCMP to packet-at-a-time processing
2010-03-13 3:42 ` Pavel Roskin
@ 2010-03-13 12:28 ` Herbert Xu
2010-03-16 6:21 ` Pavel Roskin
0 siblings, 1 reply; 6+ messages in thread
From: Herbert Xu @ 2010-03-13 12:28 UTC (permalink / raw)
To: Pavel Roskin; +Cc: roberto.sassu, linux-crypto
Pavel Roskin <proski@gnu.org> wrote:
>
> However, it's disappointing that the caller needs to deal explicitly
> with completions. The blkcipher API is much simpler. I would have hard
> time advocating a patch to CCMP that makes the code more complicated.
You won't have to deal with completions if you allocate your
algorithm with the CRYPTO_ALG_ASYNC bit off. Of course you won't
be able to use most hardware accelerations either.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Converting mac80211 CCMP to packet-at-a-time processing
2010-03-13 12:28 ` Herbert Xu
@ 2010-03-16 6:21 ` Pavel Roskin
2010-03-18 8:19 ` Herbert Xu
0 siblings, 1 reply; 6+ messages in thread
From: Pavel Roskin @ 2010-03-16 6:21 UTC (permalink / raw)
To: Herbert Xu; +Cc: roberto.sassu, linux-crypto
On Sat, 2010-03-13 at 20:28 +0800, Herbert Xu wrote:
> Pavel Roskin <proski@gnu.org> wrote:
> >
> > However, it's disappointing that the caller needs to deal explicitly
> > with completions. The blkcipher API is much simpler. I would have hard
> > time advocating a patch to CCMP that makes the code more complicated.
>
> You won't have to deal with completions if you allocate your
> algorithm with the CRYPTO_ALG_ASYNC bit off. Of course you won't
> be able to use most hardware accelerations either.
Actually, I thought using CRYPTO_ALG_ASYNC in the mask meant to
_exclude_ asynchronous algorithms.
Is there any documentation for Linux crypto API that documents use of
CRYPTO_ALG_ASYNC? Also, I'd like to know meanings of
CRYPTO_TFM_REQ_MAY_BACKLOG and CRYPTO_TFM_REQ_MAY_SLEEP.
The crypto API feels like a minefield to me - I should check everything
in the code or even experiment to figure out how the public API works.
--
Regards,
Pavel Roskin
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Converting mac80211 CCMP to packet-at-a-time processing
2010-03-16 6:21 ` Pavel Roskin
@ 2010-03-18 8:19 ` Herbert Xu
0 siblings, 0 replies; 6+ messages in thread
From: Herbert Xu @ 2010-03-18 8:19 UTC (permalink / raw)
To: Pavel Roskin; +Cc: roberto.sassu, linux-crypto
Pavel Roskin <proski@gnu.org> wrote:
>
>> You won't have to deal with completions if you allocate your
>> algorithm with the CRYPTO_ALG_ASYNC bit off. Of course you won't
>> be able to use most hardware accelerations either.
>
> Actually, I thought using CRYPTO_ALG_ASYNC in the mask meant to
> _exclude_ asynchronous algorithms.
That's what I just said, no?
> Is there any documentation for Linux crypto API that documents use of
> CRYPTO_ALG_ASYNC? Also, I'd like to know meanings of
> CRYPTO_TFM_REQ_MAY_BACKLOG and CRYPTO_TFM_REQ_MAY_SLEEP.
Normally an async driver will simply drop requests and return
EBUSY when the hardware queue is full. MAY_BACKLOG allows the
caller to place a single request on a backlog queue. When that
request moves onto the hardware queue the caller will be notified
through the completion function with err set to EINPROGRESS.
This is used by drivers/md/dm-crypt.
MAY_SLEEP is only relevant for synchronous algorithms, it allows
the API to sleep which is useful if you are making a single large
request which would take an extended period of time to process.
> The crypto API feels like a minefield to me - I should check everything
> in the code or even experiment to figure out how the public API works.
Well patches to improve the API and/or documentation are welcome.
Thanks,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2010-03-18 8:20 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-03-12 5:29 Converting mac80211 CCMP to packet-at-a-time processing Pavel Roskin
-- strict thread matches above, loose matches on Subject: below --
2010-03-12 10:49 Roberto Sassu
2010-03-13 3:42 ` Pavel Roskin
2010-03-13 12:28 ` Herbert Xu
2010-03-16 6:21 ` Pavel Roskin
2010-03-18 8:19 ` Herbert Xu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).