2015-04-12 00:56:17 -04:00
|
|
|
/*
|
|
|
|
* linux/fs/ext4/crypto_fname.c
|
|
|
|
*
|
|
|
|
* Copyright (C) 2015, Google, Inc.
|
|
|
|
*
|
|
|
|
* This contains functions for filename crypto management in ext4
|
|
|
|
*
|
|
|
|
* Written by Uday Savagaonkar, 2014.
|
|
|
|
*
|
|
|
|
* This has not yet undergone a rigorous security audit.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <crypto/hash.h>
|
|
|
|
#include <crypto/sha.h>
|
|
|
|
#include <keys/encrypted-type.h>
|
|
|
|
#include <keys/user-type.h>
|
|
|
|
#include <linux/crypto.h>
|
|
|
|
#include <linux/gfp.h>
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/key.h>
|
|
|
|
#include <linux/list.h>
|
|
|
|
#include <linux/mempool.h>
|
|
|
|
#include <linux/random.h>
|
|
|
|
#include <linux/scatterlist.h>
|
|
|
|
#include <linux/spinlock_types.h>
|
|
|
|
|
|
|
|
#include "ext4.h"
|
|
|
|
#include "ext4_crypto.h"
|
|
|
|
#include "xattr.h"
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ext4_dir_crypt_complete() -
|
|
|
|
*/
|
|
|
|
static void ext4_dir_crypt_complete(struct crypto_async_request *req, int res)
|
|
|
|
{
|
|
|
|
struct ext4_completion_result *ecr = req->data;
|
|
|
|
|
|
|
|
if (res == -EINPROGRESS)
|
|
|
|
return;
|
|
|
|
ecr->res = res;
|
|
|
|
complete(&ecr->completion);
|
|
|
|
}
|
|
|
|
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
static unsigned max_name_len(struct inode *inode)
|
|
|
|
{
|
|
|
|
return S_ISLNK(inode->i_mode) ? inode->i_sb->s_blocksize :
|
|
|
|
EXT4_NAME_LEN;
|
|
|
|
}
|
|
|
|
|
2015-04-12 00:56:17 -04:00
|
|
|
/**
|
|
|
|
* ext4_fname_encrypt() -
|
|
|
|
*
|
|
|
|
* This function encrypts the input filename, and returns the length of the
|
|
|
|
* ciphertext. Errors are returned as negative numbers. We trust the caller to
|
|
|
|
* allocate sufficient memory to oname string.
|
|
|
|
*/
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
static int ext4_fname_encrypt(struct inode *inode,
|
2015-04-12 00:56:17 -04:00
|
|
|
const struct qstr *iname,
|
|
|
|
struct ext4_str *oname)
|
|
|
|
{
|
|
|
|
u32 ciphertext_len;
|
|
|
|
struct ablkcipher_request *req = NULL;
|
|
|
|
DECLARE_EXT4_COMPLETION_RESULT(ecr);
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
|
|
|
|
struct crypto_ablkcipher *tfm = ci->ci_ctfm;
|
2015-04-12 00:56:17 -04:00
|
|
|
int res = 0;
|
|
|
|
char iv[EXT4_CRYPTO_BLOCK_SIZE];
|
2015-05-18 13:15:47 -04:00
|
|
|
struct scatterlist src_sg, dst_sg;
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
int padding = 4 << (ci->ci_flags & EXT4_POLICY_FLAGS_PAD_MASK);
|
2015-05-18 13:15:47 -04:00
|
|
|
char *workbuf, buf[32], *alloc_buf = NULL;
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
unsigned lim = max_name_len(inode);
|
2015-04-12 00:56:17 -04:00
|
|
|
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
if (iname->len <= 0 || iname->len > lim)
|
2015-04-12 00:56:17 -04:00
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
ciphertext_len = (iname->len < EXT4_CRYPTO_BLOCK_SIZE) ?
|
|
|
|
EXT4_CRYPTO_BLOCK_SIZE : iname->len;
|
2015-05-01 16:56:50 -04:00
|
|
|
ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding);
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
ciphertext_len = (ciphertext_len > lim)
|
|
|
|
? lim : ciphertext_len;
|
2015-04-12 00:56:17 -04:00
|
|
|
|
2015-05-18 13:15:47 -04:00
|
|
|
if (ciphertext_len <= sizeof(buf)) {
|
|
|
|
workbuf = buf;
|
|
|
|
} else {
|
|
|
|
alloc_buf = kmalloc(ciphertext_len, GFP_NOFS);
|
|
|
|
if (!alloc_buf)
|
|
|
|
return -ENOMEM;
|
|
|
|
workbuf = alloc_buf;
|
|
|
|
}
|
|
|
|
|
2015-04-12 00:56:17 -04:00
|
|
|
/* Allocate request */
|
|
|
|
req = ablkcipher_request_alloc(tfm, GFP_NOFS);
|
|
|
|
if (!req) {
|
|
|
|
printk_ratelimited(
|
|
|
|
KERN_ERR "%s: crypto_request_alloc() failed\n", __func__);
|
2015-05-18 13:15:47 -04:00
|
|
|
kfree(alloc_buf);
|
2015-04-12 00:56:17 -04:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
ablkcipher_request_set_callback(req,
|
|
|
|
CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
|
|
|
|
ext4_dir_crypt_complete, &ecr);
|
|
|
|
|
|
|
|
/* Copy the input */
|
|
|
|
memcpy(workbuf, iname->name, iname->len);
|
|
|
|
if (iname->len < ciphertext_len)
|
|
|
|
memset(workbuf + iname->len, 0, ciphertext_len - iname->len);
|
|
|
|
|
|
|
|
/* Initialize IV */
|
|
|
|
memset(iv, 0, EXT4_CRYPTO_BLOCK_SIZE);
|
|
|
|
|
|
|
|
/* Create encryption request */
|
2015-05-18 13:15:47 -04:00
|
|
|
sg_init_one(&src_sg, workbuf, ciphertext_len);
|
|
|
|
sg_init_one(&dst_sg, oname->name, ciphertext_len);
|
|
|
|
ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, ciphertext_len, iv);
|
2015-04-12 00:56:17 -04:00
|
|
|
res = crypto_ablkcipher_encrypt(req);
|
|
|
|
if (res == -EINPROGRESS || res == -EBUSY) {
|
|
|
|
wait_for_completion(&ecr.completion);
|
|
|
|
res = ecr.res;
|
|
|
|
}
|
2015-05-18 13:15:47 -04:00
|
|
|
kfree(alloc_buf);
|
2015-04-12 00:56:17 -04:00
|
|
|
ablkcipher_request_free(req);
|
|
|
|
if (res < 0) {
|
|
|
|
printk_ratelimited(
|
|
|
|
KERN_ERR "%s: Error (error code %d)\n", __func__, res);
|
|
|
|
}
|
|
|
|
oname->len = ciphertext_len;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ext4_fname_decrypt()
|
|
|
|
* This function decrypts the input filename, and returns
|
|
|
|
* the length of the plaintext.
|
|
|
|
* Errors are returned as negative numbers.
|
|
|
|
* We trust the caller to allocate sufficient memory to oname string.
|
|
|
|
*/
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
static int ext4_fname_decrypt(struct inode *inode,
|
2015-04-12 00:56:17 -04:00
|
|
|
const struct ext4_str *iname,
|
|
|
|
struct ext4_str *oname)
|
|
|
|
{
|
|
|
|
struct ext4_str tmp_in[2], tmp_out[1];
|
|
|
|
struct ablkcipher_request *req = NULL;
|
|
|
|
DECLARE_EXT4_COMPLETION_RESULT(ecr);
|
2015-05-18 13:15:47 -04:00
|
|
|
struct scatterlist src_sg, dst_sg;
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
|
|
|
|
struct crypto_ablkcipher *tfm = ci->ci_ctfm;
|
2015-04-12 00:56:17 -04:00
|
|
|
int res = 0;
|
|
|
|
char iv[EXT4_CRYPTO_BLOCK_SIZE];
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
unsigned lim = max_name_len(inode);
|
2015-04-12 00:56:17 -04:00
|
|
|
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
if (iname->len <= 0 || iname->len > lim)
|
2015-04-12 00:56:17 -04:00
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
tmp_in[0].name = iname->name;
|
|
|
|
tmp_in[0].len = iname->len;
|
|
|
|
tmp_out[0].name = oname->name;
|
|
|
|
|
|
|
|
/* Allocate request */
|
|
|
|
req = ablkcipher_request_alloc(tfm, GFP_NOFS);
|
|
|
|
if (!req) {
|
|
|
|
printk_ratelimited(
|
|
|
|
KERN_ERR "%s: crypto_request_alloc() failed\n", __func__);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
ablkcipher_request_set_callback(req,
|
|
|
|
CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
|
|
|
|
ext4_dir_crypt_complete, &ecr);
|
|
|
|
|
|
|
|
/* Initialize IV */
|
|
|
|
memset(iv, 0, EXT4_CRYPTO_BLOCK_SIZE);
|
|
|
|
|
|
|
|
/* Create encryption request */
|
2015-05-18 13:15:47 -04:00
|
|
|
sg_init_one(&src_sg, iname->name, iname->len);
|
|
|
|
sg_init_one(&dst_sg, oname->name, oname->len);
|
|
|
|
ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, iv);
|
2015-04-12 00:56:17 -04:00
|
|
|
res = crypto_ablkcipher_decrypt(req);
|
|
|
|
if (res == -EINPROGRESS || res == -EBUSY) {
|
|
|
|
wait_for_completion(&ecr.completion);
|
|
|
|
res = ecr.res;
|
|
|
|
}
|
|
|
|
ablkcipher_request_free(req);
|
|
|
|
if (res < 0) {
|
|
|
|
printk_ratelimited(
|
|
|
|
KERN_ERR "%s: Error in ext4_fname_encrypt (error code %d)\n",
|
|
|
|
__func__, res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
oname->len = strnlen(oname->name, iname->len);
|
|
|
|
return oname->len;
|
|
|
|
}
|
|
|
|
|
2015-05-01 16:56:45 -04:00
|
|
|
static const char *lookup_table =
|
|
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
|
|
|
|
|
2015-04-12 00:56:17 -04:00
|
|
|
/**
|
|
|
|
* ext4_fname_encode_digest() -
|
|
|
|
*
|
|
|
|
* Encodes the input digest using characters from the set [a-zA-Z0-9_+].
|
|
|
|
* The encoded string is roughly 4/3 times the size of the input string.
|
|
|
|
*/
|
2015-05-01 16:56:45 -04:00
|
|
|
static int digest_encode(const char *src, int len, char *dst)
|
2015-04-12 00:56:17 -04:00
|
|
|
{
|
2015-05-01 16:56:45 -04:00
|
|
|
int i = 0, bits = 0, ac = 0;
|
|
|
|
char *cp = dst;
|
|
|
|
|
|
|
|
while (i < len) {
|
|
|
|
ac += (((unsigned char) src[i]) << bits);
|
|
|
|
bits += 8;
|
|
|
|
do {
|
|
|
|
*cp++ = lookup_table[ac & 0x3f];
|
|
|
|
ac >>= 6;
|
|
|
|
bits -= 6;
|
|
|
|
} while (bits >= 6);
|
2015-04-12 00:56:17 -04:00
|
|
|
i++;
|
|
|
|
}
|
2015-05-01 16:56:45 -04:00
|
|
|
if (bits)
|
|
|
|
*cp++ = lookup_table[ac & 0x3f];
|
|
|
|
return cp - dst;
|
2015-04-12 00:56:17 -04:00
|
|
|
}
|
|
|
|
|
2015-05-01 16:56:45 -04:00
|
|
|
static int digest_decode(const char *src, int len, char *dst)
|
2015-04-12 00:56:17 -04:00
|
|
|
{
|
2015-05-01 16:56:45 -04:00
|
|
|
int i = 0, bits = 0, ac = 0;
|
|
|
|
const char *p;
|
|
|
|
char *cp = dst;
|
|
|
|
|
|
|
|
while (i < len) {
|
|
|
|
p = strchr(lookup_table, src[i]);
|
|
|
|
if (p == NULL || src[i] == 0)
|
|
|
|
return -2;
|
|
|
|
ac += (p - lookup_table) << bits;
|
|
|
|
bits += 6;
|
|
|
|
if (bits >= 8) {
|
|
|
|
*cp++ = ac & 0xff;
|
|
|
|
ac >>= 8;
|
|
|
|
bits -= 8;
|
|
|
|
}
|
|
|
|
i++;
|
2015-04-12 00:56:17 -04:00
|
|
|
}
|
2015-05-01 16:56:45 -04:00
|
|
|
if (ac)
|
|
|
|
return -1;
|
|
|
|
return cp - dst;
|
2015-04-12 00:56:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ext4_fname_crypto_round_up() -
|
|
|
|
*
|
|
|
|
* Return: The next multiple of block size
|
|
|
|
*/
|
|
|
|
u32 ext4_fname_crypto_round_up(u32 size, u32 blksize)
|
|
|
|
{
|
|
|
|
return ((size+blksize-1)/blksize)*blksize;
|
|
|
|
}
|
|
|
|
|
2015-05-31 13:35:32 -04:00
|
|
|
unsigned ext4_fname_encrypted_size(struct inode *inode, u32 ilen)
|
|
|
|
{
|
|
|
|
struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
|
|
|
|
int padding = 32;
|
|
|
|
|
|
|
|
if (ci)
|
|
|
|
padding = 4 << (ci->ci_flags & EXT4_POLICY_FLAGS_PAD_MASK);
|
|
|
|
if (ilen < EXT4_CRYPTO_BLOCK_SIZE)
|
|
|
|
ilen = EXT4_CRYPTO_BLOCK_SIZE;
|
|
|
|
return ext4_fname_crypto_round_up(ilen, padding);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ext4_fname_crypto_alloc_buffer() -
|
2015-04-12 00:56:17 -04:00
|
|
|
*
|
|
|
|
* Allocates an output buffer that is sufficient for the crypto operation
|
|
|
|
* specified by the context and the direction.
|
|
|
|
*/
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
int ext4_fname_crypto_alloc_buffer(struct inode *inode,
|
2015-04-12 00:56:17 -04:00
|
|
|
u32 ilen, struct ext4_str *crypto_str)
|
|
|
|
{
|
2015-05-31 13:35:32 -04:00
|
|
|
unsigned int olen = ext4_fname_encrypted_size(inode, ilen);
|
2015-04-12 00:56:17 -04:00
|
|
|
|
|
|
|
crypto_str->len = olen;
|
|
|
|
if (olen < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2)
|
|
|
|
olen = EXT4_FNAME_CRYPTO_DIGEST_SIZE*2;
|
|
|
|
/* Allocated buffer can hold one more character to null-terminate the
|
|
|
|
* string */
|
|
|
|
crypto_str->name = kmalloc(olen+1, GFP_NOFS);
|
|
|
|
if (!(crypto_str->name))
|
|
|
|
return -ENOMEM;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ext4_fname_crypto_free_buffer() -
|
|
|
|
*
|
|
|
|
* Frees the buffer allocated for crypto operation.
|
|
|
|
*/
|
|
|
|
void ext4_fname_crypto_free_buffer(struct ext4_str *crypto_str)
|
|
|
|
{
|
|
|
|
if (!crypto_str)
|
|
|
|
return;
|
|
|
|
kfree(crypto_str->name);
|
|
|
|
crypto_str->name = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ext4_fname_disk_to_usr() - converts a filename from disk space to user space
|
|
|
|
*/
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
int _ext4_fname_disk_to_usr(struct inode *inode,
|
2015-05-01 16:56:45 -04:00
|
|
|
struct dx_hash_info *hinfo,
|
|
|
|
const struct ext4_str *iname,
|
|
|
|
struct ext4_str *oname)
|
2015-04-12 00:56:17 -04:00
|
|
|
{
|
2015-05-01 16:56:45 -04:00
|
|
|
char buf[24];
|
|
|
|
int ret;
|
|
|
|
|
2015-04-12 00:56:17 -04:00
|
|
|
if (iname->len < 3) {
|
|
|
|
/*Check for . and .. */
|
|
|
|
if (iname->name[0] == '.' && iname->name[iname->len-1] == '.') {
|
|
|
|
oname->name[0] = '.';
|
|
|
|
oname->name[iname->len-1] = '.';
|
|
|
|
oname->len = iname->len;
|
|
|
|
return oname->len;
|
|
|
|
}
|
|
|
|
}
|
2015-07-17 11:33:16 -04:00
|
|
|
if (iname->len < EXT4_CRYPTO_BLOCK_SIZE) {
|
|
|
|
EXT4_ERROR_INODE(inode, "encrypted inode too small");
|
|
|
|
return -EUCLEAN;
|
|
|
|
}
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
if (EXT4_I(inode)->i_crypt_info)
|
|
|
|
return ext4_fname_decrypt(inode, iname, oname);
|
2015-05-01 16:56:45 -04:00
|
|
|
|
|
|
|
if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) {
|
|
|
|
ret = digest_encode(iname->name, iname->len, oname->name);
|
|
|
|
oname->len = ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
if (hinfo) {
|
|
|
|
memcpy(buf, &hinfo->hash, 4);
|
|
|
|
memcpy(buf+4, &hinfo->minor_hash, 4);
|
|
|
|
} else
|
|
|
|
memset(buf, 0, 8);
|
fscrypt: avoid collisions when presenting long encrypted filenames
commit 6b06cdee81d68a8a829ad8e8d0f31d6836744af9 upstream.
When accessing an encrypted directory without the key, userspace must
operate on filenames derived from the ciphertext names, which contain
arbitrary bytes. Since we must support filenames as long as NAME_MAX,
we can't always just base64-encode the ciphertext, since that may make
it too long. Currently, this is solved by presenting long names in an
abbreviated form containing any needed filesystem-specific hashes (e.g.
to identify a directory block), then the last 16 bytes of ciphertext.
This needs to be sufficient to identify the actual name on lookup.
However, there is a bug. It seems to have been assumed that due to the
use of a CBC (ciphertext block chaining)-based encryption mode, the last
16 bytes (i.e. the AES block size) of ciphertext would depend on the
full plaintext, preventing collisions. However, we actually use CBC
with ciphertext stealing (CTS), which handles the last two blocks
specially, causing them to appear "flipped". Thus, it's actually the
second-to-last block which depends on the full plaintext.
This caused long filenames that differ only near the end of their
plaintexts to, when observed without the key, point to the wrong inode
and be undeletable. For example, with ext4:
# echo pass | e4crypt add_key -p 16 edir/
# seq -f "edir/abcdefghijklmnopqrstuvwxyz012345%.0f" 100000 | xargs touch
# find edir/ -type f | xargs stat -c %i | sort | uniq | wc -l
100000
# sync
# echo 3 > /proc/sys/vm/drop_caches
# keyctl new_session
# find edir/ -type f | xargs stat -c %i | sort | uniq | wc -l
2004
# rm -rf edir/
rm: cannot remove 'edir/_A7nNFi3rhkEQlJ6P,hdzluhODKOeWx5V': Structure needs cleaning
...
To fix this, when presenting long encrypted filenames, encode the
second-to-last block of ciphertext rather than the last 16 bytes.
Although it would be nice to solve this without depending on a specific
encryption mode, that would mean doing a cryptographic hash like SHA-256
which would be much less efficient. This way is sufficient for now, and
it's still compatible with encryption modes like HEH which are strong
pseudorandom permutations. Also, changing the presented names is still
allowed at any time because they are only provided to allow applications
to do things like delete encrypted directories. They're not designed to
be used to persistently identify files --- which would be hard to do
anyway, given that they're encrypted after all.
For ease of backports, this patch only makes the minimal fix to both
ext4 and f2fs. It leaves ubifs as-is, since ubifs doesn't compare the
ciphertext block yet. Follow-on patches will clean things up properly
and make the filesystems use a shared helper function.
Fixes: 5de0b4d0cd15 ("ext4 crypto: simplify and speed up filename encryption")
Reported-by: Gwendal Grignou <gwendal@chromium.org>
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2017-04-24 10:00:09 -07:00
|
|
|
memcpy(buf + 8, iname->name + ((iname->len - 17) & ~15), 16);
|
2015-05-01 16:56:45 -04:00
|
|
|
oname->name[0] = '_';
|
|
|
|
ret = digest_encode(buf, 24, oname->name+1);
|
|
|
|
oname->len = ret + 1;
|
|
|
|
return ret + 1;
|
2015-04-12 00:56:17 -04:00
|
|
|
}
|
|
|
|
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
int ext4_fname_disk_to_usr(struct inode *inode,
|
2015-05-01 16:56:45 -04:00
|
|
|
struct dx_hash_info *hinfo,
|
2015-04-12 00:56:17 -04:00
|
|
|
const struct ext4_dir_entry_2 *de,
|
|
|
|
struct ext4_str *oname)
|
|
|
|
{
|
|
|
|
struct ext4_str iname = {.name = (unsigned char *) de->name,
|
|
|
|
.len = de->name_len };
|
|
|
|
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
return _ext4_fname_disk_to_usr(inode, hinfo, &iname, oname);
|
2015-04-12 00:56:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ext4_fname_usr_to_disk() - converts a filename from user space to disk space
|
|
|
|
*/
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
int ext4_fname_usr_to_disk(struct inode *inode,
|
2015-04-12 00:56:17 -04:00
|
|
|
const struct qstr *iname,
|
|
|
|
struct ext4_str *oname)
|
|
|
|
{
|
|
|
|
int res;
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
|
2015-04-12 00:56:17 -04:00
|
|
|
|
|
|
|
if (iname->len < 3) {
|
|
|
|
/*Check for . and .. */
|
|
|
|
if (iname->name[0] == '.' &&
|
|
|
|
iname->name[iname->len-1] == '.') {
|
|
|
|
oname->name[0] = '.';
|
|
|
|
oname->name[iname->len-1] = '.';
|
|
|
|
oname->len = iname->len;
|
|
|
|
return oname->len;
|
|
|
|
}
|
|
|
|
}
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
if (ci) {
|
|
|
|
res = ext4_fname_encrypt(inode, iname, oname);
|
2015-04-12 00:56:17 -04:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
/* Without a proper key, a user is not allowed to modify the filenames
|
|
|
|
* in a directory. Consequently, a user space name cannot be mapped to
|
|
|
|
* a disk-space name */
|
|
|
|
return -EACCES;
|
|
|
|
}
|
|
|
|
|
2015-05-18 13:14:47 -04:00
|
|
|
int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
|
|
|
|
int lookup, struct ext4_filename *fname)
|
2015-04-12 00:56:17 -04:00
|
|
|
{
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
struct ext4_crypt_info *ci;
|
2015-05-18 13:14:47 -04:00
|
|
|
int ret = 0, bigname = 0;
|
|
|
|
|
|
|
|
memset(fname, 0, sizeof(struct ext4_filename));
|
|
|
|
fname->usr_fname = iname;
|
2015-04-12 00:56:17 -04:00
|
|
|
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
if (!ext4_encrypted_inode(dir) ||
|
2015-04-12 00:56:17 -04:00
|
|
|
((iname->name[0] == '.') &&
|
|
|
|
((iname->len == 1) ||
|
|
|
|
((iname->name[1] == '.') && (iname->len == 2))))) {
|
2015-05-18 13:14:47 -04:00
|
|
|
fname->disk_name.name = (unsigned char *) iname->name;
|
|
|
|
fname->disk_name.len = iname->len;
|
2015-05-31 13:35:22 -04:00
|
|
|
return 0;
|
2015-04-12 00:56:17 -04:00
|
|
|
}
|
2015-05-31 13:34:22 -04:00
|
|
|
ret = ext4_get_encryption_info(dir);
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
ci = EXT4_I(dir)->i_crypt_info;
|
|
|
|
if (ci) {
|
|
|
|
ret = ext4_fname_crypto_alloc_buffer(dir, iname->len,
|
2015-05-18 13:14:47 -04:00
|
|
|
&fname->crypto_buf);
|
|
|
|
if (ret < 0)
|
2015-05-31 13:35:22 -04:00
|
|
|
return ret;
|
ext4 crypto: reorganize how we store keys in the inode
This is a pretty massive patch which does a number of different things:
1) The per-inode encryption information is now stored in an allocated
data structure, ext4_crypt_info, instead of directly in the node.
This reduces the size usage of an in-memory inode when it is not
using encryption.
2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
encryption structure instead. This remove an unnecessary memory
allocation and free for the fname_crypto_ctx as well as allowing us
to reuse the ctfm in a directory for multiple lookups and file
creations.
3) We also cache the inode's policy information in the ext4_crypt_info
structure so we don't have to continually read it out of the
extended attributes.
4) We now keep the keyring key in the inode's encryption structure
instead of releasing it after we are done using it to derive the
per-inode key. This allows us to test to see if the key has been
revoked; if it has, we prevent the use of the derived key and free
it.
5) When an inode is released (or when the derived key is freed), we
will use memset_explicit() to zero out the derived key, so it's not
left hanging around in memory. This implies that when a user logs
out, it is important to first revoke the key, and then unlink it,
and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
release any decrypted pages and dcache entries from the system
caches.
6) All this, and we also shrink the number of lines of code by around
100. :-)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-05-18 13:17:47 -04:00
|
|
|
ret = ext4_fname_encrypt(dir, iname, &fname->crypto_buf);
|
2015-05-18 13:14:47 -04:00
|
|
|
if (ret < 0)
|
2015-05-31 13:35:22 -04:00
|
|
|
goto errout;
|
2015-05-18 13:14:47 -04:00
|
|
|
fname->disk_name.name = fname->crypto_buf.name;
|
|
|
|
fname->disk_name.len = fname->crypto_buf.len;
|
2015-05-31 13:35:22 -04:00
|
|
|
return 0;
|
2015-05-01 16:56:45 -04:00
|
|
|
}
|
2015-05-31 13:35:22 -04:00
|
|
|
if (!lookup)
|
|
|
|
return -EACCES;
|
2015-05-01 16:56:45 -04:00
|
|
|
|
2015-05-18 13:14:47 -04:00
|
|
|
/* We don't have the key and we are doing a lookup; decode the
|
|
|
|
* user-supplied name
|
|
|
|
*/
|
|
|
|
if (iname->name[0] == '_')
|
|
|
|
bigname = 1;
|
|
|
|
if ((bigname && (iname->len != 33)) ||
|
2015-05-31 13:35:22 -04:00
|
|
|
(!bigname && (iname->len > 43)))
|
|
|
|
return -ENOENT;
|
|
|
|
|
2015-05-18 13:14:47 -04:00
|
|
|
fname->crypto_buf.name = kmalloc(32, GFP_KERNEL);
|
2015-05-31 13:35:22 -04:00
|
|
|
if (fname->crypto_buf.name == NULL)
|
|
|
|
return -ENOMEM;
|
2015-05-18 13:14:47 -04:00
|
|
|
ret = digest_decode(iname->name + bigname, iname->len - bigname,
|
|
|
|
fname->crypto_buf.name);
|
|
|
|
if (ret < 0) {
|
|
|
|
ret = -ENOENT;
|
2015-05-31 13:35:22 -04:00
|
|
|
goto errout;
|
2015-05-18 13:14:47 -04:00
|
|
|
}
|
|
|
|
fname->crypto_buf.len = ret;
|
|
|
|
if (bigname) {
|
|
|
|
memcpy(&fname->hinfo.hash, fname->crypto_buf.name, 4);
|
|
|
|
memcpy(&fname->hinfo.minor_hash, fname->crypto_buf.name + 4, 4);
|
|
|
|
} else {
|
|
|
|
fname->disk_name.name = fname->crypto_buf.name;
|
|
|
|
fname->disk_name.len = fname->crypto_buf.len;
|
|
|
|
}
|
2015-05-31 13:35:22 -04:00
|
|
|
return 0;
|
|
|
|
errout:
|
|
|
|
kfree(fname->crypto_buf.name);
|
|
|
|
fname->crypto_buf.name = NULL;
|
2015-04-12 00:56:17 -04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-05-18 13:14:47 -04:00
|
|
|
void ext4_fname_free_filename(struct ext4_filename *fname)
|
2015-04-12 00:56:17 -04:00
|
|
|
{
|
2015-05-18 13:14:47 -04:00
|
|
|
kfree(fname->crypto_buf.name);
|
|
|
|
fname->crypto_buf.name = NULL;
|
|
|
|
fname->usr_fname = NULL;
|
|
|
|
fname->disk_name.name = NULL;
|
2015-04-12 00:56:17 -04:00
|
|
|
}
|