ecryptfs: enhancing ecryptfs to be configurable with encryption type
enabled eCryptfs for qcom targets. In addition to the usual options, a special mode 'aes-xts' was added for qcom ICE hw encryption Change-Id: I20c01adc46c977b4a5db0be9ff93384cda14bc56 Signed-off-by: Lina Zarivach <linaz@codeaurora.org> Signed-off-by: Andrey Markovytch <andreym@codeaurora.org> [gbroner@codeaurora.org: fix merge conflict] Signed-off-by: Gilad Broner <gbroner@codeaurora.org>
This commit is contained in:
parent
eaf3acf0d2
commit
5eebf86343
12 changed files with 634 additions and 40 deletions
|
@ -4,7 +4,7 @@
|
|||
|
||||
obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
|
||||
|
||||
ecryptfs-y := dentry.o file.o inode.o main.o super.o mmap.o read_write.o \
|
||||
crypto.o keystore.o kthread.o debug.o
|
||||
ecryptfs-y := dentry.o file.o inode.o main.o super.o mmap.o read_write.o events.o \
|
||||
crypto.o keystore.o kthread.o debug.o caches_utils.o
|
||||
|
||||
ecryptfs-$(CONFIG_ECRYPT_FS_MESSAGING) += messaging.o miscdev.o
|
||||
|
|
76
fs/ecryptfs/caches_utils.c
Normal file
76
fs/ecryptfs/caches_utils.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/pagevec.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
void ecryptfs_drop_pagecache_sb(struct super_block *sb, void *unused)
|
||||
{
|
||||
struct inode *inode, *toput_inode = NULL;
|
||||
|
||||
spin_lock(&sb->s_inode_list_lock);
|
||||
list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
|
||||
spin_lock(&inode->i_lock);
|
||||
if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) ||
|
||||
(inode->i_mapping->nrpages == 0)) {
|
||||
spin_unlock(&inode->i_lock);
|
||||
continue;
|
||||
}
|
||||
__iget(inode);
|
||||
spin_unlock(&inode->i_lock);
|
||||
spin_unlock(&sb->s_inode_list_lock);
|
||||
invalidate_mapping_pages(inode->i_mapping, 0, -1);
|
||||
iput(toput_inode);
|
||||
toput_inode = inode;
|
||||
spin_lock(&sb->s_inode_list_lock);
|
||||
}
|
||||
spin_unlock(&sb->s_inode_list_lock);
|
||||
iput(toput_inode);
|
||||
}
|
||||
|
||||
void clean_inode_pages(struct address_space *mapping,
|
||||
pgoff_t start, pgoff_t end)
|
||||
{
|
||||
struct pagevec pvec;
|
||||
pgoff_t index = start;
|
||||
int i;
|
||||
|
||||
pagevec_init(&pvec, 0);
|
||||
while (index <= end && pagevec_lookup(&pvec, mapping, index,
|
||||
min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) {
|
||||
for (i = 0; i < pagevec_count(&pvec); i++) {
|
||||
struct page *page = pvec.pages[i];
|
||||
|
||||
/**
|
||||
* We rely upon deletion
|
||||
* not changing page->index
|
||||
*/
|
||||
index = page->index;
|
||||
if (index > end)
|
||||
break;
|
||||
if (!trylock_page(page))
|
||||
continue;
|
||||
WARN_ON(page->index != index);
|
||||
zero_user(page, 0, PAGE_CACHE_SIZE);
|
||||
unlock_page(page);
|
||||
}
|
||||
pagevec_release(&pvec);
|
||||
cond_resched();
|
||||
index++;
|
||||
}
|
||||
}
|
|
@ -35,6 +35,7 @@
|
|||
#include <linux/scatterlist.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/ecryptfs.h>
|
||||
#include "ecryptfs_kernel.h"
|
||||
|
||||
#define DECRYPT 0
|
||||
|
@ -466,6 +467,30 @@ out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void init_ecryption_parameters(bool *hw_crypt, bool *cipher_supported,
|
||||
struct ecryptfs_crypt_stat *crypt_stat)
|
||||
{
|
||||
if (!hw_crypt || !cipher_supported)
|
||||
return;
|
||||
|
||||
*cipher_supported = false;
|
||||
*hw_crypt = false;
|
||||
|
||||
if (get_events() && get_events()->is_cipher_supported_cb) {
|
||||
*cipher_supported =
|
||||
get_events()->is_cipher_supported_cb(
|
||||
ecryptfs_get_full_cipher(crypt_stat->cipher,
|
||||
crypt_stat->cipher_mode));
|
||||
if (*cipher_supported) {
|
||||
/**
|
||||
* we should apply external algorythm
|
||||
* assume that is_hw_crypt() cbck is supplied
|
||||
*/
|
||||
*hw_crypt = get_events()->is_hw_crypt_cb();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ecryptfs_encrypt_page
|
||||
* @page: Page mapped from the eCryptfs inode for the file; contains
|
||||
|
@ -491,11 +516,18 @@ int ecryptfs_encrypt_page(struct page *page)
|
|||
loff_t extent_offset;
|
||||
loff_t lower_offset;
|
||||
int rc = 0;
|
||||
bool is_hw_crypt;
|
||||
bool is_cipher_supported;
|
||||
|
||||
|
||||
ecryptfs_inode = page->mapping->host;
|
||||
crypt_stat =
|
||||
&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
|
||||
BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
|
||||
|
||||
init_ecryption_parameters(&is_hw_crypt,
|
||||
&is_cipher_supported, crypt_stat);
|
||||
|
||||
enc_extent_page = alloc_page(GFP_USER);
|
||||
if (!enc_extent_page) {
|
||||
rc = -ENOMEM;
|
||||
|
@ -503,24 +535,51 @@ int ecryptfs_encrypt_page(struct page *page)
|
|||
"encrypted extent\n");
|
||||
goto out;
|
||||
}
|
||||
if (is_hw_crypt) {
|
||||
/* no need for encryption */
|
||||
} else {
|
||||
for (extent_offset = 0;
|
||||
extent_offset <
|
||||
(PAGE_CACHE_SIZE / crypt_stat->extent_size);
|
||||
extent_offset++) {
|
||||
|
||||
for (extent_offset = 0;
|
||||
extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size);
|
||||
extent_offset++) {
|
||||
rc = crypt_extent(crypt_stat, enc_extent_page, page,
|
||||
extent_offset, ENCRYPT);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "%s: Error encrypting extent; "
|
||||
"rc = [%d]\n", __func__, rc);
|
||||
goto out;
|
||||
if (is_cipher_supported) {
|
||||
if (!get_events()->encrypt_cb) {
|
||||
rc = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
rc = get_events()->encrypt_cb(page,
|
||||
enc_extent_page,
|
||||
ecryptfs_inode_to_lower(
|
||||
ecryptfs_inode),
|
||||
extent_offset);
|
||||
} else {
|
||||
rc = crypt_extent(crypt_stat,
|
||||
enc_extent_page, page,
|
||||
extent_offset, ENCRYPT);
|
||||
}
|
||||
if (rc) {
|
||||
ecryptfs_printk(KERN_ERR,
|
||||
"%s: Error encrypting; rc = [%d]\n",
|
||||
__func__, rc);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lower_offset = lower_offset_for_page(crypt_stat, page);
|
||||
enc_extent_virt = kmap(enc_extent_page);
|
||||
if (is_hw_crypt)
|
||||
enc_extent_virt = kmap(page);
|
||||
else
|
||||
enc_extent_virt = kmap(enc_extent_page);
|
||||
|
||||
rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt, lower_offset,
|
||||
PAGE_CACHE_SIZE);
|
||||
kunmap(enc_extent_page);
|
||||
if (!is_hw_crypt)
|
||||
kunmap(enc_extent_page);
|
||||
else
|
||||
kunmap(page);
|
||||
|
||||
if (rc < 0) {
|
||||
ecryptfs_printk(KERN_ERR,
|
||||
"Error attempting to write lower page; rc = [%d]\n",
|
||||
|
@ -559,6 +618,8 @@ int ecryptfs_decrypt_page(struct page *page)
|
|||
unsigned long extent_offset;
|
||||
loff_t lower_offset;
|
||||
int rc = 0;
|
||||
bool is_cipher_supported;
|
||||
bool is_hw_crypt;
|
||||
|
||||
ecryptfs_inode = page->mapping->host;
|
||||
crypt_stat =
|
||||
|
@ -577,13 +638,33 @@ int ecryptfs_decrypt_page(struct page *page)
|
|||
goto out;
|
||||
}
|
||||
|
||||
init_ecryption_parameters(&is_hw_crypt,
|
||||
&is_cipher_supported, crypt_stat);
|
||||
|
||||
if (is_hw_crypt) {
|
||||
rc = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
for (extent_offset = 0;
|
||||
extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size);
|
||||
extent_offset++) {
|
||||
rc = crypt_extent(crypt_stat, page, page,
|
||||
if (is_cipher_supported) {
|
||||
if (!get_events()->decrypt_cb) {
|
||||
rc = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = get_events()->decrypt_cb(page, page,
|
||||
ecryptfs_inode_to_lower(ecryptfs_inode),
|
||||
extent_offset);
|
||||
|
||||
} else
|
||||
rc = crypt_extent(crypt_stat, page, page,
|
||||
extent_offset, DECRYPT);
|
||||
|
||||
if (rc) {
|
||||
printk(KERN_ERR "%s: Error encrypting extent; "
|
||||
ecryptfs_printk(KERN_ERR, "%s: Error decrypting extent;"
|
||||
"rc = [%d]\n", __func__, rc);
|
||||
goto out;
|
||||
}
|
||||
|
@ -823,7 +904,6 @@ int ecryptfs_new_file_context(struct inode *ecryptfs_inode)
|
|||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
|
||||
&ecryptfs_superblock_to_private(
|
||||
ecryptfs_inode->i_sb)->mount_crypt_stat;
|
||||
int cipher_name_len;
|
||||
int rc = 0;
|
||||
|
||||
ecryptfs_set_default_crypt_stat_vals(crypt_stat, mount_crypt_stat);
|
||||
|
@ -837,12 +917,14 @@ int ecryptfs_new_file_context(struct inode *ecryptfs_inode)
|
|||
"to the inode key sigs; rc = [%d]\n", rc);
|
||||
goto out;
|
||||
}
|
||||
cipher_name_len =
|
||||
strlen(mount_crypt_stat->global_default_cipher_name);
|
||||
memcpy(crypt_stat->cipher,
|
||||
strlcpy(crypt_stat->cipher,
|
||||
mount_crypt_stat->global_default_cipher_name,
|
||||
cipher_name_len);
|
||||
crypt_stat->cipher[cipher_name_len] = '\0';
|
||||
sizeof(crypt_stat->cipher));
|
||||
|
||||
strlcpy(crypt_stat->cipher_mode,
|
||||
mount_crypt_stat->global_default_cipher_mode,
|
||||
sizeof(crypt_stat->cipher_mode));
|
||||
|
||||
crypt_stat->key_size =
|
||||
mount_crypt_stat->global_default_cipher_key_size;
|
||||
ecryptfs_generate_new_key(crypt_stat);
|
||||
|
@ -971,7 +1053,8 @@ ecryptfs_cipher_code_str_map[] = {
|
|||
{"twofish", RFC2440_CIPHER_TWOFISH},
|
||||
{"cast6", RFC2440_CIPHER_CAST_6},
|
||||
{"aes", RFC2440_CIPHER_AES_192},
|
||||
{"aes", RFC2440_CIPHER_AES_256}
|
||||
{"aes", RFC2440_CIPHER_AES_256},
|
||||
{"aes_xts", RFC2440_CIPHER_AES_XTS_256}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -999,6 +1082,11 @@ u8 ecryptfs_code_for_cipher_string(char *cipher_name, size_t key_bytes)
|
|||
case 32:
|
||||
code = RFC2440_CIPHER_AES_256;
|
||||
}
|
||||
} else if (strcmp(cipher_name, "aes_xts") == 0) {
|
||||
switch (key_bytes) {
|
||||
case 32:
|
||||
code = RFC2440_CIPHER_AES_XTS_256;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_SIZE(ecryptfs_cipher_code_str_map); i++)
|
||||
if (strcmp(cipher_name, map[i].cipher_str) == 0) {
|
||||
|
@ -1038,9 +1126,24 @@ int ecryptfs_read_and_validate_header_region(struct inode *inode)
|
|||
u8 file_size[ECRYPTFS_SIZE_AND_MARKER_BYTES];
|
||||
u8 *marker = file_size + ECRYPTFS_FILE_SIZE_BYTES;
|
||||
int rc;
|
||||
unsigned int ra_pages_org;
|
||||
struct file *lower_file = NULL;
|
||||
|
||||
if (!inode)
|
||||
return -EIO;
|
||||
lower_file = ecryptfs_inode_to_private(inode)->lower_file;
|
||||
if (!lower_file)
|
||||
return -EIO;
|
||||
|
||||
/*disable read a head mechanism for a while */
|
||||
ra_pages_org = lower_file->f_ra.ra_pages;
|
||||
lower_file->f_ra.ra_pages = 0;
|
||||
|
||||
rc = ecryptfs_read_lower(file_size, 0, ECRYPTFS_SIZE_AND_MARKER_BYTES,
|
||||
inode);
|
||||
lower_file->f_ra.ra_pages = ra_pages_org;
|
||||
/* restore read a head mechanism */
|
||||
|
||||
if (rc < ECRYPTFS_SIZE_AND_MARKER_BYTES)
|
||||
return rc >= 0 ? -EINVAL : rc;
|
||||
rc = ecryptfs_validate_marker(marker);
|
||||
|
@ -1430,6 +1533,11 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
|
|||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
|
||||
&ecryptfs_superblock_to_private(
|
||||
ecryptfs_dentry->d_sb)->mount_crypt_stat;
|
||||
unsigned int ra_pages_org;
|
||||
struct file *lower_file =
|
||||
ecryptfs_inode_to_private(ecryptfs_inode)->lower_file;
|
||||
if (!lower_file)
|
||||
return -EIO;
|
||||
|
||||
ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat,
|
||||
mount_crypt_stat);
|
||||
|
@ -1441,8 +1549,14 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
|
|||
__func__);
|
||||
goto out;
|
||||
}
|
||||
/*disable read a head mechanism */
|
||||
ra_pages_org = lower_file->f_ra.ra_pages;
|
||||
lower_file->f_ra.ra_pages = 0;
|
||||
|
||||
rc = ecryptfs_read_lower(page_virt, 0, crypt_stat->extent_size,
|
||||
ecryptfs_inode);
|
||||
lower_file->f_ra.ra_pages = ra_pages_org; /* restore it back */
|
||||
|
||||
if (rc >= 0)
|
||||
rc = ecryptfs_read_headers_virt(page_virt, crypt_stat,
|
||||
ecryptfs_dentry,
|
||||
|
|
|
@ -244,6 +244,7 @@ struct ecryptfs_crypt_stat {
|
|||
struct mutex cs_tfm_mutex;
|
||||
struct mutex cs_hash_tfm_mutex;
|
||||
struct mutex cs_mutex;
|
||||
unsigned char cipher_mode[ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1];
|
||||
};
|
||||
|
||||
/* inode private data. */
|
||||
|
@ -344,6 +345,8 @@ struct ecryptfs_mount_crypt_stat {
|
|||
unsigned char global_default_fn_cipher_name[
|
||||
ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1];
|
||||
char global_default_fnek_sig[ECRYPTFS_SIG_SIZE_HEX + 1];
|
||||
unsigned char global_default_cipher_mode[ECRYPTFS_MAX_CIPHER_NAME_SIZE
|
||||
+ 1];
|
||||
};
|
||||
|
||||
/* superblock private data. */
|
||||
|
@ -526,6 +529,52 @@ ecryptfs_dentry_to_lower_path(struct dentry *dentry)
|
|||
return &((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a cipher and mode strings, the function
|
||||
* concatenates them to create a new string of
|
||||
* <cipher>_<mode> format.
|
||||
*/
|
||||
static inline char *ecryptfs_get_full_cipher(
|
||||
char *cipher, char *mode)
|
||||
{
|
||||
static char final[2*ECRYPTFS_MAX_CIPHER_NAME_SIZE+1];
|
||||
|
||||
if (strlen(mode) > 0) {
|
||||
memset(final, 0, sizeof(final));
|
||||
snprintf(final, sizeof(final), "%s_%s", cipher, mode);
|
||||
return final;
|
||||
}
|
||||
return cipher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a <cipher>[_<mode>] formatted string, the function
|
||||
* extracts cipher string and/or mode string.
|
||||
* Note: the passed cipher and/or mode strings will be null-terminated.
|
||||
*/
|
||||
static inline void ecryptfs_parse_full_cipher(
|
||||
char *s, char *cipher, char *mode)
|
||||
{
|
||||
char input[2*ECRYPTFS_MAX_CIPHER_NAME_SIZE+1+1];
|
||||
/* +1 for '_'; +1 for '\0' */
|
||||
char *p;
|
||||
char *input_p = input;
|
||||
|
||||
if (s == NULL || cipher == NULL)
|
||||
return;
|
||||
|
||||
memset(input, 0, sizeof(input));
|
||||
strlcpy(input, s, sizeof(input));
|
||||
|
||||
p = strsep(&input_p, "_");
|
||||
strlcpy(cipher, p, ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1);
|
||||
|
||||
|
||||
/* check if mode is specified */
|
||||
if (input_p != NULL && mode != NULL)
|
||||
strlcpy(mode, input_p, ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1);
|
||||
}
|
||||
|
||||
#define ecryptfs_printk(type, fmt, arg...) \
|
||||
__ecryptfs_printk(type "%s: " fmt, __func__, ## arg);
|
||||
__printf(1, 2)
|
||||
|
@ -717,4 +766,15 @@ int ecryptfs_set_f_namelen(long *namelen, long lower_namelen,
|
|||
int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
|
||||
loff_t offset);
|
||||
|
||||
void clean_inode_pages(struct address_space *mapping,
|
||||
pgoff_t start, pgoff_t end);
|
||||
|
||||
void ecryptfs_drop_pagecache_sb(struct super_block *sb, void *unused);
|
||||
|
||||
void ecryptfs_free_events(void);
|
||||
|
||||
void ecryptfs_freepage(struct page *page);
|
||||
|
||||
struct ecryptfs_events *get_events(void);
|
||||
|
||||
#endif /* #ifndef ECRYPTFS_KERNEL_H */
|
||||
|
|
212
fs/ecryptfs/events.c
Normal file
212
fs/ecryptfs/events.c
Normal file
|
@ -0,0 +1,212 @@
|
|||
/**
|
||||
* eCryptfs: Linux filesystem encryption layer
|
||||
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/string.h>
|
||||
#include <linux/ecryptfs.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/random.h>
|
||||
#include "ecryptfs_kernel.h"
|
||||
|
||||
static DEFINE_MUTEX(events_mutex);
|
||||
struct ecryptfs_events *events_ptr = NULL;
|
||||
static int handle;
|
||||
|
||||
void ecryptfs_free_events(void)
|
||||
{
|
||||
mutex_lock(&events_mutex);
|
||||
if (events_ptr != NULL) {
|
||||
kfree(events_ptr);
|
||||
events_ptr = NULL;
|
||||
}
|
||||
|
||||
mutex_unlock(&events_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register to ecryptfs events, by passing callback
|
||||
* functions to be called upon events occurence.
|
||||
* The function returns a handle to be passed
|
||||
* to unregister function.
|
||||
*/
|
||||
int ecryptfs_register_to_events(struct ecryptfs_events *ops)
|
||||
{
|
||||
int ret_value = 0;
|
||||
|
||||
if (!ops)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&events_mutex);
|
||||
|
||||
if (events_ptr != NULL) {
|
||||
ecryptfs_printk(KERN_ERR,
|
||||
"already registered!\n");
|
||||
ret_value = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
events_ptr =
|
||||
kzalloc(sizeof(struct ecryptfs_events), GFP_KERNEL);
|
||||
|
||||
if (!events_ptr) {
|
||||
ecryptfs_printk(KERN_ERR, "malloc failure\n");
|
||||
ret_value = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
/* copy the callbacks */
|
||||
events_ptr->open_cb = ops->open_cb;
|
||||
events_ptr->release_cb = ops->release_cb;
|
||||
events_ptr->encrypt_cb = ops->encrypt_cb;
|
||||
events_ptr->decrypt_cb = ops->decrypt_cb;
|
||||
events_ptr->is_cipher_supported_cb =
|
||||
ops->is_cipher_supported_cb;
|
||||
events_ptr->is_hw_crypt_cb = ops->is_hw_crypt_cb;
|
||||
|
||||
get_random_bytes(&handle, sizeof(handle));
|
||||
ret_value = handle;
|
||||
|
||||
out:
|
||||
mutex_unlock(&events_mutex);
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister from ecryptfs events.
|
||||
*/
|
||||
int ecryptfs_unregister_from_events(int user_handle)
|
||||
{
|
||||
int ret_value = 0;
|
||||
|
||||
mutex_lock(&events_mutex);
|
||||
|
||||
if (!events_ptr) {
|
||||
ret_value = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (user_handle != handle) {
|
||||
ret_value = ECRYPTFS_INVALID_EVENTS_HANDLE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
kfree(events_ptr);
|
||||
events_ptr = NULL;
|
||||
|
||||
out:
|
||||
mutex_unlock(&events_mutex);
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function decides whether the passed file offset
|
||||
* belongs to ecryptfs metadata or not.
|
||||
* The caller must pass ecryptfs data, which was received in one
|
||||
* of the callback invocations.
|
||||
*/
|
||||
bool ecryptfs_is_page_in_metadata(void *data, pgoff_t offset)
|
||||
{
|
||||
|
||||
struct ecryptfs_crypt_stat *stat = NULL;
|
||||
bool ret = true;
|
||||
|
||||
if (!data) {
|
||||
ecryptfs_printk(KERN_ERR, "ecryptfs_is_page_in_metadata: invalid data parameter\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
}
|
||||
stat = (struct ecryptfs_crypt_stat *)data;
|
||||
|
||||
if (stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
|
||||
ret = false;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (offset >= (stat->metadata_size/PAGE_CACHE_SIZE)) {
|
||||
ret = false;
|
||||
goto end;
|
||||
}
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given two ecryptfs data, the function
|
||||
* decides whether they are equal.
|
||||
*/
|
||||
inline bool ecryptfs_is_data_equal(void *data1, void *data2)
|
||||
{
|
||||
/* pointer comparison*/
|
||||
return data1 == data2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given ecryptfs data, the function
|
||||
* returns appropriate key size.
|
||||
*/
|
||||
size_t ecryptfs_get_key_size(void *data)
|
||||
{
|
||||
|
||||
struct ecryptfs_crypt_stat *stat = NULL;
|
||||
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
stat = (struct ecryptfs_crypt_stat *)data;
|
||||
return stat->key_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given ecryptfs data, the function
|
||||
* returns appropriate cipher.
|
||||
*/
|
||||
const unsigned char *ecryptfs_get_cipher(void *data)
|
||||
{
|
||||
|
||||
struct ecryptfs_crypt_stat *stat = NULL;
|
||||
|
||||
if (!data) {
|
||||
ecryptfs_printk(KERN_ERR,
|
||||
"ecryptfs_get_cipher: invalid data parameter\n");
|
||||
return NULL;
|
||||
}
|
||||
stat = (struct ecryptfs_crypt_stat *)data;
|
||||
return ecryptfs_get_full_cipher(stat->cipher, stat->cipher_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given ecryptfs data, the function
|
||||
* returns file encryption key.
|
||||
*/
|
||||
const unsigned char *ecryptfs_get_key(void *data)
|
||||
{
|
||||
|
||||
struct ecryptfs_crypt_stat *stat = NULL;
|
||||
|
||||
if (!data) {
|
||||
ecryptfs_printk(KERN_ERR,
|
||||
"ecryptfs_get_key: invalid data parameter\n");
|
||||
return NULL;
|
||||
}
|
||||
stat = (struct ecryptfs_crypt_stat *)data;
|
||||
return stat->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns ecryptfs events pointer
|
||||
*/
|
||||
inline struct ecryptfs_events *get_events(void)
|
||||
{
|
||||
return events_ptr;
|
||||
}
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/security.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/fs_stack.h>
|
||||
#include <linux/ecryptfs.h>
|
||||
#include "ecryptfs_kernel.h"
|
||||
|
||||
/**
|
||||
|
@ -184,6 +185,9 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
|
|||
int rc = 0;
|
||||
struct ecryptfs_crypt_stat *crypt_stat = NULL;
|
||||
struct dentry *ecryptfs_dentry = file->f_path.dentry;
|
||||
int ret;
|
||||
|
||||
|
||||
/* Private value of ecryptfs_dentry allocated in
|
||||
* ecryptfs_lookup() */
|
||||
struct ecryptfs_file_info *file_info;
|
||||
|
@ -231,12 +235,31 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
|
|||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = read_or_initialize_metadata(ecryptfs_dentry);
|
||||
if (rc)
|
||||
goto out_put;
|
||||
ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = "
|
||||
"[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino,
|
||||
(unsigned long long)i_size_read(inode));
|
||||
|
||||
if (get_events() && get_events()->open_cb) {
|
||||
|
||||
ret = vfs_fsync(file, false);
|
||||
|
||||
if (ret)
|
||||
ecryptfs_printk(KERN_ERR,
|
||||
"failed to sync file ret = %d.\n", ret);
|
||||
|
||||
get_events()->open_cb(ecryptfs_inode_to_lower(inode),
|
||||
crypt_stat);
|
||||
|
||||
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
|
||||
truncate_inode_pages(inode->i_mapping, 0);
|
||||
truncate_inode_pages(
|
||||
ecryptfs_inode_to_lower(inode)->i_mapping, 0);
|
||||
}
|
||||
}
|
||||
goto out;
|
||||
out_put:
|
||||
ecryptfs_put_lower_file(inode);
|
||||
|
@ -261,9 +284,24 @@ static int ecryptfs_flush(struct file *file, fl_owner_t td)
|
|||
|
||||
static int ecryptfs_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
|
||||
int ret;
|
||||
ret = vfs_fsync(file, false);
|
||||
|
||||
if (ret)
|
||||
pr_err("failed to sync file ret = %d.\n", ret);
|
||||
|
||||
if (get_events() && get_events()->release_cb)
|
||||
get_events()->release_cb(ecryptfs_inode_to_lower(inode));
|
||||
|
||||
ecryptfs_put_lower_file(inode);
|
||||
kmem_cache_free(ecryptfs_file_info_cache,
|
||||
ecryptfs_file_to_private(file));
|
||||
|
||||
clean_inode_pages(inode->i_mapping, 0, -1);
|
||||
clean_inode_pages(ecryptfs_inode_to_lower(inode)->i_mapping, 0, -1);
|
||||
truncate_inode_pages(inode->i_mapping, 0);
|
||||
truncate_inode_pages(ecryptfs_inode_to_lower(inode)->i_mapping, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -261,12 +261,15 @@ out:
|
|||
*
|
||||
* Returns zero on success; non-zero on error condition
|
||||
*/
|
||||
|
||||
|
||||
static int
|
||||
ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
|
||||
umode_t mode, bool excl)
|
||||
{
|
||||
struct inode *ecryptfs_inode;
|
||||
int rc;
|
||||
struct ecryptfs_crypt_stat *crypt_stat;
|
||||
|
||||
ecryptfs_inode = ecryptfs_do_create(directory_inode, ecryptfs_dentry,
|
||||
mode);
|
||||
|
@ -276,6 +279,7 @@ ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
|
|||
rc = PTR_ERR(ecryptfs_inode);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* At this point, a file exists on "disk"; we need to make sure
|
||||
* that this on disk file is prepared to be an ecryptfs file */
|
||||
rc = ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode);
|
||||
|
@ -288,6 +292,13 @@ ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
|
|||
goto out;
|
||||
}
|
||||
unlock_new_inode(ecryptfs_inode);
|
||||
|
||||
crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
|
||||
if (get_events() && get_events()->open_cb)
|
||||
get_events()->open_cb(
|
||||
ecryptfs_inode_to_lower(ecryptfs_inode),
|
||||
crypt_stat);
|
||||
|
||||
d_instantiate(ecryptfs_dentry, ecryptfs_inode);
|
||||
out:
|
||||
return rc;
|
||||
|
|
|
@ -918,6 +918,7 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
|
|||
struct ecryptfs_parse_tag_70_packet_silly_stack *s;
|
||||
struct key *auth_tok_key = NULL;
|
||||
int rc = 0;
|
||||
char full_cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE];
|
||||
|
||||
(*packet_size) = 0;
|
||||
(*filename_size) = 0;
|
||||
|
@ -977,12 +978,13 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
|
|||
s->fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX] = '\0';
|
||||
(*packet_size) += ECRYPTFS_SIG_SIZE;
|
||||
s->cipher_code = data[(*packet_size)++];
|
||||
rc = ecryptfs_cipher_code_to_string(s->cipher_string, s->cipher_code);
|
||||
rc = ecryptfs_cipher_code_to_string(full_cipher, s->cipher_code);
|
||||
if (rc) {
|
||||
printk(KERN_WARNING "%s: Cipher code [%d] is invalid\n",
|
||||
__func__, s->cipher_code);
|
||||
goto out;
|
||||
}
|
||||
ecryptfs_parse_full_cipher(full_cipher, s->cipher_string, 0);
|
||||
rc = ecryptfs_find_auth_tok_for_sig(&auth_tok_key,
|
||||
&s->auth_tok, mount_crypt_stat,
|
||||
s->fnek_sig_hex);
|
||||
|
@ -1151,6 +1153,7 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
|
|||
char *payload = NULL;
|
||||
size_t payload_len = 0;
|
||||
int rc;
|
||||
char full_cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE];
|
||||
|
||||
rc = ecryptfs_get_auth_tok_sig(&auth_tok_sig, auth_tok);
|
||||
if (rc) {
|
||||
|
@ -1188,12 +1191,15 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
|
|||
memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key,
|
||||
auth_tok->session_key.decrypted_key_size);
|
||||
crypt_stat->key_size = auth_tok->session_key.decrypted_key_size;
|
||||
rc = ecryptfs_cipher_code_to_string(crypt_stat->cipher, cipher_code);
|
||||
rc = ecryptfs_cipher_code_to_string(full_cipher, cipher_code);
|
||||
if (rc) {
|
||||
ecryptfs_printk(KERN_ERR, "Cipher code [%d] is invalid\n",
|
||||
cipher_code)
|
||||
goto out;
|
||||
}
|
||||
ecryptfs_parse_full_cipher(full_cipher,
|
||||
crypt_stat->cipher, crypt_stat->cipher_mode);
|
||||
|
||||
crypt_stat->flags |= ECRYPTFS_KEY_VALID;
|
||||
if (ecryptfs_verbosity > 0) {
|
||||
ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n");
|
||||
|
@ -1380,6 +1386,7 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
|
|||
struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
|
||||
size_t length_size;
|
||||
int rc = 0;
|
||||
char full_cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE];
|
||||
|
||||
(*packet_size) = 0;
|
||||
(*new_auth_tok) = NULL;
|
||||
|
@ -1453,10 +1460,13 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
|
|||
rc = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
rc = ecryptfs_cipher_code_to_string(crypt_stat->cipher,
|
||||
rc = ecryptfs_cipher_code_to_string(full_cipher,
|
||||
(u16)data[(*packet_size)]);
|
||||
if (rc)
|
||||
goto out_free;
|
||||
ecryptfs_parse_full_cipher(full_cipher,
|
||||
crypt_stat->cipher, crypt_stat->cipher_mode);
|
||||
|
||||
/* A little extra work to differentiate among the AES key
|
||||
* sizes; see RFC2440 */
|
||||
switch(data[(*packet_size)++]) {
|
||||
|
@ -1975,9 +1985,11 @@ pki_encrypt_session_key(struct key *auth_tok_key,
|
|||
|
||||
rc = write_tag_66_packet(auth_tok->token.private_key.signature,
|
||||
ecryptfs_code_for_cipher_string(
|
||||
crypt_stat->cipher,
|
||||
crypt_stat->key_size),
|
||||
crypt_stat, &payload, &payload_len);
|
||||
ecryptfs_get_full_cipher(
|
||||
crypt_stat->cipher,
|
||||
crypt_stat->cipher_mode),
|
||||
crypt_stat->key_size),
|
||||
crypt_stat, &payload, &payload_len);
|
||||
up_write(&(auth_tok_key->sem));
|
||||
key_put(auth_tok_key);
|
||||
if (rc) {
|
||||
|
@ -2343,8 +2355,10 @@ encrypted_session_key_set:
|
|||
dest[(*packet_size)++] = 0x04; /* version 4 */
|
||||
/* TODO: Break from RFC2440 so that arbitrary ciphers can be
|
||||
* specified with strings */
|
||||
cipher_code = ecryptfs_code_for_cipher_string(crypt_stat->cipher,
|
||||
crypt_stat->key_size);
|
||||
cipher_code = ecryptfs_code_for_cipher_string(
|
||||
ecryptfs_get_full_cipher(crypt_stat->cipher,
|
||||
crypt_stat->cipher_mode),
|
||||
crypt_stat->key_size);
|
||||
if (cipher_code == 0) {
|
||||
ecryptfs_printk(KERN_WARNING, "Unable to generate code for "
|
||||
"cipher [%s]\n", crypt_stat->cipher);
|
||||
|
|
|
@ -309,12 +309,14 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options,
|
|||
case ecryptfs_opt_ecryptfs_cipher:
|
||||
cipher_name_src = args[0].from;
|
||||
cipher_name_dst =
|
||||
mount_crypt_stat->
|
||||
global_default_cipher_name;
|
||||
strncpy(cipher_name_dst, cipher_name_src,
|
||||
ECRYPTFS_MAX_CIPHER_NAME_SIZE);
|
||||
cipher_name_dst[ECRYPTFS_MAX_CIPHER_NAME_SIZE] = '\0';
|
||||
mount_crypt_stat->global_default_cipher_name;
|
||||
|
||||
ecryptfs_parse_full_cipher(cipher_name_src,
|
||||
mount_crypt_stat->global_default_cipher_name,
|
||||
mount_crypt_stat->global_default_cipher_mode);
|
||||
|
||||
cipher_name_set = 1;
|
||||
|
||||
break;
|
||||
case ecryptfs_opt_ecryptfs_key_bytes:
|
||||
cipher_key_bytes_src = args[0].from;
|
||||
|
@ -411,6 +413,7 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options,
|
|||
strcpy(mount_crypt_stat->global_default_cipher_name,
|
||||
ECRYPTFS_DEFAULT_CIPHER);
|
||||
}
|
||||
|
||||
if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)
|
||||
&& !fn_cipher_name_set)
|
||||
strcpy(mount_crypt_stat->global_default_fn_cipher_name,
|
||||
|
@ -423,12 +426,18 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options,
|
|||
mount_crypt_stat->global_default_cipher_key_size;
|
||||
|
||||
cipher_code = ecryptfs_code_for_cipher_string(
|
||||
mount_crypt_stat->global_default_cipher_name,
|
||||
ecryptfs_get_full_cipher(
|
||||
mount_crypt_stat->global_default_cipher_name,
|
||||
mount_crypt_stat->global_default_cipher_mode),
|
||||
mount_crypt_stat->global_default_cipher_key_size);
|
||||
if (!cipher_code) {
|
||||
ecryptfs_printk(KERN_ERR,
|
||||
"eCryptfs doesn't support cipher: %s",
|
||||
mount_crypt_stat->global_default_cipher_name);
|
||||
ecryptfs_printk(
|
||||
KERN_ERR,
|
||||
"eCryptfs doesn't support cipher: %s and key size %lu",
|
||||
ecryptfs_get_full_cipher(
|
||||
mount_crypt_stat->global_default_cipher_name,
|
||||
mount_crypt_stat->global_default_cipher_mode),
|
||||
mount_crypt_stat->global_default_cipher_key_size);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -488,6 +497,7 @@ static struct file_system_type ecryptfs_fs_type;
|
|||
* @dev_name: The path to mount over
|
||||
* @raw_data: The options passed into the kernel
|
||||
*/
|
||||
|
||||
static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags,
|
||||
const char *dev_name, void *raw_data)
|
||||
{
|
||||
|
@ -557,6 +567,8 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
|
|||
|
||||
ecryptfs_set_superblock_lower(s, path.dentry->d_sb);
|
||||
|
||||
ecryptfs_drop_pagecache_sb(ecryptfs_superblock_to_lower(s), 0);
|
||||
|
||||
/**
|
||||
* Set the POSIX ACL flag based on whether they're enabled in the lower
|
||||
* mount.
|
||||
|
@ -895,6 +907,7 @@ static void __exit ecryptfs_exit(void)
|
|||
do_sysfs_unregistration();
|
||||
unregister_filesystem(&ecryptfs_fs_type);
|
||||
ecryptfs_free_kmem_caches();
|
||||
ecryptfs_free_events();
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Michael A. Halcrow <mhalcrow@us.ibm.com>");
|
||||
|
|
|
@ -552,10 +552,16 @@ static sector_t ecryptfs_bmap(struct address_space *mapping, sector_t block)
|
|||
return rc;
|
||||
}
|
||||
|
||||
void ecryptfs_freepage(struct page *page)
|
||||
{
|
||||
zero_user(page, 0, PAGE_CACHE_SIZE);
|
||||
}
|
||||
|
||||
const struct address_space_operations ecryptfs_aops = {
|
||||
.writepage = ecryptfs_writepage,
|
||||
.readpage = ecryptfs_readpage,
|
||||
.write_begin = ecryptfs_write_begin,
|
||||
.write_end = ecryptfs_write_end,
|
||||
.bmap = ecryptfs_bmap,
|
||||
.freepage = ecryptfs_freepage,
|
||||
};
|
||||
|
|
|
@ -69,6 +69,9 @@ static void ecryptfs_i_callback(struct rcu_head *head)
|
|||
{
|
||||
struct inode *inode = container_of(head, struct inode, i_rcu);
|
||||
struct ecryptfs_inode_info *inode_info;
|
||||
if (inode == NULL)
|
||||
return;
|
||||
|
||||
inode_info = ecryptfs_inode_to_private(inode);
|
||||
|
||||
kmem_cache_free(ecryptfs_inode_info_cache, inode_info);
|
||||
|
@ -88,9 +91,12 @@ static void ecryptfs_destroy_inode(struct inode *inode)
|
|||
struct ecryptfs_inode_info *inode_info;
|
||||
|
||||
inode_info = ecryptfs_inode_to_private(inode);
|
||||
|
||||
BUG_ON(inode_info->lower_file);
|
||||
|
||||
ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat);
|
||||
call_rcu(&inode->i_rcu, ecryptfs_i_callback);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -162,7 +168,9 @@ static int ecryptfs_show_options(struct seq_file *m, struct dentry *root)
|
|||
mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
|
||||
|
||||
seq_printf(m, ",ecryptfs_cipher=%s",
|
||||
mount_crypt_stat->global_default_cipher_name);
|
||||
ecryptfs_get_full_cipher(
|
||||
mount_crypt_stat->global_default_cipher_name,
|
||||
mount_crypt_stat->global_default_cipher_mode));
|
||||
|
||||
if (mount_crypt_stat->global_default_cipher_key_size)
|
||||
seq_printf(m, ",ecryptfs_key_bytes=%zd",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#ifndef _LINUX_ECRYPTFS_H
|
||||
#define _LINUX_ECRYPTFS_H
|
||||
|
||||
struct inode;
|
||||
struct page;
|
||||
|
||||
/* Version verification for shared data structures w/ userspace */
|
||||
#define ECRYPTFS_VERSION_MAJOR 0x00
|
||||
#define ECRYPTFS_VERSION_MINOR 0x04
|
||||
|
@ -41,6 +44,7 @@
|
|||
#define RFC2440_CIPHER_AES_256 0x09
|
||||
#define RFC2440_CIPHER_TWOFISH 0x0a
|
||||
#define RFC2440_CIPHER_CAST_6 0x0b
|
||||
#define RFC2440_CIPHER_AES_XTS_256 0x0c
|
||||
|
||||
#define RFC2440_CIPHER_RSA 0x01
|
||||
|
||||
|
@ -102,4 +106,42 @@ struct ecryptfs_auth_tok {
|
|||
} token;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define ECRYPTFS_INVALID_EVENTS_HANDLE -1
|
||||
|
||||
/**
|
||||
* ecryptfs_events struct represents a partial interface
|
||||
* towards ecryptfs module. If registered to ecryptfs events,
|
||||
* one can receive push notifications.
|
||||
* A first callback received from ecryptfs will probably be
|
||||
* about file opening (open_cb),
|
||||
* in which ecryptfs passes its ecryptfs_data for future usage.
|
||||
* This data represents a file and must be passed in every query functions
|
||||
* such as ecryptfs_get_key_size(), ecryptfs_get_cipher() etc.
|
||||
*/
|
||||
struct ecryptfs_events {
|
||||
bool (*is_cipher_supported_cb)(char *cipher);
|
||||
void (*open_cb)(struct inode *inode, void *ecrytpfs_data);
|
||||
void (*release_cb)(struct inode *inode);
|
||||
int (*encrypt_cb)(struct page *in_page, struct page *out_page,
|
||||
struct inode *inode, unsigned long extent_offset);
|
||||
int (*decrypt_cb)(struct page *in_page, struct page *out_page,
|
||||
struct inode *inode, unsigned long extent_offset);
|
||||
bool (*is_hw_crypt_cb)(void);
|
||||
};
|
||||
|
||||
|
||||
int ecryptfs_register_to_events(struct ecryptfs_events *ops);
|
||||
|
||||
int ecryptfs_unregister_from_events(int user_handle);
|
||||
|
||||
const unsigned char *ecryptfs_get_key(void *ecrytpfs_data);
|
||||
|
||||
size_t ecryptfs_get_key_size(void *ecrytpfs_data);
|
||||
|
||||
const unsigned char *ecryptfs_get_cipher(void *ecrytpfs_data);
|
||||
|
||||
bool ecryptfs_is_page_in_metadata(void *ecrytpfs_data, pgoff_t offset);
|
||||
|
||||
bool ecryptfs_is_data_equal(void *ecrytpfs_data1, void *ecrytpfs_data2);
|
||||
|
||||
#endif /* _LINUX_ECRYPTFS_H */
|
||||
|
|
Loading…
Add table
Reference in a new issue