2015-04-12 12:56:17 +08: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);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ext4_valid_filenames_enc_mode(uint32_t mode)
|
|
|
|
{
|
|
|
|
return (mode == EXT4_ENCRYPTION_MODE_AES_256_CTS);
|
|
|
|
}
|
|
|
|
|
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-19 01:17:47 +08: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 12:56:17 +08: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-19 01:17:47 +08:00
|
|
|
static int ext4_fname_encrypt(struct inode *inode,
|
2015-04-12 12:56:17 +08: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-19 01:17:47 +08:00
|
|
|
struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
|
|
|
|
struct crypto_ablkcipher *tfm = ci->ci_ctfm;
|
2015-04-12 12:56:17 +08:00
|
|
|
int res = 0;
|
|
|
|
char iv[EXT4_CRYPTO_BLOCK_SIZE];
|
2015-05-19 01:15:47 +08: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-19 01:17:47 +08:00
|
|
|
int padding = 4 << (ci->ci_flags & EXT4_POLICY_FLAGS_PAD_MASK);
|
2015-05-19 01:15:47 +08: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-19 01:17:47 +08:00
|
|
|
unsigned lim = max_name_len(inode);
|
2015-04-12 12:56:17 +08: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-19 01:17:47 +08:00
|
|
|
if (iname->len <= 0 || iname->len > lim)
|
2015-04-12 12:56:17 +08:00
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
ciphertext_len = (iname->len < EXT4_CRYPTO_BLOCK_SIZE) ?
|
|
|
|
EXT4_CRYPTO_BLOCK_SIZE : iname->len;
|
2015-05-02 04:56:50 +08: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-19 01:17:47 +08:00
|
|
|
ciphertext_len = (ciphertext_len > lim)
|
|
|
|
? lim : ciphertext_len;
|
2015-04-12 12:56:17 +08:00
|
|
|
|
2015-05-19 01:15:47 +08: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 12:56:17 +08: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-19 01:15:47 +08:00
|
|
|
kfree(alloc_buf);
|
2015-04-12 12:56:17 +08: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-19 01:15:47 +08: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 12:56:17 +08:00
|
|
|
res = crypto_ablkcipher_encrypt(req);
|
|
|
|
if (res == -EINPROGRESS || res == -EBUSY) {
|
|
|
|
BUG_ON(req->base.data != &ecr);
|
|
|
|
wait_for_completion(&ecr.completion);
|
|
|
|
res = ecr.res;
|
|
|
|
}
|
2015-05-19 01:15:47 +08:00
|
|
|
kfree(alloc_buf);
|
2015-04-12 12:56:17 +08: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-19 01:17:47 +08:00
|
|
|
static int ext4_fname_decrypt(struct inode *inode,
|
2015-04-12 12:56:17 +08: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-19 01:15:47 +08: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-19 01:17:47 +08:00
|
|
|
struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
|
|
|
|
struct crypto_ablkcipher *tfm = ci->ci_ctfm;
|
2015-04-12 12:56:17 +08: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-19 01:17:47 +08:00
|
|
|
unsigned lim = max_name_len(inode);
|
2015-04-12 12:56:17 +08: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-19 01:17:47 +08:00
|
|
|
if (iname->len <= 0 || iname->len > lim)
|
2015-04-12 12:56:17 +08: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-19 01:15:47 +08: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 12:56:17 +08:00
|
|
|
res = crypto_ablkcipher_decrypt(req);
|
|
|
|
if (res == -EINPROGRESS || res == -EBUSY) {
|
|
|
|
BUG_ON(req->base.data != &ecr);
|
|
|
|
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-02 04:56:45 +08:00
|
|
|
static const char *lookup_table =
|
|
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
|
|
|
|
|
2015-04-12 12:56:17 +08: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-02 04:56:45 +08:00
|
|
|
static int digest_encode(const char *src, int len, char *dst)
|
2015-04-12 12:56:17 +08:00
|
|
|
{
|
2015-05-02 04:56:45 +08: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 12:56:17 +08:00
|
|
|
i++;
|
|
|
|
}
|
2015-05-02 04:56:45 +08:00
|
|
|
if (bits)
|
|
|
|
*cp++ = lookup_table[ac & 0x3f];
|
|
|
|
return cp - dst;
|
2015-04-12 12:56:17 +08:00
|
|
|
}
|
|
|
|
|
2015-05-02 04:56:45 +08:00
|
|
|
static int digest_decode(const char *src, int len, char *dst)
|
2015-04-12 12:56:17 +08:00
|
|
|
{
|
2015-05-02 04:56:45 +08: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 12:56:17 +08:00
|
|
|
}
|
2015-05-02 04:56:45 +08:00
|
|
|
if (ac)
|
|
|
|
return -1;
|
|
|
|
return cp - dst;
|
2015-04-12 12:56:17 +08: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-06-01 01:35:32 +08: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 12:56:17 +08: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-19 01:17:47 +08:00
|
|
|
int ext4_fname_crypto_alloc_buffer(struct inode *inode,
|
2015-04-12 12:56:17 +08:00
|
|
|
u32 ilen, struct ext4_str *crypto_str)
|
|
|
|
{
|
2015-06-01 01:35:32 +08:00
|
|
|
unsigned int olen = ext4_fname_encrypted_size(inode, ilen);
|
2015-04-12 12:56:17 +08: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-19 01:17:47 +08:00
|
|
|
int _ext4_fname_disk_to_usr(struct inode *inode,
|
2015-05-02 04:56:45 +08:00
|
|
|
struct dx_hash_info *hinfo,
|
|
|
|
const struct ext4_str *iname,
|
|
|
|
struct ext4_str *oname)
|
2015-04-12 12:56:17 +08:00
|
|
|
{
|
2015-05-02 04:56:45 +08:00
|
|
|
char buf[24];
|
|
|
|
int ret;
|
|
|
|
|
2015-04-12 12:56:17 +08: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 23:33:16 +08: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-19 01:17:47 +08:00
|
|
|
if (EXT4_I(inode)->i_crypt_info)
|
|
|
|
return ext4_fname_decrypt(inode, iname, oname);
|
2015-05-02 04:56:45 +08: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);
|
|
|
|
memcpy(buf + 8, iname->name + iname->len - 16, 16);
|
|
|
|
oname->name[0] = '_';
|
|
|
|
ret = digest_encode(buf, 24, oname->name+1);
|
|
|
|
oname->len = ret + 1;
|
|
|
|
return ret + 1;
|
2015-04-12 12:56:17 +08: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-19 01:17:47 +08:00
|
|
|
int ext4_fname_disk_to_usr(struct inode *inode,
|
2015-05-02 04:56:45 +08:00
|
|
|
struct dx_hash_info *hinfo,
|
2015-04-12 12:56:17 +08: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-19 01:17:47 +08:00
|
|
|
return _ext4_fname_disk_to_usr(inode, hinfo, &iname, oname);
|
2015-04-12 12:56:17 +08: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-19 01:17:47 +08:00
|
|
|
int ext4_fname_usr_to_disk(struct inode *inode,
|
2015-04-12 12:56:17 +08: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-19 01:17:47 +08:00
|
|
|
struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
|
2015-04-12 12:56:17 +08: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-19 01:17:47 +08:00
|
|
|
if (ci) {
|
|
|
|
res = ext4_fname_encrypt(inode, iname, oname);
|
2015-04-12 12:56:17 +08: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-19 01:14:47 +08:00
|
|
|
int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
|
|
|
|
int lookup, struct ext4_filename *fname)
|
2015-04-12 12:56:17 +08: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-19 01:17:47 +08:00
|
|
|
struct ext4_crypt_info *ci;
|
2015-05-19 01:14:47 +08:00
|
|
|
int ret = 0, bigname = 0;
|
|
|
|
|
|
|
|
memset(fname, 0, sizeof(struct ext4_filename));
|
|
|
|
fname->usr_fname = iname;
|
2015-04-12 12:56:17 +08: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-19 01:17:47 +08:00
|
|
|
if (!ext4_encrypted_inode(dir) ||
|
2015-04-12 12:56:17 +08:00
|
|
|
((iname->name[0] == '.') &&
|
|
|
|
((iname->len == 1) ||
|
|
|
|
((iname->name[1] == '.') && (iname->len == 2))))) {
|
2015-05-19 01:14:47 +08:00
|
|
|
fname->disk_name.name = (unsigned char *) iname->name;
|
|
|
|
fname->disk_name.len = iname->len;
|
2015-06-01 01:35:22 +08:00
|
|
|
return 0;
|
2015-04-12 12:56:17 +08:00
|
|
|
}
|
2015-06-01 01:34:22 +08: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-19 01:17:47 +08: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-19 01:14:47 +08:00
|
|
|
&fname->crypto_buf);
|
|
|
|
if (ret < 0)
|
2015-06-01 01:35:22 +08: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-19 01:17:47 +08:00
|
|
|
ret = ext4_fname_encrypt(dir, iname, &fname->crypto_buf);
|
2015-05-19 01:14:47 +08:00
|
|
|
if (ret < 0)
|
2015-06-01 01:35:22 +08:00
|
|
|
goto errout;
|
2015-05-19 01:14:47 +08:00
|
|
|
fname->disk_name.name = fname->crypto_buf.name;
|
|
|
|
fname->disk_name.len = fname->crypto_buf.len;
|
2015-06-01 01:35:22 +08:00
|
|
|
return 0;
|
2015-05-02 04:56:45 +08:00
|
|
|
}
|
2015-06-01 01:35:22 +08:00
|
|
|
if (!lookup)
|
|
|
|
return -EACCES;
|
2015-05-02 04:56:45 +08:00
|
|
|
|
2015-05-19 01:14:47 +08: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-06-01 01:35:22 +08:00
|
|
|
(!bigname && (iname->len > 43)))
|
|
|
|
return -ENOENT;
|
|
|
|
|
2015-05-19 01:14:47 +08:00
|
|
|
fname->crypto_buf.name = kmalloc(32, GFP_KERNEL);
|
2015-06-01 01:35:22 +08:00
|
|
|
if (fname->crypto_buf.name == NULL)
|
|
|
|
return -ENOMEM;
|
2015-05-19 01:14:47 +08:00
|
|
|
ret = digest_decode(iname->name + bigname, iname->len - bigname,
|
|
|
|
fname->crypto_buf.name);
|
|
|
|
if (ret < 0) {
|
|
|
|
ret = -ENOENT;
|
2015-06-01 01:35:22 +08:00
|
|
|
goto errout;
|
2015-05-19 01:14:47 +08: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-06-01 01:35:22 +08:00
|
|
|
return 0;
|
|
|
|
errout:
|
|
|
|
kfree(fname->crypto_buf.name);
|
|
|
|
fname->crypto_buf.name = NULL;
|
2015-04-12 12:56:17 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-05-19 01:14:47 +08:00
|
|
|
void ext4_fname_free_filename(struct ext4_filename *fname)
|
2015-04-12 12:56:17 +08:00
|
|
|
{
|
2015-05-19 01:14:47 +08:00
|
|
|
kfree(fname->crypto_buf.name);
|
|
|
|
fname->crypto_buf.name = NULL;
|
|
|
|
fname->usr_fname = NULL;
|
|
|
|
fname->disk_name.name = NULL;
|
2015-04-12 12:56:17 +08:00
|
|
|
}
|