misc: Remove Samsung Secure Data Protection sprinkles

* Will make upstream merges easier

Change-Id: Ie0a5028235996f2bf233dc50489c1a9804b294de
Signed-off-by: Kevin F. Haggerty <haggertk@lineageos.org>
This commit is contained in:
Kevin F. Haggerty 2017-05-17 22:11:03 -06:00 committed by Francescodario Cuzzocrea
parent ed185d55e9
commit 16d4fbdb9f
45 changed files with 1 additions and 5919 deletions

View File

@ -28,17 +28,6 @@ config ECRYPT_FS_VIRTUAL_FAT_XATTR
help
Modification of encrypted filesystem for virtual FAT xattr
config SDP
bool "Enables SDP"
default n
depends on ECRYPT_FS
help
Sensitive Data Protection
config SDP_KEY_DUMP
bool "SDP KEY DUMP"
default n
config FORCE_DISABLE_FIPS
bool "Force disable FIPS config"
default n

View File

@ -7,6 +7,5 @@ EXTRA_CFLAGS += -DECRYPT_FS_VIRTUAL_FAT_XATTR
endif
obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
obj-$(CONFIG_SDP) += ecryptfs_dek.o mm.o ecryptfs_sdp_chamber.o
ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o miscdev.o kthread.o debug.o

View File

@ -42,10 +42,6 @@
#define SEED_LEN 32
#endif
#ifdef CONFIG_SDP
#include "ecryptfs_dek.h"
#endif
static int
ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
struct page *dst_page, int dst_offset,
@ -515,12 +511,10 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
BUG_ON(!crypt_stat || !crypt_stat->tfm
|| !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED));
if (unlikely(ecryptfs_verbosity > 0)) {
#ifndef CONFIG_SDP
ecryptfs_printk(KERN_DEBUG, "Key size [%zd]; key:\n",
crypt_stat->key_size);
ecryptfs_dump_hex(crypt_stat->key,
crypt_stat->key_size);
#endif
}
/* Consider doing this once, when the file is opened */
mutex_lock(&crypt_stat->cs_tfm_mutex);
@ -632,31 +626,6 @@ int ecryptfs_encrypt_page(struct page *page)
crypt_stat =
&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
#ifdef CONFIG_SDP
if (!(crypt_stat->flags & ECRYPTFS_KEY_SET) ||
!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
if((crypt_stat->flags & ECRYPTFS_DEK_SDP_ENABLED) &&
(crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE)) {
rc = ecryptfs_get_sdp_dek(crypt_stat);
if (rc) {
ecryptfs_printk(KERN_ERR, "%s Get SDP key failed\n", __func__);
goto out;
}
rc = ecryptfs_compute_root_iv(crypt_stat);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error computing "
"the root IV\n");
goto out;
}
}
}
#if ECRYPTFS_DEK_DEBUG
ecryptfs_printk(KERN_ERR, "\tKEY [%zd]:\n", crypt_stat->key_size);
ecryptfs_dump_hex(crypt_stat->key, crypt_stat->key_size);
ecryptfs_printk(KERN_ERR, "\tIV [%zd]:\n", ECRYPTFS_MAX_IV_BYTES);
ecryptfs_dump_hex(crypt_stat->root_iv, ECRYPTFS_MAX_IV_BYTES);
#endif
#endif
enc_extent_page = alloc_page(GFP_USER);
if (!enc_extent_page) {
rc = -ENOMEM;
@ -765,31 +734,6 @@ int ecryptfs_decrypt_page(struct page *page)
crypt_stat =
&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
#ifdef CONFIG_SDP
if (!(crypt_stat->flags & ECRYPTFS_KEY_SET) ||
!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
if((crypt_stat->flags & ECRYPTFS_DEK_SDP_ENABLED) &&
(crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE)) {
rc = ecryptfs_get_sdp_dek(crypt_stat);
if (rc) {
ecryptfs_printk(KERN_ERR, "%s Get SDP key failed\n", __func__);
goto out;
}
rc = ecryptfs_compute_root_iv(crypt_stat);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error computing "
"the root IV\n");
goto out;
}
}
}
#if ECRYPTFS_DEK_DEBUG
ecryptfs_printk(KERN_ERR, "\tKEY [%zd]:\n", crypt_stat->key_size);
ecryptfs_dump_hex(crypt_stat->key, crypt_stat->key_size);
ecryptfs_printk(KERN_ERR, "\tIV [%zd]:\n", ECRYPTFS_MAX_IV_BYTES);
ecryptfs_dump_hex(crypt_stat->root_iv, ECRYPTFS_MAX_IV_BYTES);
#endif
#endif
enc_extent_page = alloc_page(GFP_USER);
if (!enc_extent_page) {
rc = -ENOMEM;
@ -1111,11 +1055,6 @@ static void ecryptfs_copy_mount_wide_flags_to_inode_flags(
& ECRYPTFS_GLOBAL_ENCFN_USE_FEK)
crypt_stat->flags |= ECRYPTFS_ENCFN_USE_FEK;
}
#ifdef CONFIG_SDP
if (mount_crypt_stat->flags & ECRYPTFS_MOUNT_SDP_ENABLED)
crypt_stat->flags |= ECRYPTFS_DEK_SDP_ENABLED;
#endif
}
static int ecryptfs_copy_mount_wide_sigs_to_inode_sigs(
@ -1165,9 +1104,6 @@ static void ecryptfs_set_default_crypt_stat_vals(
crypt_stat->flags &= ~(ECRYPTFS_KEY_VALID);
crypt_stat->file_version = ECRYPTFS_FILE_VERSION;
crypt_stat->mount_crypt_stat = mount_crypt_stat;
#ifdef CONFIG_SDP
crypt_stat->engine_id = -1;
#endif
}
/**
@ -1260,14 +1196,7 @@ static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = {
{0x00000001, ECRYPTFS_ENABLE_HMAC},
{0x00000002, ECRYPTFS_ENCRYPTED},
{0x00000004, ECRYPTFS_METADATA_IN_XATTR},
#ifdef CONFIG_SDP
{0x00000008, ECRYPTFS_ENCRYPT_FILENAMES},
{0x00100000, ECRYPTFS_DEK_SDP_ENABLED},
{0x00200000, ECRYPTFS_DEK_IS_SENSITIVE},
{0x00400000, ECRYPTFS_DEK_MULTI_ENGINE},
#else
{0x00000008, ECRYPTFS_ENCRYPT_FILENAMES},
#endif
};
/**
@ -1587,18 +1516,6 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
rc = -EINVAL;
goto out;
}
#ifdef CONFIG_SDP
#if ECRYPTFS_DEK_DEBUG
ecryptfs_printk(KERN_INFO, "name is [%s], flag is %d\n",
ecryptfs_dentry->d_name.name, crypt_stat->flags);
if (crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
ecryptfs_printk(KERN_INFO, "is sensitive\n");
}
else{
ecryptfs_printk(KERN_INFO, "is protected\n");
}
#endif
#endif
virt_len = crypt_stat->metadata_size;
order = get_order(virt_len);
/* Released in this function */
@ -1842,14 +1759,6 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
rc = ecryptfs_read_headers_virt(page_virt, crypt_stat,
ecryptfs_dentry,
ECRYPTFS_VALIDATE_HEADER_SIZE);
#ifdef CONFIG_SDP
if ((rc) && crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE)
/*
* metadata is not in the file header, SDP sensitive file.
* Don't check xattr region. we don't put info there.
*/
goto out;
#endif
if (rc) {
/* metadata is not in the file header, so try xattrs */
memset(page_virt, 0, PAGE_CACHE_SIZE);
@ -1884,24 +1793,6 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
}
}
#ifdef CONFIG_SDP
#if ECRYPTFS_DEK_DEBUG
ecryptfs_printk(KERN_INFO, "name is [%s], flag is %d\n",
ecryptfs_dentry->d_name.name, crypt_stat->flags);
if (crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
ecryptfs_printk(KERN_INFO, "dek_file_type is sensitive, enc type=%d\n",
crypt_stat->sdp_dek.type);
if (ecryptfs_is_persona_locked(crypt_stat->engine_id)) {
ecryptfs_printk(KERN_INFO, "persona is locked, rc=%d\n", rc);
} else {
ecryptfs_printk(KERN_INFO, "persona is unlocked, rc=%d\n", rc);
}
} else {
ecryptfs_printk(KERN_INFO, "dek_file_type is protected\n");
}
#endif
#endif
out:
if (page_virt) {
memset(page_virt, 0, PAGE_CACHE_SIZE);

View File

@ -95,7 +95,6 @@ void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok)
*
* Dump hexadecimal representation of char array
*/
#ifndef CONFIG_SDP
void ecryptfs_dump_hex(char *data, int bytes)
{
int i = 0;
@ -119,8 +118,3 @@ void ecryptfs_dump_hex(char *data, int bytes)
if (add_newline)
printk("\n");
}
#else
void ecryptfs_dump_hex(char *data, int bytes)
{
}
#endif

View File

@ -1,781 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <linux/pagemap.h>
#include <linux/crypto.h>
#include <asm/unaligned.h>
#include <sdp/fs_handler.h>
#include "ecryptfs_dek.h"
#include "ecryptfs_sdp_chamber.h"
#include "mm.h"
extern int dek_encrypt_dek_efs(int engine_id, dek_t *plainDek, dek_t *encDek);
extern int dek_decrypt_dek_efs(int engine_id, dek_t *encDek, dek_t *plainDek);
extern int dek_is_locked(int engine_id);
static int ecryptfs_update_crypt_flag(struct dentry *dentry, enum sdp_op operation);
static const char* get_op_name(enum sdp_op operation) {
switch (operation)
{
case TO_SENSITIVE: return "TO_SENSITIVE";
case TO_PROTECTED: return "TO_PROTECTED";
default: return "OP_UNKNOWN";
}
}
static int ecryptfs_set_key(struct ecryptfs_crypt_stat *crypt_stat) {
int rc = 0;
mutex_lock(&crypt_stat->cs_tfm_mutex);
if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) {
rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
crypt_stat->key_size);
if (rc) {
ecryptfs_printk(KERN_ERR,
"Error setting key; rc = [%d]\n",
rc);
rc = -EINVAL;
goto out;
}
crypt_stat->flags |= ECRYPTFS_KEY_SET;
crypt_stat->flags |= ECRYPTFS_KEY_VALID;
}
out:
mutex_unlock(&crypt_stat->cs_tfm_mutex);
return rc;
}
int ecryptfs_is_sdp_locked(int engine_id)
{
if(engine_id < 0) {
DEK_LOGE("invalid engine_id[%d]\n", engine_id);
return 0;
}
return dek_is_locked(engine_id);
}
extern int32_t sdp_mm_set_process_sensitive(unsigned int proc_id);
#define PSEUDO_KEY_LEN 32
const char pseudo_key[PSEUDO_KEY_LEN] = {
// PSEUDOSDP
0x50, 0x53, 0x55, 0x45, 0x44, 0x4f, 0x53, 0x44,
0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
void ecryptfs_clean_sdp_dek(struct ecryptfs_crypt_stat *crypt_stat)
{
int rc = 0;
printk("%s()\n", __func__);
if(crypt_stat->tfm) {
mutex_lock(&crypt_stat->cs_tfm_mutex);
rc = crypto_blkcipher_setkey(crypt_stat->tfm, pseudo_key,
PSEUDO_KEY_LEN);
if (rc) {
ecryptfs_printk(KERN_ERR,
"Error cleaning tfm rc = [%d]\n",
rc);
}
mutex_unlock(&crypt_stat->cs_tfm_mutex);
}
memset(crypt_stat->key, 0, ECRYPTFS_MAX_KEY_BYTES);
crypt_stat->flags &= ~(ECRYPTFS_KEY_SET);
crypt_stat->flags &= ~(ECRYPTFS_KEY_VALID);
}
int ecryptfs_get_sdp_dek(struct ecryptfs_crypt_stat *crypt_stat)
{
int rc = 0;
if(crypt_stat->flags & ECRYPTFS_KEY_SET) {
DEK_LOGE("get_sdp_dek: key is already set (success)\n");
return 0;
}
if(crypt_stat->flags & ECRYPTFS_DEK_SDP_ENABLED) {
if(crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
dek_t DEK;
if(crypt_stat->engine_id < 0) {
DEK_LOGE("get_sdp_dek: invalid engine-id"
"(ECRYPTFS_DEK_IS_SENSITIVE:ON, engine_id:%d)\n", crypt_stat->engine_id);
goto out;
}
memset(crypt_stat->key, 0, ECRYPTFS_MAX_KEY_BYTES);
if (crypt_stat->sdp_dek.type != DEK_TYPE_PLAIN) {
rc = dek_decrypt_dek_efs(crypt_stat->engine_id, &crypt_stat->sdp_dek, &DEK);
} else {
DEK_LOGE("DEK already plaintext, skip decryption");
rc = 0;
goto out;
}
if (rc < 0) {
DEK_LOGE("Error decypting dek; rc = [%d]\n", rc);
memset(&DEK, 0, sizeof(dek_t));
goto out;
}
memcpy(crypt_stat->key, DEK.buf, DEK.len);
crypt_stat->key_size = DEK.len;
memset(&DEK, 0, sizeof(dek_t));
} else {
#if ECRYPTFS_DEK_DEBUG
DEK_LOGD("file is not sensitive\n");
#endif
}
}
out:
/*
* Succeeded
*/
if(!rc) {
sdp_mm_set_process_sensitive(current->pid);
rc = ecryptfs_set_key(crypt_stat);
} else {
/*
* Error
*/
ecryptfs_clean_sdp_dek(crypt_stat);
}
return rc;
}
int write_dek_packet(char *dest,
struct ecryptfs_crypt_stat *crypt_stat,
size_t *written) {
*written = 0;
dest[(*written)++] = ECRYPTFS_DEK_PACKET_TYPE;
memset(dest + *written, 0, PKG_NAME_SIZE);
memcpy(dest + *written, current->comm, PKG_NAME_SIZE);
(*written) += PKG_NAME_SIZE;
put_unaligned_be32(current_euid(), dest + *written);
(*written) += 4;
memset(dest + *written, 0, DEK_MAXLEN);
if (crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
if(crypt_stat->flags & ECRYPTFS_DEK_MULTI_ENGINE) {
put_unaligned_be32(crypt_stat->engine_id, dest + *written);
(*written) += 4;
}
put_unaligned_be32(crypt_stat->sdp_dek.type, dest + *written);
(*written) += 4;
put_unaligned_be32(crypt_stat->sdp_dek.len, dest + *written);
(*written) += 4;
memcpy(dest + *written, crypt_stat->sdp_dek.buf, crypt_stat->sdp_dek.len);
(*written) += crypt_stat->sdp_dek.len;
}
return 0;
}
int parse_dek_packet(char *data,
struct ecryptfs_crypt_stat *crypt_stat,
size_t *packet_size) {
int rc = 0;
char temp_comm[PKG_NAME_SIZE]; //test
int temp_euid;
int sdp_dek_type;
int sdp_dek_len;
if (crypt_stat->file_version == 0)
return -EPERM;
(*packet_size) = 0;
if (data[(*packet_size)++] != ECRYPTFS_DEK_PACKET_TYPE) {
DEK_LOGE("First byte != 0x%.2x; invalid packet\n",
ECRYPTFS_DEK_PACKET_TYPE);
rc = -EINVAL;
}
memcpy(temp_comm, &data[*packet_size], PKG_NAME_SIZE);
(*packet_size) += PKG_NAME_SIZE;
temp_euid = get_unaligned_be32(data + *packet_size);
(*packet_size) += 4;
if (crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
if(crypt_stat->flags & ECRYPTFS_DEK_MULTI_ENGINE) {
crypt_stat->engine_id = get_unaligned_be32(data + *packet_size);
(*packet_size) += 4;
} else {
/**
* If eCryptfs header doesn't have engine-id,
* we assign it from mount_crypt_stat->userid
* (Fils created in old version)
*/
crypt_stat->engine_id = crypt_stat->mount_crypt_stat->userid;
}
sdp_dek_type = get_unaligned_be32(data + *packet_size);
if(sdp_dek_type < 0 || sdp_dek_type > 6)
return -EINVAL;
crypt_stat->sdp_dek.type = sdp_dek_type;
(*packet_size) += 4;
sdp_dek_len = get_unaligned_be32(data + *packet_size);
if(sdp_dek_len <= 0 || sdp_dek_len > DEK_MAXLEN)
return -EFAULT;
crypt_stat->sdp_dek.len = sdp_dek_len;
(*packet_size) += 4;
memcpy(crypt_stat->sdp_dek.buf, &data[*packet_size], crypt_stat->sdp_dek.len);
(*packet_size) += crypt_stat->sdp_dek.len;
}
#if ECRYPTFS_DEK_DEBUG
DEK_LOGD("%s() : comm : %s [euid:%d]\n",
__func__, temp_comm, temp_euid);
#endif
return rc;
}
static int ecryptfs_dek_copy_mount_wide_sigs_to_inode_sigs(
struct ecryptfs_crypt_stat *crypt_stat,
struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
{
struct ecryptfs_global_auth_tok *global_auth_tok;
int rc = 0;
mutex_lock(&crypt_stat->keysig_list_mutex);
mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
list_for_each_entry(global_auth_tok,
&mount_crypt_stat->global_auth_tok_list,
mount_crypt_stat_list) {
if (global_auth_tok->flags & ECRYPTFS_AUTH_TOK_FNEK)
continue;
rc = ecryptfs_add_keysig(crypt_stat, global_auth_tok->sig);
if (rc) {
printk(KERN_ERR "Error adding keysig; rc = [%d]\n", rc);
goto out;
}
}
out:
mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
mutex_unlock(&crypt_stat->keysig_list_mutex);
return rc;
}
#if defined(CONFIG_MMC_DW_FMP_ECRYPT_FS) || defined(CONFIG_UFS_FMP_ECRYPT_FS)
static void ecryptfs_propagate_flag(struct file *file, int userid, enum sdp_op operation) {
struct file *f = file;
do {
if(!f)
return ;
DEK_LOGD("%s file: %p [%s]\n",__func__, f, f->f_inode->i_sb->s_type->name);
if (operation == TO_SENSITIVE) {
mapping_set_sensitive(f->f_mapping);
} else {
mapping_clear_sensitive(f->f_mapping);
}
f->f_mapping->userid = userid;
} while (f->f_op->get_lower_file && (f = f->f_op->get_lower_file(f)));
}
#endif
void ecryptfs_set_mapping_sensitive(struct inode *ecryptfs_inode, int userid, enum sdp_op operation) {
#if defined(CONFIG_MMC_DW_FMP_ECRYPT_FS) || defined(CONFIG_UFS_FMP_ECRYPT_FS)
struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL;
struct ecryptfs_inode_info *inode_info;
inode_info = ecryptfs_inode_to_private(ecryptfs_inode);
DEK_LOGD("%s inode: %p lower_file_count: %d\n",__func__, ecryptfs_inode,atomic_read(&inode_info->lower_file_count));
mount_crypt_stat = &ecryptfs_superblock_to_private(ecryptfs_inode->i_sb)->mount_crypt_stat;
if (operation == TO_SENSITIVE) {
mapping_set_sensitive(ecryptfs_inode->i_mapping);
} else {
mapping_clear_sensitive(ecryptfs_inode->i_mapping);
}
ecryptfs_inode->i_mapping->userid = userid;
/*
* If FMP is in use, need to set flag to lower filesystems too recursively
*/
if (mount_crypt_stat->flags & ECRYPTFS_USE_FMP) {
if(inode_info->lower_file) {
ecryptfs_propagate_flag(inode_info->lower_file, userid, operation);
}
}
#else
if (operation == TO_SENSITIVE) {
mapping_set_sensitive(ecryptfs_inode->i_mapping);
} else {
mapping_clear_sensitive(ecryptfs_inode->i_mapping);
}
ecryptfs_inode->i_mapping->userid = userid;
#endif
}
/*
* set sensitive flag, update metadata
* Set cached inode pages to sensitive
*/
static int ecryptfs_update_crypt_flag(struct dentry *dentry, enum sdp_op operation)
{
int rc = 0;
struct inode *inode;
struct inode *lower_inode;
struct ecryptfs_crypt_stat *crypt_stat;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
u32 tmp_flags;
DEK_LOGE("%s(operation:%s) entered\n", __func__, get_op_name(operation));
crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
mount_crypt_stat = &ecryptfs_superblock_to_private(dentry->d_sb)->mount_crypt_stat;
if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED))
ecryptfs_init_crypt_stat(crypt_stat);
inode = dentry->d_inode;
lower_inode = ecryptfs_inode_to_lower(inode);
/*
* To update metadata we need to make sure keysig_list contains fekek.
* Because our EDEK is stored along with key for protected file.
*/
if(list_empty(&crypt_stat->keysig_list))
ecryptfs_dek_copy_mount_wide_sigs_to_inode_sigs(crypt_stat, mount_crypt_stat);
mutex_lock(&crypt_stat->cs_mutex);
rc = ecryptfs_get_lower_file(dentry, inode);
if (rc) {
mutex_unlock(&crypt_stat->cs_mutex);
DEK_LOGE("ecryptfs_get_lower_file rc=%d\n", rc);
return rc;
}
tmp_flags = crypt_stat->flags;
if (operation == TO_SENSITIVE) {
crypt_stat->flags |= ECRYPTFS_DEK_IS_SENSITIVE;
crypt_stat->flags |= ECRYPTFS_DEK_MULTI_ENGINE;
/*
* Set sensitive to inode mapping
*/
ecryptfs_set_mapping_sensitive(inode, mount_crypt_stat->userid, TO_SENSITIVE);
} else {
crypt_stat->flags &= ~ECRYPTFS_DEK_IS_SENSITIVE;
crypt_stat->flags &= ~ECRYPTFS_DEK_MULTI_ENGINE;
/*
* Set protected to inode mapping
*/
ecryptfs_set_mapping_sensitive(inode, mount_crypt_stat->userid, TO_PROTECTED);
}
rc = ecryptfs_write_metadata(dentry, inode);
if (rc) {
crypt_stat->flags = tmp_flags;
DEK_LOGE("ecryptfs_write_metadata rc=%d\n", rc);
goto out;
}
rc = ecryptfs_write_inode_size_to_metadata(inode);
if (rc) {
DEK_LOGE("Problem with "
"ecryptfs_write_inode_size_to_metadata; "
"rc = [%d]\n", rc);
goto out;
}
out:
mutex_unlock(&crypt_stat->cs_mutex);
ecryptfs_put_lower_file(inode);
fsstack_copy_attr_all(inode, lower_inode);
return rc;
}
void ecryptfs_fs_request_callback(int opcode, int ret, unsigned long ino) {
DEK_LOGD("%s opcode<%d> ret<%d> ino<%ld>\n", __func__, opcode, ret, ino);
}
int ecryptfs_sdp_set_sensitive(int engine_id, struct dentry *dentry) {
int rc = 0;
struct inode *inode = dentry->d_inode;
struct ecryptfs_crypt_stat *crypt_stat =
&ecryptfs_inode_to_private(inode)->crypt_stat;
dek_t DEK;
int id_bak = crypt_stat->engine_id;
DEK_LOGD("%s(%s)\n", __func__, dentry->d_name.name);
if(S_ISDIR(inode->i_mode)) {
crypt_stat->engine_id = engine_id;
crypt_stat->flags |= ECRYPTFS_DEK_IS_SENSITIVE;
rc = 0;
} else if(S_ISREG(inode->i_mode)) {
crypt_stat->engine_id = engine_id;
if (crypt_stat->key_size > ECRYPTFS_MAX_KEY_BYTES ||
crypt_stat->key_size > DEK_MAXLEN ||
crypt_stat->key_size > UINT_MAX){
DEK_LOGE("%s Too large key_size\n", __func__);
rc = -EFAULT;
goto out;
}
memcpy(DEK.buf, crypt_stat->key, crypt_stat->key_size);
DEK.len = (unsigned int)crypt_stat->key_size;
DEK.type = DEK_TYPE_PLAIN;
rc = dek_encrypt_dek_efs(crypt_stat->engine_id, &DEK, &crypt_stat->sdp_dek);
if (rc < 0) {
DEK_LOGE("Error encrypting dek; rc = [%d]\n", rc);
memset(&crypt_stat->sdp_dek, 0, sizeof(dek_t));
goto out;
}
#if 0
/*
* We don't have to clear FEK after set-sensitive.
* FEK will be closed when the file is closed
*/
memset(crypt_stat->key, 0, crypt_stat->key_size);
crypt_stat->flags &= ~(ECRYPTFS_KEY_SET);
#else
/*
* set-key after set sensitive file.
* Well when the file is just created and we do set_sensitive, the key is not set in the
* tfm. later SDP code, set-key is done while encryption, trying to decrypt EFEK.
*
* Here is the case in locked state user process want to create/write a file.
* the process open the file, automatically becomes sensitive by vault logic,
* and do the encryption, then boom. failed to decrypt EFEK even if FEK is
* available
*/
rc = ecryptfs_set_key(crypt_stat);
if(rc) goto out;
#endif
ecryptfs_update_crypt_flag(dentry, TO_SENSITIVE);
}
out:
if(rc) crypt_stat->engine_id = id_bak;
memset(&DEK, 0, sizeof(dek_t));
return rc;
}
int ecryptfs_sdp_set_protected(struct dentry *dentry) {
int rc = 0;
struct inode *inode = dentry->d_inode;
struct ecryptfs_crypt_stat *crypt_stat =
&ecryptfs_inode_to_private(inode)->crypt_stat;
DEK_LOGD("%s(%s)\n", __func__, dentry->d_name.name);
if(IS_CHAMBER_DENTRY(dentry)) {
DEK_LOGE("can't set-protected to chamber directory");
return -EIO;
}
if(crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
if(crypt_stat->engine_id < 0) {
DEK_LOGE("%s: invalid engine-id (ECRYPTFS_DEK_IS_SENSITIVE:ON, engine_id:%d)\n",
__func__, crypt_stat->engine_id);
return -EIO;
}
if(ecryptfs_is_sdp_locked(crypt_stat->engine_id)) {
DEK_LOGE("%s: Failed. (engine_id:%d locked)\n",
__func__, crypt_stat->engine_id);
return -EIO;
}
if(S_ISDIR(inode->i_mode)) {
crypt_stat->flags &= ~ECRYPTFS_DEK_IS_SENSITIVE;
rc = 0;
} else {
rc = ecryptfs_get_sdp_dek(crypt_stat);
if (rc) {
ecryptfs_printk(KERN_ERR, "%s Get SDP key failed\n", __func__);
goto out;
}
/*
* TODO : double check if need to compute iv here
*/
rc = ecryptfs_compute_root_iv(crypt_stat);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error computing "
"the root IV\n");
goto out;
}
rc = ecryptfs_set_key(crypt_stat);
if(rc) goto out;
ecryptfs_update_crypt_flag(dentry, TO_PROTECTED);
}
} else {
rc = 0; //already protected
}
out:
return rc;
}
int ecryptfs_sdp_convert_dek(struct dentry *dentry) {
int rc = 0;
struct inode *inode = dentry->d_inode;
struct ecryptfs_crypt_stat *crypt_stat =
&ecryptfs_inode_to_private(inode)->crypt_stat;
dek_t DEK;
rc = dek_decrypt_dek_efs(crypt_stat->engine_id, &crypt_stat->sdp_dek, &DEK);
if (rc < 0) {
DEK_LOGE("Error converting dek [DEC]; rc = [%d]\n", rc);
goto out;
}
rc = dek_encrypt_dek_efs(crypt_stat->engine_id, &DEK, &crypt_stat->sdp_dek);
if (rc < 0) {
DEK_LOGE("Error converting dek [ENC]; rc = [%d]\n", rc);
goto out;
}
rc = ecryptfs_update_crypt_flag(dentry, TO_SENSITIVE);
if (rc < 0) {
DEK_LOGE("Error converting dek [FLAG]; rc = [%d]\n", rc);
goto out;
}
out:
memset(&DEK, 0, sizeof(dek_t));
return rc;
}
long ecryptfs_do_sdp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
char filename[NAME_MAX+1] = {0};
void __user *ubuf = (void __user *)arg;
struct dentry *ecryptfs_dentry = file->f_path.dentry;
struct inode *inode = ecryptfs_dentry->d_inode;
struct ecryptfs_crypt_stat *crypt_stat =
&ecryptfs_inode_to_private(inode)->crypt_stat;
struct dentry *fp_dentry =
ecryptfs_inode_to_private(inode)->lower_file->f_dentry;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
&ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat;
int rc;
if (fp_dentry->d_name.len <= NAME_MAX)
memcpy(filename, fp_dentry->d_name.name,
fp_dentry->d_name.len + 1);
DEK_LOGD("%s(%s)\n", __func__, ecryptfs_dentry->d_name.name);
if (!(crypt_stat->flags & ECRYPTFS_DEK_SDP_ENABLED)) {
DEK_LOGE("SDP not enabled, skip sdp ioctl\n");
return -ENOTTY;
}
switch (cmd) {
case ECRYPTFS_IOCTL_GET_SDP_INFO: {
dek_arg_get_sdp_info req;
DEK_LOGD("ECRYPTFS_IOCTL_GET_SDP_INFO\n");
memset(&req, 0, sizeof(dek_arg_get_sdp_info));
if(copy_from_user(&req, ubuf, sizeof(req))) {
DEK_LOGE("can't copy from user\n");
return -EFAULT;
} else {
mutex_lock(&crypt_stat->cs_mutex);
req.engine_id = crypt_stat->engine_id;
if (crypt_stat->flags & ECRYPTFS_DEK_SDP_ENABLED) {
req.sdp_enabled = 1;
} else {
req.sdp_enabled = 0;
}
if (crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
req.is_sensitive = 1;
} else {
req.is_sensitive = 0;
}
if (crypt_stat->flags & ECRYPTFS_SDP_IS_CHAMBER_DIR) {
req.is_chamber = 1;
} else {
req.is_chamber = 0;
}
req.type = crypt_stat->sdp_dek.type;
mutex_unlock(&crypt_stat->cs_mutex);
}
if(copy_to_user(ubuf, &req, sizeof(req))) {
DEK_LOGE("can't copy to user\n");
return -EFAULT;
}
break;
}
case ECRYPTFS_IOCTL_SET_PROTECTED: {
ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_IOCTL_SET_PROTECTED\n");
if(!is_current_epmd()) {
DEK_LOGE("only epmd can call this\n");
DEK_LOGE("Permission denied\n");
return -EACCES;
}
if (!(crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE)) {
DEK_LOGE("already protected file\n");
return 0;
}
if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
DEK_LOGE("Set protected directory\n");
crypt_stat->flags &= ~ECRYPTFS_DEK_IS_SENSITIVE;
break;
}
rc = ecryptfs_sdp_set_protected(ecryptfs_dentry);
if (rc) {
DEK_LOGE("Failed to set protected rc(%d)\n", rc);
return rc;
}
break;
}
case ECRYPTFS_IOCTL_SET_SENSITIVE: {
dek_arg_set_sensitive req;
ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_IOCTL_SET_SENSITIVE\n");
if (crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
DEK_LOGE("already sensitive file\n");
return 0;
}
memset(&req, 0, sizeof(dek_arg_set_sensitive));
if(copy_from_user(&req, ubuf, sizeof(req))) {
DEK_LOGE("can't copy from user\n");
memset(&req, 0, sizeof(dek_arg_set_sensitive));
return -EFAULT;
} else {
rc = ecryptfs_sdp_set_sensitive(req.engine_id, ecryptfs_dentry);
if (rc) {
DEK_LOGE("failed to set sensitive rc(%d)\n", rc);
memset(&req, 0, sizeof(dek_arg_set_sensitive));
return rc;
}
}
memset(&req, 0, sizeof(dek_arg_set_sensitive));
break;
}
case ECRYPTFS_IOCTL_ADD_CHAMBER: {
dek_arg_add_chamber req;
int engineid;
if (!S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
DEK_LOGE("Not a directory\n");
return -ENOTDIR;
}
if(!is_current_epmd()) {
DEK_LOGE("only epmd can call this\n");
DEK_LOGE("Permission denied\n");
return -EACCES;
}
memset(&req, 0, sizeof(req));
if(copy_from_user(&req, ubuf, sizeof(req))) {
DEK_LOGE("can't copy from user\n");
memset(&req, 0, sizeof(req));
return -EFAULT;
}
if(!IS_UNDER_ROOT(ecryptfs_dentry)) {
DEK_LOGE("Chamber has to be under root directory");
return -EFAULT;
}
if(is_chamber_directory(mount_crypt_stat, ecryptfs_dentry->d_name.name, &engineid)) {
DEK_LOGE("Already chamber directory [%s] engine:%d\n",
ecryptfs_dentry->d_name.name, engineid);
if(engineid != req.engine_id) {
DEK_LOGE("Attemping to change engine-id[%d] -> [%d] : Failed\n",
engineid, req.engine_id);
return -EACCES;
}
set_chamber_flag(engineid, inode);
break;
}
rc = add_chamber_directory(mount_crypt_stat, req.engine_id,
ecryptfs_dentry->d_name.name);
if(rc) {
DEK_LOGE("add_chamber_directory failed. %d\n", rc);
return rc;
}
set_chamber_flag(req.engine_id, inode);
break;
}
case ECRYPTFS_IOCTL_REMOVE_CHAMBER: {
if (!S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
DEK_LOGE("Not a directory\n");
return -ENOTDIR;
}
if(!is_current_epmd()) {
//DEK_LOGE("only epmd can call this");
DEK_LOGE("Permission denied");
return -EACCES;
}
if(!IS_UNDER_ROOT(ecryptfs_dentry)) {
DEK_LOGE("Chamber has to be under root directory");
return -EFAULT;
}
if(!is_chamber_directory(mount_crypt_stat, ecryptfs_dentry->d_name.name, NULL)) {
DEK_LOGE("Not a chamber directory [%s]\n", ecryptfs_dentry->d_name.name);
clr_chamber_flag(inode);
return 0;
}
del_chamber_directory(mount_crypt_stat, ecryptfs_dentry->d_name.name);
clr_chamber_flag(inode);
break;
}
default: {
return -EOPNOTSUPP;
break;
}
}
return 0;
}

View File

@ -1,84 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef ECRYPTFS_DEK_H
#define ECRYPTFS_DEK_H
#include <linux/fs.h>
#include <sdp/dek_common.h>
#include "ecryptfs_kernel.h"
#define ECRYPTFS_DEK_XATTR_NAME "user.sdp"
#define ECRYPTFS_DEK_DEBUG 0
#define O_SDP 0x10000000
enum sdp_op {
TO_SENSITIVE = 0,
TO_PROTECTED
};
int ecryptfs_super_block_get_userid(struct super_block *sb);
int ecryptfs_is_sdp_locked(int engine_id);
void ecryptfs_clean_sdp_dek(struct ecryptfs_crypt_stat *crypt_stat);
int ecryptfs_get_sdp_dek(struct ecryptfs_crypt_stat *crypt_stat);
int ecryptfs_sdp_convert_dek(struct dentry *dentry);
int ecryptfs_parse_xattr_is_sensitive(const void *data, int len);
int write_dek_packet(char *dest, struct ecryptfs_crypt_stat *crypt_stat, size_t *written);
int parse_dek_packet(char *data, struct ecryptfs_crypt_stat *crypt_stat, size_t *packet_size);
long ecryptfs_do_sdp_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
int ecryptfs_sdp_set_sensitive(int engine_id, struct dentry *dentry);
int ecryptfs_sdp_set_protected(struct dentry *dentry);
void ecryptfs_set_mapping_sensitive(struct inode *ecryptfs_inode, int userid, enum sdp_op operation);
void ecryptfs_fs_request_callback(int opcode, int ret, unsigned long ino);
#define ECRYPTFS_EVT_RENAME_TO_CHAMBER 1
#define ECRYPTFS_EVT_RENAME_OUT_OF_CHAMBER 2
/*
* ioctl for SDP
*/
typedef struct _dek_arg_sdp_info {
int engine_id;
int sdp_enabled;
int is_sensitive;
int is_chamber;
unsigned int type;
}dek_arg_get_sdp_info;
typedef struct _dek_arg_set_sensitive {
int engine_id;
}dek_arg_set_sensitive;
typedef struct _dek_arg_add_chamber {
int engine_id;
}dek_arg_add_chamber;
#define ECRYPTFS_IOCTL_GET_SDP_INFO _IOR('l', 0x11, __u32)
#define ECRYPTFS_IOCTL_SET_SENSITIVE _IOW('l', 0x15, __u32)
#define ECRYPTFS_IOCTL_SET_PROTECTED _IOW('l', 0x16, __u32)
#define ECRYPTFS_IOCTL_ADD_CHAMBER _IOW('l', 0x17, __u32)
#define ECRYPTFS_IOCTL_REMOVE_CHAMBER _IOW('l', 0x18, __u32)
#endif /* #ifndef ECRYPTFS_DEK_H */

View File

@ -40,11 +40,6 @@
#include <linux/nsproxy.h>
#include <linux/backing-dev.h>
#include <linux/ecryptfs.h>
#ifdef CONFIG_SDP
#include <sdp/dek_common.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#endif
#ifdef CONFIG_WTL_ENCRYPTION_FILTER
#define ENC_NAME_FILTER_MAX_INSTANCE 5
@ -66,10 +61,6 @@
#define ECRYPTFS_BASE_PATH_SIZE 1024
#define ECRYPTFS_LABEL_SIZE 1024
#ifdef CONFIG_SDP
#define PKG_NAME_SIZE 16
#endif
void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok);
extern void ecryptfs_to_hex(char *dst, char *src, size_t src_size);
extern void ecryptfs_from_hex(char *dst, char *src, int dst_size);
@ -244,12 +235,6 @@ struct ecryptfs_crypt_stat {
#define ECRYPTFS_I_SIZE_INITIALIZED 0x00004000
#ifdef CONFIG_WTL_ENCRYPTION_FILTER
#define ECRYPTFS_ENCRYPTED_OTHER_DEVICE 0x00008000
#endif
#ifdef CONFIG_SDP
#define ECRYPTFS_DEK_SDP_ENABLED 0x00100000
#define ECRYPTFS_DEK_IS_SENSITIVE 0x00200000
#define ECRYPTFS_DEK_MULTI_ENGINE 0x00400000 // eCryptfs header contains engine id.
#define ECRYPTFS_SDP_IS_CHAMBER_DIR 0x02000000
#endif
u32 flags;
@ -272,10 +257,6 @@ struct ecryptfs_crypt_stat {
struct mutex cs_tfm_mutex;
struct mutex cs_hash_tfm_mutex;
struct mutex cs_mutex;
#ifdef CONFIG_SDP
int engine_id;
dek_t sdp_dek;
#endif
};
/* inode private data. */
@ -372,9 +353,6 @@ struct ecryptfs_mount_crypt_stat {
#endif
#if defined(CONFIG_CRYPTO_FIPS) && !defined(CONFIG_FORCE_DISABLE_FIPS)
#define ECRYPTFS_ENABLE_CC 0x00000400
#endif
#ifdef CONFIG_SDP
#define ECRYPTFS_MOUNT_SDP_ENABLED 0x80000000
#endif
u32 flags;
@ -394,13 +372,6 @@ struct ecryptfs_mount_crypt_stat {
char enc_filter_ext[ENC_EXT_FILTER_MAX_INSTANCE]
[ENC_EXT_FILTER_MAX_LEN + 1];
#endif
#ifdef CONFIG_SDP
int userid;
struct list_head chamber_dir_list;
spinlock_t chamber_dir_list_lock;
int partition_id;
#endif
};
#define ECRYPTFS_OVERRIDE_ROOT_CRED(saved_cred) \
@ -428,9 +399,6 @@ struct ecryptfs_sb_info {
struct ecryptfs_mount_crypt_stat mount_crypt_stat;
struct backing_dev_info bdi;
struct ecryptfs_propagate_stat propagate_stat;
#ifdef CONFIG_SDP
int userid;
#endif
};
/* file private data. */

View File

@ -1,183 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include "ecryptfs_sdp_chamber.h"
#include <sdp/common.h>
#define CHAMBER_PATH_MAX 512
typedef struct __chamber_info {
int partition_id;
int engine_id;
struct list_head list;
char path[CHAMBER_PATH_MAX];
}chamber_info_t;
#define NO_DIRECTORY_SEPARATOR_IN_CHAMBER_PATH 1
/* Debug */
#define CHAMBER_DEBUG 0
#if CHAMBER_DEBUG
#define CHAMBER_LOGD(FMT, ...) printk("SDP_CHAMBER[%d] %s :: " FMT , current->pid, __func__, ##__VA_ARGS__)
#else
#define CHAMBER_LOGD(FMT, ...)
#endif /* PUB_CRYPTO_DEBUG */
#define CHAMBER_LOGE(FMT, ...) printk("SDP_CHAMBER[%d] %s :: " FMT , current->pid, __func__, ##__VA_ARGS__)
chamber_info_t *alloc_chamber_info(int partition_id, int engine_id, const unsigned char *path) {
chamber_info_t *new_chamber = kmalloc(sizeof(chamber_info_t), GFP_KERNEL);
if(new_chamber == NULL) {
CHAMBER_LOGE("can't alloc memory for chamber_info\n");
return NULL;
}
new_chamber->partition_id = partition_id;
new_chamber->engine_id = engine_id;
snprintf(new_chamber->path, CHAMBER_PATH_MAX, "%s", path);
return new_chamber;
}
int add_chamber_directory(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
int engine_id, const unsigned char *path) {
chamber_info_t *new_chamber = NULL;
#if NO_DIRECTORY_SEPARATOR_IN_CHAMBER_PATH
if(strchr(path, '/') != NULL) {
CHAMBER_LOGE("Chamber directory cannot contain '/'\n");
return -EINVAL;
}
#endif
new_chamber = alloc_chamber_info(mount_crypt_stat->partition_id, engine_id, path);
if(new_chamber == NULL) {
return -ENOMEM;
}
spin_lock(&(mount_crypt_stat->chamber_dir_list_lock));
CHAMBER_LOGD("Adding %s into chamber list\n", new_chamber->path);
list_add_tail(&new_chamber->list, &(mount_crypt_stat->chamber_dir_list));
spin_unlock(&(mount_crypt_stat->chamber_dir_list_lock));
return 0;
}
chamber_info_t *find_chamber_info(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
const unsigned char *path) {
struct list_head *entry;
spin_lock(&(mount_crypt_stat->chamber_dir_list_lock));
CHAMBER_LOGD("%s\n", path);
list_for_each(entry, &mount_crypt_stat->chamber_dir_list) {
chamber_info_t *info;
info = list_entry(entry, chamber_info_t, list);
// Check path
if(!strncmp(path, info->path, CHAMBER_PATH_MAX)) {
CHAMBER_LOGD("Found %s from chamber list\n", info->path);
spin_unlock(&(mount_crypt_stat->chamber_dir_list_lock));
return info;
}
}
spin_unlock(&(mount_crypt_stat->chamber_dir_list_lock));
CHAMBER_LOGD("Not found\n");
return NULL;
}
void del_chamber_directory(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
const unsigned char *path) {
chamber_info_t *info = find_chamber_info(mount_crypt_stat, path);
if(info == NULL) {
CHAMBER_LOGD("nothing to remove\n");
return;
}
spin_lock(&mount_crypt_stat->chamber_dir_list_lock);
CHAMBER_LOGD("%s removed\n", info->path);
list_del(&info->list);
kfree(info);
spin_unlock(&mount_crypt_stat->chamber_dir_list_lock);
}
int is_chamber_directory(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
const unsigned char *path, int *engineid) {
chamber_info_t *info;
#if NO_DIRECTORY_SEPARATOR_IN_CHAMBER_PATH
if(strchr(path, '/') != NULL) {
CHAMBER_LOGD("%s containes '/'\n", path);
return 0;
}
#endif
info = find_chamber_info(mount_crypt_stat, path);
if(info == NULL)
return 0;
if(engineid) *engineid = info->engine_id;
return 1;
}
void set_chamber_flag(int engineid, struct inode *inode) {
struct ecryptfs_crypt_stat *crypt_stat;
if(inode == NULL) {
CHAMBER_LOGE("invalid inode\n");
return;
}
crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
crypt_stat->engine_id = engineid;
crypt_stat->flags |= ECRYPTFS_SDP_IS_CHAMBER_DIR;
crypt_stat->flags |= ECRYPTFS_DEK_IS_SENSITIVE;
}
void clr_chamber_flag(struct inode *inode) {
struct ecryptfs_crypt_stat *crypt_stat;
if(inode == NULL) {
CHAMBER_LOGE("invalid inode\n");
return;
}
crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
crypt_stat->engine_id = -1;
crypt_stat->flags &= ~ECRYPTFS_DEK_IS_SENSITIVE;
crypt_stat->flags &= ~ECRYPTFS_SDP_IS_CHAMBER_DIR;
}

View File

@ -1,39 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef ECRYPTFS_SDP_CHAMBER_H_
#define ECRYPTFS_SDP_CHAMBER_H_
#include "ecryptfs_kernel.h"
int add_chamber_directory(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
int engine_id, const unsigned char *path);
void del_chamber_directory(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
const unsigned char *path);
int is_chamber_directory(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
const unsigned char *path, int *engineid);
void set_chamber_flag(int engineid, struct inode *inode);
void clr_chamber_flag(struct inode *inode);
#define IS_UNDER_ROOT(dentry) (dentry->d_parent->d_inode == dentry->d_sb->s_root->d_inode)
#define IS_CHAMBER_DENTRY(dentry) (ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat.flags & ECRYPTFS_SDP_IS_CHAMBER_DIR)
#define IS_SENSITIVE_DENTRY(dentry) (ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat.flags & ECRYPTFS_DEK_IS_SENSITIVE)
#endif /* ECRYPTFS_SDP_CHAMBER_H_ */

View File

@ -39,15 +39,6 @@
#define ECRYPTFS_WAS_ENCRYPTED 0x0080
#define ECRYPTFS_WAS_ENCRYPTED_OTHER_DEVICE 0x0100
#endif
#ifdef CONFIG_SDP
#if 0
#include <linux/fs.h>
#include <linux/syscalls.h>
#include <linux/atomic.h>
#endif
#include "ecryptfs_dek.h"
#include "mm.h"
#endif
/**
* ecryptfs_read_update_atime
@ -219,14 +210,6 @@ static int read_or_initialize_metadata(struct dentry *dentry)
if (!rc)
goto out;
#ifdef CONFIG_SDP
/*
* no passthrough/xattr for sensitive files
*/
if ((rc) && crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE)
goto out;
#endif
if (mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED) {
crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
| ECRYPTFS_ENCRYPTED);
@ -244,25 +227,6 @@ static int read_or_initialize_metadata(struct dentry *dentry)
rc = -EIO;
out:
mutex_unlock(&crypt_stat->cs_mutex);
#ifdef CONFIG_SDP
if(!rc)
{
/*
* SDP v2.0 : sensitive directory (SDP vault)
* Files under sensitive directory automatically becomes sensitive
*/
struct dentry *p = dentry->d_parent;
struct inode *parent_inode = p->d_inode;
struct ecryptfs_crypt_stat *parent_crypt_stat =
&ecryptfs_inode_to_private(parent_inode)->crypt_stat;
if (!(crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) &&
((S_ISDIR(parent_inode->i_mode)) &&
(parent_crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE))) {
rc = ecryptfs_sdp_set_sensitive(parent_crypt_stat->engine_id, dentry);
}
}
#endif
return rc;
}
@ -347,13 +311,6 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
ecryptfs_set_file_lower(
file, ecryptfs_inode_to_private(inode)->lower_file);
if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
#ifdef CONFIG_SDP
/*
* it's possible to have a sensitive directory. (vault)
*/
if (mount_crypt_stat->flags & ECRYPTFS_MOUNT_SDP_ENABLED)
crypt_stat->flags |= ECRYPTFS_DEK_SDP_ENABLED;
#endif
ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
mutex_lock(&crypt_stat->cs_mutex);
crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
@ -363,63 +320,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
}
rc = read_or_initialize_metadata(ecryptfs_dentry);
if (rc) {
#ifdef CONFIG_SDP
if(file->f_flags & O_SDP){
printk("Failed to initialize metadata, "
"but let it continue cause current call is from SDP API\n");
mutex_lock(&crypt_stat->cs_mutex);
crypt_stat->flags &= ~(ECRYPTFS_KEY_VALID);
mutex_unlock(&crypt_stat->cs_mutex);
rc = 0;
/*
* Letting this continue doesn't mean to allow read/writing. It will anyway fail later.
*
* 1. In this stage, ecryptfs_stat won't have key/iv and encryption ctx.
* 2. ECRYPTFS_KEY_VALID bit is off, next attempt will try reading metadata again.
* 3. Skip DEK conversion. it cannot be done anyway.
*/
goto out;
}
#endif
goto out_put;
}
#ifdef CONFIG_SDP
if (crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
#ifdef CONFIG_SDP_KEY_DUMP
if (S_ISREG(ecryptfs_dentry->d_inode->i_mode)) {
if(get_sdp_sysfs_key_dump()) {
printk("FEK[%s] : ", ecryptfs_dentry->d_name.name);
key_dump(crypt_stat->key, 32);
}
}
#endif
/*
* Need to update sensitive mapping on file open
*/
if (S_ISREG(ecryptfs_dentry->d_inode->i_mode)) {
ecryptfs_set_mapping_sensitive(inode, mount_crypt_stat->userid, TO_SENSITIVE);
}
if (ecryptfs_is_sdp_locked(crypt_stat->engine_id)) {
ecryptfs_printk(KERN_INFO, "ecryptfs_open: persona is locked, rc=%d\n", rc);
} else {
int dek_type = crypt_stat->sdp_dek.type;
ecryptfs_printk(KERN_INFO, "ecryptfs_open: persona is unlocked, rc=%d\n", rc);
if(dek_type != DEK_TYPE_AES_ENC) {
ecryptfs_printk(KERN_DEBUG, "converting dek...\n");
rc = ecryptfs_sdp_convert_dek(ecryptfs_dentry);
ecryptfs_printk(KERN_DEBUG, "conversion ready, rc=%d\n", rc);
rc = 0; // TODO: Do we need to return error if conversion fails?
}
}
}
#if ECRYPTFS_DEK_DEBUG
else {
ecryptfs_printk(KERN_INFO, "ecryptfs_open: dek_file_type is protected\n");
}
#endif
#endif
ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = "
"[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino,
@ -451,13 +353,7 @@ static int ecryptfs_release(struct inode *inode, struct file *file)
struct ecryptfs_crypt_stat *crypt_stat;
crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
#ifdef CONFIG_SDP
mutex_lock(&crypt_stat->cs_mutex);
#endif
ecryptfs_put_lower_file(inode);
#ifdef CONFIG_SDP
mutex_unlock(&crypt_stat->cs_mutex);
#endif
kmem_cache_free(ecryptfs_file_info_cache,
ecryptfs_file_to_private(file));
return 0;
@ -524,13 +420,6 @@ ecryptfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
#endif
#ifdef CONFIG_SDP
rc = ecryptfs_do_sdp_ioctl(file, cmd, arg);
if (rc != EOPNOTSUPP)
return rc;
#else
printk("%s CONFIG_SDP not enabled \n", __func__);
#endif
if (ecryptfs_file_to_private(file))
lower_file = ecryptfs_file_to_lower(file);
if (lower_file && lower_file->f_op && lower_file->f_op->unlocked_ioctl)
@ -545,14 +434,6 @@ ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct file *lower_file = NULL;
long rc = -ENOIOCTLCMD;
#ifdef CONFIG_SDP
rc = ecryptfs_do_sdp_ioctl(file, cmd, arg);
if (rc != EOPNOTSUPP)
return rc;
#else
printk("%s CONFIG_SDP not enabled \n", __func__);
#endif
if (ecryptfs_file_to_private(file))
lower_file = ecryptfs_file_to_lower(file);
if (lower_file && lower_file->f_op && lower_file->f_op->compat_ioctl)

View File

@ -36,14 +36,6 @@
#include <asm/unaligned.h>
#include "ecryptfs_kernel.h"
#ifdef CONFIG_SDP
#include <sdp/fs_request.h>
#include "ecryptfs_sdp_chamber.h"
#include "ecryptfs_dek.h"
#include "../sdcardfs/sdcardfs.h"
#endif
/* Do not directly use this function. Use ECRYPTFS_OVERRIDE_CRED() instead. */
const struct cred * ecryptfs_override_fsids(uid_t fsuid, gid_t fsgid)
{
@ -72,7 +64,6 @@ void ecryptfs_revert_fsids(const struct cred * old_cred)
put_cred(cur_cred);
}
#ifndef CONFIG_SDP
static struct dentry *lock_parent(struct dentry *dentry)
{
struct dentry *dir;
@ -87,7 +78,6 @@ static void unlock_dir(struct dentry *dir)
mutex_unlock(&dir->d_inode->i_mutex);
dput(dir);
}
#endif
static int ecryptfs_inode_test(struct inode *inode, void *lower_inode)
{
@ -181,36 +171,6 @@ static int ecryptfs_interpose(struct dentry *lower_dentry,
if(d_unhashed(dentry))
d_rehash(dentry);
#ifdef CONFIG_SDP
if(S_ISDIR(inode->i_mode) && dentry) {
if(IS_UNDER_ROOT(dentry)) {
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
&ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat;
int engineid;
printk("Creating a directoy under root directory of current partition.\n");
if(is_chamber_directory(mount_crypt_stat, dentry->d_name.name, &engineid)) {
printk("This is a chamber directory engine[%d]\n", engineid);
set_chamber_flag(engineid, inode);
}
} else if(IS_SENSITIVE_DENTRY(dentry->d_parent)) {
/*
* When parent directory is sensitive
*/
struct ecryptfs_crypt_stat *crypt_stat =
&ecryptfs_inode_to_private(inode)->crypt_stat;
struct ecryptfs_crypt_stat *parent_crypt_stat =
&ecryptfs_inode_to_private(dentry->d_parent->d_inode)->crypt_stat;
//TODO : remove this log
DEK_LOGE("Parent %s[id:%d] is sensitive. so this directory is sensitive too\n",
dentry->d_parent->d_name.name, parent_crypt_stat->engine_id);
crypt_stat->flags |= ECRYPTFS_DEK_IS_SENSITIVE;
crypt_stat->engine_id = parent_crypt_stat->engine_id;
}
}
#endif
return 0;
}
@ -581,38 +541,6 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry,
}
}
#ifdef CONFIG_SDP
if (S_ISDIR(inode->i_mode) && dentry) {
if(IS_UNDER_ROOT(dentry)) {
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
&ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat;
int engineid;
printk("Lookup a directoy under root directory of current partition.\n");
if(is_chamber_directory(mount_crypt_stat, dentry->d_name.name, &engineid)) {
/*
* When this directory is under ROOT directory and the name is registered
* as Chamber.
*/
printk("This is a chamber directory engine[%d]\n", engineid);
set_chamber_flag(engineid, inode);
}
} else if(IS_SENSITIVE_DENTRY(dentry->d_parent)) {
/*
* When parent directory is sensitive
*/
struct ecryptfs_crypt_stat *crypt_stat =
&ecryptfs_inode_to_private(inode)->crypt_stat;
struct ecryptfs_crypt_stat *parent_crypt_stat =
&ecryptfs_inode_to_private(dentry->d_parent->d_inode)->crypt_stat;
printk("Parent %s is sensitive. so this directory is sensitive too\n",
dentry->d_parent->d_name.name);
crypt_stat->flags |= ECRYPTFS_DEK_IS_SENSITIVE;
crypt_stat->engine_id = parent_crypt_stat->engine_id;
}
}
#endif
if (inode->i_state & I_NEW)
unlock_new_inode(inode);
d_add(dentry, inode);
@ -620,13 +548,6 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry,
return rc;
}
#ifdef CONFIG_SDP
static inline int isdigit(int ch)
{
return (ch >= '0') && (ch <= '9');
}
#endif
/**
* ecryptfs_lookup
* @ecryptfs_dir_inode: The eCryptfs directory inode
@ -684,68 +605,9 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
}
mutex_lock(&lower_dir_dentry->d_inode->i_mutex);
#ifdef CONFIG_SDP
if(!strncmp(lower_dir_dentry->d_sb->s_type->name, "sdcardfs", 8)) {
struct sdcardfs_dentry_info *dinfo = SDCARDFS_D(lower_dir_dentry);
struct dentry *parent = dget_parent(lower_dir_dentry);
struct sdcardfs_dentry_info *parent_info = SDCARDFS_D(parent);
dinfo->under_knox = 1;
dinfo->userid = -1;
if(IS_UNDER_ROOT(ecryptfs_dentry)) {
parent_info->permission = PERMISSION_PRE_ROOT;
if(mount_crypt_stat->userid >= 100 && mount_crypt_stat->userid <= 200) {
parent_info->userid = mount_crypt_stat->userid;
/* Assume masked off by default. */
if (!strcasecmp(ecryptfs_dentry->d_name.name, "Android")) {
/* App-specific directories inside; let anyone traverse */
dinfo->permission = PERMISSION_ROOT;
}
}
else {
int len = strlen(ecryptfs_dentry->d_name.name);
int i, numeric = 1;
for(i=0 ; i < len ; i++)
if(!isdigit(ecryptfs_dentry->d_name.name[i])) { numeric = 0; break; }
if(numeric) {
dinfo->userid = simple_strtoul(ecryptfs_dentry->d_name.name, NULL, 10);
}
}
}
else {
struct sdcardfs_sb_info *sbi = SDCARDFS_SB(lower_dir_dentry->d_sb);
/* Derive custom permissions based on parent and current node */
switch (parent_info->permission) {
case PERMISSION_ROOT:
if (!strcasecmp(ecryptfs_dentry->d_name.name, "data") || !strcasecmp(ecryptfs_dentry->d_name.name, "obb") || !strcasecmp(ecryptfs_dentry->d_name.name, "media")) {
/* App-specific directories inside; let anyone traverse */
dinfo->permission = PERMISSION_ANDROID;
}
break;
case PERMISSION_ANDROID:
dinfo->permission = PERMISSION_UNDER_ANDROID;
dinfo->appid = get_appid(sbi->pkgl_id, ecryptfs_dentry->d_name.name);
break;
}
}
dput(parent);
}
#endif
lower_dentry = lookup_one_len(encrypted_and_encoded_name,
lower_dir_dentry,
encrypted_and_encoded_name_size);
#ifdef CONFIG_SDP
if(!strncmp(lower_dir_dentry->d_sb->s_type->name, "sdcardfs", 8)) {
struct sdcardfs_dentry_info *dinfo = SDCARDFS_D(lower_dir_dentry);
dinfo->under_knox = 0;
dinfo->userid = -1;
}
#endif
mutex_unlock(&lower_dir_dentry->d_inode->i_mutex);
if (IS_ERR(lower_dentry)) {
rc = PTR_ERR(lower_dentry);
@ -853,23 +715,6 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
lower_dentry = ecryptfs_dentry_to_lower(dentry);
lower_dir_dentry = lock_parent(lower_dentry);
#ifdef CONFIG_SDP
if(!strncmp(lower_dir_dentry->d_sb->s_type->name, "sdcardfs", 8)) {
struct sdcardfs_dentry_info *dinfo = SDCARDFS_D(lower_dir_dentry);
int len = strlen(dentry->d_name.name);
int i, numeric = 1;
dinfo->under_knox = 1;
dinfo->userid = -1;
if(IS_UNDER_ROOT(dentry)) {
for(i=0 ; i < len ; i++)
if(!isdigit(dentry->d_name.name[i])) { numeric = 0; break; }
if(numeric) {
dinfo->userid = simple_strtoul(dentry->d_name.name, NULL, 10);
}
}
}
#endif
rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode);
if (rc || !lower_dentry->d_inode)
goto out;
@ -880,13 +725,6 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);
out:
#ifdef CONFIG_SDP
if(!strncmp(lower_dir_dentry->d_sb->s_type->name, "sdcardfs", 8)) {
struct sdcardfs_dentry_info *dinfo = SDCARDFS_D(lower_dir_dentry);
dinfo->under_knox = 0;
dinfo->userid = -1;
}
#endif
unlock_dir(lower_dir_dentry);
if (!dentry->d_inode)
d_drop(dentry);
@ -899,13 +737,6 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
struct dentry *lower_dir_dentry;
int rc;
#ifdef CONFIG_SDP
if(IS_CHAMBER_DENTRY(dentry)) {
printk("You're removing chamber directory. I/O error\n");
return -EIO;
}
#endif
lower_dentry = ecryptfs_dentry_to_lower(dentry);
dget(dentry);
lower_dir_dentry = lock_parent(lower_dentry);
@ -947,8 +778,6 @@ out:
return rc;
}
#define ECRYPTFS_SDP_RENAME_DEBUG 0
static int
ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
@ -960,72 +789,6 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct dentry *lower_new_dir_dentry;
struct dentry *trap = NULL;
struct inode *target_inode;
#ifdef CONFIG_SDP
sdp_fs_command_t *cmd = NULL;
int rename_event = 0x00;
struct ecryptfs_crypt_stat *crypt_stat =
&(ecryptfs_inode_to_private(old_dentry->d_inode)->crypt_stat);
struct ecryptfs_crypt_stat *parent_crypt_stat =
&(ecryptfs_inode_to_private(old_dentry->d_parent->d_inode)->crypt_stat);
struct ecryptfs_crypt_stat *new_parent_crypt_stat =
&(ecryptfs_inode_to_private(new_dentry->d_parent->d_inode)->crypt_stat);
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
&ecryptfs_superblock_to_private(old_dentry->d_sb)->mount_crypt_stat;
#if ECRYPTFS_SDP_RENAME_DEBUG
printk("You're renaming %s to %s\n",
old_dentry->d_name.name,
new_dentry->d_name.name);
printk("old_dentry[%p] : %s [parent %s : %s] inode:%p\n",
old_dentry, old_dentry->d_name.name,
old_dentry->d_parent->d_name.name,
IS_SENSITIVE_DENTRY(old_dentry->d_parent) ? "sensitive" : "protected",
old_dentry->d_inode);
printk("new_dentry[%p] : %s [parent %s : %s] inode:%p\n",
new_dentry, new_dentry->d_name.name,
new_dentry->d_parent->d_name.name,
IS_SENSITIVE_DENTRY(new_dentry->d_parent) ? "sensitive" : "protected",
new_dentry->d_inode);
#endif
if(IS_CHAMBER_DENTRY(old_dentry)) {
printk("Rename trial on chamber : failed\n");
return -EIO;
}
#if 0 // kernel panic. new_crypt_stat->engine_id
if(IS_SENSITIVE_DENTRY(old_dentry->d_parent) &&
IS_SENSITIVE_DENTRY(new_dentry->d_parent)) {
if(crypt_stat->engine_id != new_crypt_stat->engine_id) {
printk("Rename chamber file to another chamber : failed\n");
return -EIO;
}
}
#endif
if(IS_SENSITIVE_DENTRY(old_dentry->d_parent)) {
if(ecryptfs_is_sdp_locked(parent_crypt_stat->engine_id)) {
printk("Rename/move trial in locked state\n");
return -EIO;
}
}
if(IS_SENSITIVE_DENTRY(old_dentry->d_parent) &&
IS_SENSITIVE_DENTRY(new_dentry->d_parent)) {
if(parent_crypt_stat->engine_id != new_parent_crypt_stat->engine_id) {
printk("Can't move between chambers\n");
return -EIO;
}
}
if(IS_SENSITIVE_DENTRY(old_dentry->d_parent) &&
!IS_SENSITIVE_DENTRY(new_dentry->d_parent))
rename_event |= ECRYPTFS_EVT_RENAME_OUT_OF_CHAMBER;
if(!IS_SENSITIVE_DENTRY(old_dentry->d_parent) &&
IS_SENSITIVE_DENTRY(new_dentry->d_parent))
rename_event |= ECRYPTFS_EVT_RENAME_TO_CHAMBER;
#endif
lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
@ -1056,45 +819,6 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (new_dir != old_dir)
fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
#ifdef CONFIG_SDP
if(!rc) {
crypt_stat = &(ecryptfs_inode_to_private(old_dentry->d_inode)->crypt_stat);
if(rename_event > 0) {
switch(rename_event) {
case ECRYPTFS_EVT_RENAME_TO_CHAMBER:
cmd = sdp_fs_command_alloc(FSOP_SDP_SET_SENSITIVE, current->pid,
mount_crypt_stat->userid, mount_crypt_stat->partition_id,
old_dentry->d_inode->i_ino,
GFP_NOFS);
break;
case ECRYPTFS_EVT_RENAME_OUT_OF_CHAMBER:
cmd = sdp_fs_command_alloc(FSOP_SDP_SET_PROTECTED, current->pid,
mount_crypt_stat->userid, mount_crypt_stat->partition_id,
old_dentry->d_inode->i_ino,
GFP_NOFS);
break;
default:
cmd = NULL;
break;
}
}
#if ECRYPTFS_SDP_RENAME_DEBUG
printk("[end of rename] old_dentry[%p] : %s [parent %s : %s] inode:%p\n",
old_dentry, old_dentry->d_name.name,
old_dentry->d_parent->d_name.name,
IS_SENSITIVE_DENTRY(old_dentry->d_parent) ? "sensitive" : "protected",
old_dentry->d_inode);
printk("[end of rename] new_dentry[%p] : %s [parent %s : %s] inode:%p\n",
new_dentry, new_dentry->d_name.name,
new_dentry->d_parent->d_name.name,
IS_SENSITIVE_DENTRY(new_dentry->d_parent) ? "sensitive" : "protected",
new_dentry->d_inode);
#endif
}
#endif
out_lock:
unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
dput(lower_new_dir_dentry);
@ -1102,12 +826,6 @@ out_lock:
dput(lower_new_dentry);
dput(lower_old_dentry);
#ifdef CONFIG_SDP
if(!rc && cmd != NULL) {
sdp_fs_request(cmd, ecryptfs_fs_request_callback);
sdp_fs_command_free(cmd);
}
#endif
return rc;
}

View File

@ -35,10 +35,6 @@
#include <linux/slab.h>
#include "ecryptfs_kernel.h"
#ifdef CONFIG_SDP
#include "ecryptfs_dek.h"
#endif
/**
* request_key returned an error instead of a valid key address;
* determine the type of error, make appropriate log entries, and
@ -1909,22 +1905,6 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
rc = -EIO;
goto out_wipe_list;
break;
#ifdef CONFIG_SDP
case ECRYPTFS_DEK_PACKET_TYPE:
printk("%s() ECRYPTFS_DEK_PACKET_TYPE \n",
__func__);
rc = parse_dek_packet(
(unsigned char *)&src[i], crypt_stat,
&packet_size);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error parsing "
"dek packet %d\n", rc);
rc = -EIO;
goto out_wipe_list;
}
i += packet_size;
break;
#endif
default:
ecryptfs_printk(KERN_DEBUG, "No packet at offset [%zd] "
"of the file header; hex value of "
@ -2024,15 +2004,6 @@ found_matching_auth_tok:
BUG();
}
#ifdef CONFIG_SDP
if((crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE)) {
rc = ecryptfs_get_sdp_dek(crypt_stat);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error setting sdp key after parse\n");
goto out_wipe_list;
}
}
#endif
rc = ecryptfs_compute_root_iv(crypt_stat);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error computing "
@ -2478,20 +2449,9 @@ encrypted_session_key_set:
ECRYPTFS_SALT_SIZE);
(*packet_size) += ECRYPTFS_SALT_SIZE; /* salt */
dest[(*packet_size)++] = 0x60; /* hash iterations (65536) */
#ifdef CONFIG_SDP
if ((crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE)) {
ecryptfs_printk(KERN_DEBUG, "Sensitive file, tag_3 to zeroes\n");
memset(&dest[(*packet_size)], 0, key_rec->enc_key_size);
} else {
memcpy(&dest[(*packet_size)], key_rec->enc_key,
key_rec->enc_key_size);
}
(*packet_size) += key_rec->enc_key_size;
#else
memcpy(&dest[(*packet_size)], key_rec->enc_key,
key_rec->enc_key_size);
(*packet_size) += key_rec->enc_key_size;
#endif
out:
if (rc)
(*packet_size) = 0;
@ -2576,19 +2536,6 @@ ecryptfs_generate_key_packet_set(char *dest_base,
goto out_free;
}
(*len) += written;
#ifdef CONFIG_SDP
if (crypt_stat->flags & ECRYPTFS_DEK_SDP_ENABLED &&
crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
rc = write_dek_packet(dest_base + (*len), crypt_stat,
&written);
if (rc) {
ecryptfs_printk(KERN_WARNING, "Error "
"writing dek packet\n");
goto out_free;
}
(*len) += written;
}
#endif
} else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
rc = write_tag_1_packet(dest_base + (*len), &max,
auth_tok_key, auth_tok,

View File

@ -39,11 +39,6 @@
#include <linux/magic.h>
#include "ecryptfs_kernel.h"
#ifdef CONFIG_SDP
#include "mm.h"
#include "ecryptfs_sdp_chamber.h"
#endif
#ifdef CONFIG_WTL_ENCRYPTION_FILTER
#include <linux/ctype.h>
#endif
@ -173,11 +168,6 @@ void ecryptfs_put_lower_file(struct inode *inode)
if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count,
&inode_info->lower_file_mutex)) {
filemap_write_and_wait(inode->i_mapping);
#ifdef CONFIG_SDP
if (inode_info->crypt_stat.flags & ECRYPTFS_DEK_IS_SENSITIVE) {
ecryptfs_mm_do_sdp_cleanup(inode);
}
#endif
fput(inode_info->lower_file);
inode_info->lower_file = NULL;
mutex_unlock(&inode_info->lower_file_mutex);
@ -197,9 +187,6 @@ enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig,
#endif
#if defined(CONFIG_CRYPTO_FIPS) && !defined(CONFIG_FORCE_DISABLE_FIPS)
ecryptfs_opt_enable_cc,
#endif
#ifdef CONFIG_SDP
ecryptfs_opt_userid, ecryptfs_opt_sdp, ecryptfs_opt_chamber_dirs, ecryptfs_opt_partition_id,
#endif
ecryptfs_opt_base, ecryptfs_opt_type, ecryptfs_opt_label,
ecryptfs_opt_err };
@ -224,12 +211,6 @@ static const match_table_t tokens = {
#endif
#if defined(CONFIG_CRYPTO_FIPS) && !defined(CONFIG_FORCE_DISABLE_FIPS)
{ecryptfs_opt_enable_cc, "ecryptfs_enable_cc"},
#endif
#ifdef CONFIG_SDP
{ecryptfs_opt_chamber_dirs, "chamber=%s"},
{ecryptfs_opt_userid, "userid=%s"},
{ecryptfs_opt_sdp, "sdp_enabled"},
{ecryptfs_opt_partition_id, "partition_id=%u"},
#endif
{ecryptfs_opt_base, "base=%s"},
{ecryptfs_opt_type, "type=%s"},
@ -273,13 +254,6 @@ static void ecryptfs_init_mount_crypt_stat(
INIT_LIST_HEAD(&mount_crypt_stat->global_auth_tok_list);
mutex_init(&mount_crypt_stat->global_auth_tok_list_mutex);
mount_crypt_stat->flags |= ECRYPTFS_MOUNT_CRYPT_STAT_INITIALIZED;
#ifdef CONFIG_SDP
spin_lock_init(&mount_crypt_stat->chamber_dir_list_lock);
INIT_LIST_HEAD(&mount_crypt_stat->chamber_dir_list);
mount_crypt_stat->partition_id = -1;
#endif
}
static void ecryptfs_init_propagate_stat(
@ -525,78 +499,6 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options,
strncpy(cipher_mode, ECRYPTFS_AES_CBC_MODE, ECRYPTFS_MAX_CIPHER_MODE_SIZE);
break;
#endif
#ifdef CONFIG_SDP
case ecryptfs_opt_userid: {
char *userid_src = args[0].from;
int userid =
(int)simple_strtol(userid_src,
&userid_src, 0);
sbi->userid = userid;
mount_crypt_stat->userid = userid;
/*
* Enabling SDP by default for Knox container.
*/
mount_crypt_stat->flags |= ECRYPTFS_MOUNT_SDP_ENABLED;
}
break;
case ecryptfs_opt_sdp:
mount_crypt_stat->flags |= ECRYPTFS_MOUNT_SDP_ENABLED;
break;
case ecryptfs_opt_chamber_dirs: {
char *chamber_dirs = args[0].from;
char *token = NULL;
/**
* chamber directories by mount-option.
* The userid in the mount option is used as engine_id
*
* TODO : This won't work when chamber_dirs mount option comes before
* user_id option.
*/
printk("%s : chamber dirs : %s\n", __func__, chamber_dirs);
while ((token = strsep(&chamber_dirs, "|")) != NULL)
if(!is_chamber_directory(mount_crypt_stat, (const unsigned char *)token, NULL))
add_chamber_directory(mount_crypt_stat,
mount_crypt_stat->userid, (const unsigned char *)token);
}
break;
case ecryptfs_opt_partition_id: {
char *partition_id_str = args[0].from;
mount_crypt_stat->partition_id =
(int)simple_strtol(partition_id_str,
&partition_id_str, 0);
printk("%s : partition_id : %d", __func__, mount_crypt_stat->partition_id);
}
break;
#endif
case ecryptfs_opt_base:
base_path_src = args[0].from;
base_path_dst = propagate_stat->base_path;
strncpy(base_path_dst, base_path_src, ECRYPTFS_BASE_PATH_SIZE);
break;
case ecryptfs_opt_type:
propagate_type = match_strdup(&args[0]);
if (!propagate_type)
return -ENOMEM;
if (!strncmp(propagate_type, "default", strlen("default")))
propagate_stat->propagate_type = TYPE_E_DEFAULT;
else if (!strncmp(propagate_type, "read", strlen("read")))
propagate_stat->propagate_type = TYPE_E_READ;
else if (!strncmp(propagate_type, "write", strlen("write")))
propagate_stat->propagate_type = TYPE_E_WRITE;
else {
printk(KERN_WARNING
"%s: eCryptfs: unrecognized option [type=%s]\n",
__func__, propagate_type);
propagate_stat->propagate_type = TYPE_E_NONE;
}
kfree(propagate_type);
break;
case ecryptfs_opt_label:
label_src = args[0].from;
label_dst = propagate_stat->label;
strncpy(label_dst, label_src, ECRYPTFS_LABEL_SIZE);
break;
case ecryptfs_opt_err:
default:
printk(KERN_WARNING
@ -759,10 +661,6 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
goto out;
}
#ifdef CONFIG_SDP
sbi->userid = -1;
#endif
rc = ecryptfs_parse_options(sbi, raw_data, &check_ruid);
if (rc) {
err = "Error parsing options";

View File

@ -28,8 +28,6 @@
#include <linux/pagemap.h>
#include "ecryptfs_kernel.h"
#include "ecryptfs_dek.h"
extern spinlock_t inode_sb_list_lock;
static int ecryptfs_mm_debug = 0;

View File

@ -33,9 +33,6 @@
#include <linux/statfs.h>
#include <linux/magic.h>
#include "ecryptfs_kernel.h"
#ifdef CONFIG_SDP
#include "ecryptfs_dek.h"
#endif
struct kmem_cache *ecryptfs_inode_info_cache;
@ -63,10 +60,6 @@ static struct inode *ecryptfs_alloc_inode(struct super_block *sb)
mutex_init(&inode_info->lower_file_mutex);
atomic_set(&inode_info->lower_file_count, 0);
inode_info->lower_file = NULL;
#ifdef CONFIG_SDP
// get userid from super block
inode_info->crypt_stat.engine_id = -1;
#endif
inode = &inode_info->vfs_inode;
out:
return inode;
@ -170,16 +163,6 @@ static int ecryptfs_show_options(struct seq_file *m, struct dentry *root)
}
mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
#ifdef CONFIG_SDP
seq_printf(m, ",userid=%d", mount_crypt_stat->userid);
if (mount_crypt_stat->flags & ECRYPTFS_MOUNT_SDP_ENABLED){
seq_printf(m, ",sdp_enabled");
}
if (mount_crypt_stat->partition_id >= 0){
seq_printf(m, ",partition_id=%d", mount_crypt_stat->partition_id);
}
#endif
seq_printf(m, ",ecryptfs_cipher=%s",
mount_crypt_stat->global_default_cipher_name);

View File

@ -168,9 +168,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
mapping->assoc_mapping = NULL;
mapping->backing_dev_info = &default_backing_dev_info;
mapping->writeback_index = 0;
#ifdef CONFIG_SDP
mapping->userid = 0;
#endif
/*
* If the block_device provides a backing_dev_info for client

View File

@ -51,9 +51,6 @@ void get_derived_permission(struct dentry *parent, struct dentry *dentry)
struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
struct sdcardfs_inode_info *info = SDCARDFS_I(dentry->d_inode);
struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode);
#ifdef CONFIG_SDP
struct sdcardfs_dentry_info *parent_dinfo = SDCARDFS_D(parent);
#endif
appid_t appid;
/* By default, each inode inherits from its parent.
@ -157,19 +154,6 @@ void get_derived_permission(struct dentry *parent, struct dentry *dentry)
case PERM_ANDROID_KNOX_PACKAGE_DATA:
break;
}
#ifdef CONFIG_SDP
if((parent_info->perm == PERM_PRE_ROOT) && (parent_dinfo->under_knox) && (parent_dinfo->userid >= 0)) {
info->userid = parent_dinfo->userid;
}
if(parent_dinfo->under_knox) {
if(parent_dinfo->permission == PERMISSION_UNDER_ANDROID) {
if (parent_dinfo->appid != 0){
info->d_uid = multiuser_get_uid(parent_info->userid, parent_dinfo->appid);
}
}
}
#endif
}
/* set vfs_inode from sdcardfs_inode */

View File

@ -209,16 +209,12 @@ struct sdcardfs_dentry_info {
spinlock_t lock; /* protects lower_path */
struct path lower_path;
struct path orig_path;
#ifdef CONFIG_SDP
int under_knox;
int userid;
#define PERMISSION_PRE_ROOT 0
#define PERMISSION_ROOT 1
#define PERMISSION_ANDROID 2
#define PERMISSION_UNDER_ANDROID 3
int permission;
appid_t appid;
#endif
};
struct sdcardfs_mount_options {

View File

@ -669,9 +669,6 @@ struct address_space {
spinlock_t private_lock; /* for use by the address_space */
struct list_head private_list; /* ditto */
struct address_space *assoc_mapping; /* ditto */
#ifdef CONFIG_SDP
int userid;
#endif
} __attribute__((aligned(sizeof(long))));
/*
* On most architectures that alignment is already the case; but

View File

@ -24,9 +24,6 @@ enum mapping_flags {
AS_ENOSPC = __GFP_BITS_SHIFT + 1, /* ENOSPC on async write */
AS_MM_ALL_LOCKS = __GFP_BITS_SHIFT + 2, /* under mm_take_all_locks() */
AS_UNEVICTABLE = __GFP_BITS_SHIFT + 3, /* e.g., ramdisk, SHM_LOCK */
#ifdef CONFIG_SDP
AS_SENSITIVE = __GFP_BITS_SHIFT + 5, /* Group of sensitive pages to be cleaned up */
#endif
};
static inline void mapping_set_error(struct address_space *mapping, int error)
@ -71,25 +68,6 @@ static inline void mapping_set_gfp_mask(struct address_space *m, gfp_t mask)
(__force unsigned long)mask;
}
#ifdef CONFIG_SDP
static inline void mapping_set_sensitive(struct address_space *mapping)
{
set_bit(AS_SENSITIVE, &mapping->flags);
}
static inline void mapping_clear_sensitive(struct address_space *mapping)
{
clear_bit(AS_SENSITIVE, &mapping->flags);
}
static inline int mapping_sensitive(struct address_space *mapping)
{
if (mapping)
return test_bit(AS_SENSITIVE, &mapping->flags);
return !!mapping;
}
#endif
/*
* The page cache can done in larger chunks than
* one page, because it allows for more efficient

View File

@ -1629,9 +1629,6 @@ struct task_struct {
#ifdef CONFIG_HAVE_HW_BREAKPOINT
atomic_t ptrace_bp_refcnt;
#endif
#ifdef CONFIG_SDP
unsigned int sensitive;
#endif
};
/* Future-safe accessor for struct task_struct's cpus_allowed. */

View File

@ -1,28 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef PAGEMAP_H_
#define PAGEMAP_H_
#include <sdp/common.h>
#include <linux/pagemap.h>
void sdp_page_cleanup(struct page *page);
#endif /* PAGEMAP_H_ */

View File

@ -1,33 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef SDP_COMMON_H__
#define SDP_COMMON_H__
#define PER_USER_RANGE 100000
#define KNOX_PERSONA_BASE_ID 100
#define DEK_USER_ID_OFFSET 100
#define BASE_ID KNOX_PERSONA_BASE_ID
#define GET_ARR_IDX(__userid) (__userid - BASE_ID)
#define SDP_CACHE_CLEANUP_DEBUG 0
#endif

View File

@ -1,32 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _LINUX_DEK_AES_H
#define _LINUX_DEK_AES_H
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <sdp/dek_aes.h>
int dek_aes_encrypt(kek_t *kek, char *src, char *dst, int len);
int dek_aes_decrypt(kek_t *kek, char *src, char *dst, int len);
#endif

View File

@ -1,132 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DEK_COMMON_H__
#define DEK_COMMON_H__
// ==== kernel configs
#include <linux/limits.h>
#include <linux/ioctl.h>
#include <linux/device.h>
#include <sdp/common.h>
// ==== common configs
#define SDPK_DEFAULT_ALGOTYPE (SDPK_ALGOTYPE_ASYMM_ECDH)
#define SDPK_ALGOTYPE_ASYMM_RSA 0
#define SDPK_ALGOTYPE_ASYMM_DH 1
#define SDPK_ALGOTYPE_ASYMM_ECDH 2
//#define DEK_ENGINE_LOCAL_KEK
#define KEK_RSA_KEY_BITS 2048
#define KEK_MK_BITS 256
#define KEK_SS_BITS 256
#define DH_DEFAULT_GENERATOR DH_GENERATOR_2
#define DH_MAXLEN 256
#define DEK_NAME_LEN 256
#define DEK_LEN 32
#define DEK_MAXLEN 400 // TODO : need to optimize the length of EDEK DEK_RSA_KEY_BITS/8 : 256 bytes , DH2236 : 280 bytes
#define DEK_PW_LEN 32
#define KEK_MAXLEN (KEK_RSA_KEY_BITS/4+4)
#define KEK_MK_LEN (KEK_MK_BITS/8)
#define KEK_SS_LEN (KEK_SS_BITS/8)
#define DEK_AES_HEADER 44
#define FEK_MAXLEN 32
#define EFEK_MAXLEN (FEK_MAXLEN+16)
#define AES_BLOCK_SIZE 16
// DEK types
#define DEK_TYPE_PLAIN 0
#define DEK_TYPE_RSA_ENC 1
#define DEK_TYPE_AES_ENC 2
//#define DEK_TYPE_DH_PUB 4
#define DEK_TYPE_DH_ENC 5
#define DEK_TYPE_ECDH256_ENC 6
// KEK types
#define KEK_TYPE_SYM 10
#define KEK_TYPE_RSA_PUB 11
#define KEK_TYPE_RSA_PRIV 12
#define KEK_TYPE_DH_PUB 13
#define KEK_TYPE_DH_PRIV 14
#define KEK_TYPE_ECDH256_PUB 15
#define KEK_TYPE_ECDH256_PRIV 16
#define SDPK_PATH_MAX 256
#define SDPK_PATH_FMT "/data/system/users/%d/SDPK_%s"
#define SDPK_RPRI_NAME "Rpri"
#define SDPK_RPUB_NAME "Rpub"
#define SDPK_DPRI_NAME "Dpri"
#define SDPK_DPUB_NAME "Dpub"
#define SDPK_EDPRI_NAME "EDpri"
#define SDPK_EDPUB_NAME "EDpub"
#define SDPK_SYM_NAME "sym"
typedef struct _password{
unsigned int len;
unsigned char buf[DEK_MAXLEN];
}password_t;
typedef struct _key{
unsigned int type;
unsigned int len;
unsigned char buf[DEK_MAXLEN];
}dek_t;
typedef struct _kek{
unsigned int type;
unsigned int len;
unsigned char buf[KEK_MAXLEN];
}kek_t;
typedef struct _payload{
unsigned int efek_len;
unsigned int dpub_len;
unsigned char efek_buf[EFEK_MAXLEN];
unsigned char dpub_buf[DH_MAXLEN];
}dh_payload;
/* Debug */
#define DEK_DEBUG 0
#if DEK_DEBUG
#define DEK_LOGD(...) printk("dek: "__VA_ARGS__)
#else
#define DEK_LOGD(...)
#endif /* DEK_DEBUG */
#define DEK_LOGE(...) printk("dek: "__VA_ARGS__)
void key_dump(unsigned char *buf, int len);
int is_kek_available(int userid, int kek_type);
int dek_create_sysfs_asym_alg(struct device *d);
int dek_create_sysfs_key_dump(struct device *d);
int get_sdp_sysfs_asym_alg(void);
int get_sdp_sysfs_key_dump(void);
int is_root(void);
int is_current_epmd(void);
int is_current_adbd(void);
int is_system_server(void);
#endif

View File

@ -1,104 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DEK_IOCTL_H_
#define DEK_IOCTL_H_
#include <sdp/dek_common.h>
#define __DEKIOC 0x77
typedef struct _dek_arg_generate_dek {
int engine_id;
dek_t dek;
}dek_arg_generate_dek;
typedef struct _dek_arg_encrypt_dek {
int engine_id;
dek_t plain_dek;
dek_t enc_dek;
}dek_arg_encrypt_dek;
typedef struct _dek_arg_decrypt_dek {
int engine_id;
dek_t plain_dek;
dek_t enc_dek;
}dek_arg_decrypt_dek;
typedef struct _dek_arg_is_kek_avail {
int engine_id;
int kek_type;
int ret;
}dek_arg_is_kek_avail;
/*
* DEK_ON_BOOT indicates that there's persona in the system.
*
* The driver will load public key and encrypted private key.
*/
typedef struct _dek_arg_on_boot {
int engine_id;
int user_id;
kek_t SDPK_Rpub;
kek_t SDPK_Dpub;
kek_t SDPK_EDpub;
}dek_arg_on_boot;
typedef struct _dek_arg_on_device_locked {
int engine_id;
int user_id;
}dek_arg_on_device_locked;
typedef struct _dek_arg_on_device_unlocked {
int engine_id;
kek_t SDPK_Rpri;
kek_t SDPK_Dpri;
kek_t SDPK_EDpri;
kek_t SDPK_sym;
}dek_arg_on_device_unlocked;
typedef struct _dek_arg_on_user_added {
int engine_id;
int user_id;
kek_t SDPK_Rpub;
kek_t SDPK_Dpub;
kek_t SDPK_EDpub;
}dek_arg_on_user_added;
typedef struct _dek_arg_on_user_removed {
int engine_id;
int user_id;
}dek_arg_on_user_removed, dek_arg_disk_cache_cleanup;
// SDP driver events
#define DEK_ON_BOOT _IOW(__DEKIOC, 0, unsigned int)
#define DEK_ON_DEVICE_LOCKED _IOW(__DEKIOC, 4, unsigned int)
#define DEK_ON_DEVICE_UNLOCKED _IOW(__DEKIOC, 5, unsigned int)
#define DEK_ON_USER_ADDED _IOW(__DEKIOC, 6, unsigned int)
#define DEK_ON_USER_REMOVED _IOW(__DEKIOC, 7, unsigned int)
#define DEK_ON_CHANGE_PASSWORD _IOW(__DEKIOC, 8, unsigned int) // @Deprecated
// SDP driver DEK requests
#define DEK_GENERATE_DEK _IOW(__DEKIOC, 1, unsigned int)
#define DEK_ENCRYPT_DEK _IOW(__DEKIOC, 2, unsigned int)
#define DEK_DECRYPT_DEK _IOR(__DEKIOC, 3, unsigned int)
#define DEK_GET_KEK _IOW(__DEKIOC, 9, unsigned int)
#define DEK_DISK_CACHE_CLEANUP _IOW(__DEKIOC, 10, unsigned int)
#define DEK_IS_KEK_AVAIL _IOW(__DEKIOC, 11, unsigned int)
#endif /* DEK_IOCTL_H_ */

View File

@ -1,44 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DLP_IOCTL_H_
#define DLP_IOCTL_H_
#include <linux/types.h>
#include <linux/ioctl.h>
#define DLP_DEV_PATH "/dev/sdp_dlp"
#define __DLPIOC 0x78
#define MAX_EXT_LENGTH 1000
typedef struct _dlp_lock_set {
int user_id;
} dlp_lock_set;
typedef struct _dlp_extension_set {
int user_id;
char extensions[MAX_EXT_LENGTH+1];
} dlp_extension_set;
#define DLP_LOCK_ENABLE _IOW(__DLPIOC, 1, dlp_lock_set)
#define DLP_LOCK_DISABLE _IOW(__DLPIOC, 2, dlp_lock_set)
#define DLP_EXTENSION_SET _IOW(__DLPIOC, 3, dlp_extension_set)
#endif /* DLP_IOCTL_H_ */

View File

@ -1,80 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _SDP_FS_HANDLER_H
#define _SDP_FS_HANDLER_H
#include <sdp/dek_common.h>
#include <sdp/fs_request.h>
#include <linux/list.h>
#include <linux/wait.h>
#include <linux/spinlock.h>
#include <linux/limits.h>
#define SDP_FS_HANDLER_NETLINK 28
#define SDP_FS_HANDLER_PID_SET 3001
#define SDP_FS_HANDLER_RESULT 3002
#define OP_SDP_SET_DIR_SENSITIVE 10
#define OP_SDP_SET_DIR_PROTECTED 11
#define OP_SDP_ERROR 99
typedef struct result {
u32 request_id;
u8 opcode;
s16 ret;
}result_t;
/** The request state */
enum req_state {
SDP_FS_HANDLER_REQ_INIT = 0,
SDP_FS_HANDLER_REQ_PENDING,
SDP_FS_HANDLER_REQ_FINISHED
};
typedef struct __sdp_fs_handler_contorl {
struct list_head pending_list;
//wait_queue_head_t waitq;
spinlock_t lock;
/** The next unique request id */
u32 reqctr;
}sdp_fs_handler_control_t;
typedef struct __sdp_fs_handler_request {
u32 id;
u8 opcode;
struct list_head list;
/** refcount */
atomic_t count;
enum req_state state;
sdp_fs_command_t command;
result_t result;
fs_request_cb_t callback;
/** The request was aborted */
u8 aborted;
}sdp_fs_handler_request_t;
#endif

View File

@ -1,73 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef FS_REQUEST_H_
#define FS_REQUEST_H_
#include <linux/slab.h>
#define FSOP_SDP_SET_SENSITIVE 10
#define FSOP_SDP_SET_PROTECTED 11
#define FSOP_DLP_FILE_OPENED 21
#define FSOP_DLP_FILE_CLOSED 22
#define FSOP_DLP_FILE_INIT 23
#define FSOP_DLP_FILE_INIT_RESTRICTED 24
#define FSOP_DLP_FILE_REMOVE 25
#define FSOP_DLP_FILE_RENAME 26
#define FSOP_AUDIT_FAIL_ENCRYPT 51
#define FSOP_AUDIT_FAIL_DECRYPT 52
// opcode, ret, inode
typedef void (*fs_request_cb_t)(int, int, unsigned long);
typedef struct sdp_fs_command {
int req_id;
int opcode;
int user_id;
int part_id;
unsigned long ino;
int pid;
}sdp_fs_command_t;
extern int sdp_fs_request(sdp_fs_command_t *sdp_req, fs_request_cb_t callback);
static inline sdp_fs_command_t *sdp_fs_command_alloc(int opcode, int pid,
int userid, int partid, unsigned long ino, gfp_t gfp) {
sdp_fs_command_t *cmd;
cmd = kmalloc(sizeof(sdp_fs_command_t), gfp);
cmd->opcode = opcode;
cmd->pid = pid;
cmd->user_id = userid;
cmd->part_id = partid;
cmd->ino = ino;
return cmd;
}
static inline void sdp_fs_command_free(sdp_fs_command_t *cmd)
{
kzfree(cmd);
}
#endif /* FS_REQUEST_H_ */

View File

@ -1,39 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _SDP_KEK_PACK_H_
#define _SDP_KEK_PACK_H_
#include <sdp/dek_common.h>
void init_kek_pack(void);
int add_kek_pack(int engine_id, int userid);
void del_kek_pack(int engine_id);
int add_kek(int engine_id, kek_t *kek);
int del_kek(int engine_id, int kek_type);
kek_t *get_kek(int engine_id, int kek_type, int *rc);
void put_kek(kek_t *kek);
int is_kek_pack(int engine_id);
int is_kek(int engine_id, int kek_type);
#endif /* _SDP_KEK_PACK_H_ */

View File

@ -1,94 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _FIPS_CRYPTO_H
#define _FIPS_CRYPTO_H
#include <sdp/dek_common.h>
#include <linux/list.h>
#include <linux/wait.h>
#include <linux/spinlock.h>
#define OP_RSA_ENC 10
#define OP_RSA_DEC 11
#define OP_DH_DEC 12
#define OP_DH_ENC 13
#define OP_ECDH_DEC 14
#define OP_ECDH_ENC 15
#define PUB_CRYPTO_ERROR 99
typedef struct __cipher_param {
u32 request_id;
u8 opcode;
dek_t in;
kek_t key;
}cipher_param_t;
typedef struct result {
u32 request_id;
u8 opcode;
s16 ret;
dek_t dek;
}result_t;
/** The request state */
enum req_state {
PUB_CRYPTO_REQ_INIT = 0,
PUB_CRYPTO_REQ_PENDING,
PUB_CRYPTO_REQ_FINISHED
};
typedef struct pub_crypto_contorl {
struct list_head pending_list;
//wait_queue_head_t waitq;
spinlock_t lock;
/** The next unique request id */
u32 reqctr;
}pub_crypto_control_t;
typedef struct pub_crypto_request {
u32 id;
u8 opcode;
struct list_head list;
/** refcount */
atomic_t count;
wait_queue_head_t waitq;
enum req_state state;
cipher_param_t cipher_param;
result_t result;
/** The request was aborted */
u8 aborted;
}pub_crypto_request_t;
int rsa_encryptByPub(dek_t *dek, dek_t *edek, kek_t *key);
int rsa_decryptByPair(dek_t *edek, dek_t *dek, kek_t *key);
int dh_decryptEDEK(dek_t *edek, dek_t *dek, kek_t *key);
int dh_encryptDEK(dek_t *dek, dek_t *edek, kek_t *key);
int ecdh_decryptEDEK(dek_t *edek, dek_t *dek, kek_t *key);
int ecdh_encryptDEK(dek_t *dek, dek_t *edek, kek_t *key);
#endif

View File

@ -1,55 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _UAPI_SDP_MM_H_
#define _UAPI_SDP_MM_H_
#include <linux/types.h>
#include <linux/ioctl.h>
#define MAX_SENSITIVE_PROC 100
/*
* struct sdp_mm_sensitive_proc_req - for setting the process as sensitive
* @proc_id - process id of the process to be set (as sensitive)
*/
struct sdp_mm_sensitive_proc_req {
unsigned int proc_id; /* in */
};
/*
* struct sdp_mm_sensitive_proc_list_resp - for querying sensitive process list
* @sensitive_proc_list_len - number of sensitive processes in the list
* @sensitive_proc_list - sensitive process list
*/
struct sdp_mm_sensitive_proc_list_resp {
unsigned int sensitive_proc_list_len;
unsigned int sensitive_proc_list[MAX_SENSITIVE_PROC];
};
#define SDP_MM_IOC_MAGIC 0x77
#define SDP_MM_IOCTL_PROC_SENSITIVE_QUERY_REQ \
_IOWR(SDP_MM_IOC_MAGIC, 1, struct sdp_mm_sensitive_proc_list_resp)
#define SDP_MM_IOCTL_SET_SENSITIVE_PROC_REQ \
_IOWR(SDP_MM_IOC_MAGIC, 2, struct sdp_mm_sensitive_proc_req)
#endif /* _UAPI_SDP_MM_H_ */

View File

@ -507,10 +507,6 @@ config MIN_DIRTY_THRESH_PAGES
disables this option.)
Do not use it if you unsure.
config SDP_CACHE_CLEANUP
bool "SDP requirement. cache cleanup"
depends on SDP
default n
config MMAP_READAROUND_LIMIT
int "Limit mmap readaround upperbound"
@ -518,4 +514,4 @@ config MMAP_READAROUND_LIMIT
help
Inappropriate mmap readaround size can hurt device performance
during the sluggish situation. Add the hard upper-limit for
mmap readaround.
mmap readaround.

View File

@ -36,10 +36,6 @@
#include <linux/cleancache.h>
#include "internal.h"
#ifdef CONFIG_SDP
#include <sdp/cache_cleanup.h>
#endif
/*
* FIXME: remove all knowledge of the buffer layer from the core VM
*/
@ -118,11 +114,6 @@ void __delete_from_page_cache(struct page *page)
{
struct address_space *mapping = page->mapping;
#ifdef CONFIG_SDP
if(mapping_sensitive(mapping))
sdp_page_cleanup(page);
#endif
/*
* if we're uptodate, flush out into the cleancache, otherwise
* invalidate any existing cleancache entries. We can't leave

View File

@ -33,7 +33,3 @@ obj-$(CONFIG_TIMA_UEVENT) += tima_uevent/
#TZ ICCC
obj-$(CONFIG_TZ_ICCC) += tz_iccc/
# Knox SDP
obj-$(CONFIG_SDP) += sdp/
obj-$(CONFIG_SDP) += sdp/built-in.o

View File

@ -1,7 +0,0 @@
#
# Makefile for DEK and DLP modules
#
obj-$(CONFIG_SDP) += dek.o dek_aes.o sdp_mm.o pub_crypto_emul.o dek_sysfs.o cache_cleanup.o kek_pack.o fs_handler.o
obj-$(CONFIG_DLP) += sdp_dlp.o

View File

@ -1,70 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <sdp/common.h>
#include <sdp/cache_cleanup.h>
#if SDP_CACHE_CLEANUP_DEBUG
static void sdp_page_dump(unsigned char *buf, int len, const char* str)
{
unsigned int i;
char s[512];
s[0] = 0;
for(i=0;i<len && i<32;++i) {
char tmp[8];
sprintf(tmp, " %02x", buf[i]);
strcat(s, tmp);
}
if (len > 32) {
char tmp[8];
sprintf(tmp, " ...");
strcat(s, tmp);
}
printk("%s [%s len=%d]\n", s, str, len);
}
#else
static void sdp_page_dump(unsigned char *buf, int len, const char* str) {
return;
}
#endif
void sdp_page_cleanup(struct page *page)
{
if(page && page->mapping) {
if(mapping_sensitive(page->mapping)) {
void *d;
#if SDP_CACHE_CLEANUP_DEBUG
printk("%s : deleting [%s] sensitive page.\n",
__func__, page->mapping->host->i_sb->s_type->name);
//dump_stack();
#endif
d = kmap_atomic(page);
if(d) {
sdp_page_dump((unsigned char *)d, PAGE_SIZE, "freeing");
clear_page(d);
sdp_page_dump((unsigned char *)d, PAGE_SIZE, "freed");
kunmap_atomic(d);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,107 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <linux/err.h>
#include <sdp/dek_common.h>
#include <sdp/dek_aes.h>
static struct crypto_blkcipher *dek_aes_key_setup(kek_t *kek)
{
struct crypto_blkcipher *tfm = NULL;
tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
if (!IS_ERR(tfm)) {
crypto_blkcipher_setkey(tfm, kek->buf, kek->len);
} else {
printk("dek: failed to alloc blkcipher\n");
}
return tfm;
}
static void dek_aes_key_free(struct crypto_blkcipher *tfm)
{
crypto_free_blkcipher(tfm);
}
static int __dek_aes_encrypt(struct crypto_blkcipher *tfm, char *src, char *dst, int len) {
struct blkcipher_desc desc;
struct scatterlist src_sg, dst_sg;
int bsize = crypto_blkcipher_ivsize(tfm);
u8 iv[bsize];
memset(&iv, 0, sizeof(iv));
desc.tfm = tfm;
desc.info = iv;
desc.flags = 0;
sg_init_one(&src_sg, src, len);
sg_init_one(&dst_sg, dst, len);
return crypto_blkcipher_encrypt_iv(&desc, &dst_sg, &src_sg, len);
}
static int __dek_aes_decrypt(struct crypto_blkcipher *tfm, char *src, char *dst, int len) {
struct blkcipher_desc desc;
struct scatterlist src_sg, dst_sg;
int bsize = crypto_blkcipher_ivsize(tfm);
u8 iv[bsize];
memset(&iv, 0, sizeof(iv));
desc.tfm = tfm;
desc.info = iv;
desc.flags = 0;
sg_init_one(&src_sg, src, len);
sg_init_one(&dst_sg, dst, len);
return crypto_blkcipher_decrypt_iv(&desc, &dst_sg, &src_sg, len);
}
int dek_aes_encrypt(kek_t *kek, char *src, char *dst, int len) {
int rc;
struct crypto_blkcipher *tfm;
if(kek == NULL) return -EINVAL;
tfm = dek_aes_key_setup(kek);
if(tfm) {
rc = __dek_aes_encrypt(tfm, src, dst, len);
dek_aes_key_free(tfm);
return rc;
} else
return -ENOMEM;
}
int dek_aes_decrypt(kek_t *kek, char *src, char *dst, int len) {
int rc;
struct crypto_blkcipher *tfm;
if(kek == NULL) return -EINVAL;
tfm = dek_aes_key_setup(kek);
if(tfm) {
rc = __dek_aes_decrypt(tfm, src, dst, len);
dek_aes_key_free(tfm);
return rc;
} else
return -ENOMEM;
}

View File

@ -1,129 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <linux/kernel.h>
#include <linux/stat.h>
#include <linux/string.h>
#include <sdp/dek_common.h>
static int g_asym_alg = SDPK_DEFAULT_ALGOTYPE;
#define ALG_NAME_RSA_NAME "RSA"
#define ALG_NAME_DH_NAME "DH"
#define ALG_NAME_ECDH_NAME "ECDH"
static ssize_t dek_show_asym_alg(struct device *dev,
struct device_attribute *attr, char *buf) {
switch(g_asym_alg) {
case SDPK_ALGOTYPE_ASYMM_RSA:
return sprintf(buf, "%s\n", ALG_NAME_RSA_NAME);
case SDPK_ALGOTYPE_ASYMM_DH:
return sprintf(buf, "%s\n", ALG_NAME_DH_NAME);
case SDPK_ALGOTYPE_ASYMM_ECDH:
return sprintf(buf, "%s\n", ALG_NAME_ECDH_NAME);
default:
return sprintf(buf, "unknown\n");
}
return 0;
}
static ssize_t dek_set_asym_alg(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count) {
if(!strncmp(ALG_NAME_RSA_NAME, buf, strlen(ALG_NAME_RSA_NAME))) {
g_asym_alg = SDPK_ALGOTYPE_ASYMM_RSA;
return strlen(ALG_NAME_RSA_NAME);
}
if(!strncmp(ALG_NAME_DH_NAME, buf, strlen(ALG_NAME_DH_NAME))) {
g_asym_alg = SDPK_ALGOTYPE_ASYMM_DH;
return strlen(ALG_NAME_DH_NAME);
}
if(!strncmp(ALG_NAME_ECDH_NAME, buf, strlen(ALG_NAME_ECDH_NAME))) {
g_asym_alg = SDPK_ALGOTYPE_ASYMM_ECDH;
return strlen(ALG_NAME_ECDH_NAME);
}
return -1;
}
static DEVICE_ATTR(asym_alg, S_IRUSR | S_IWUSR, dek_show_asym_alg, dek_set_asym_alg);
int dek_create_sysfs_asym_alg(struct device *d) {
int error;
if((error = device_create_file(d, &dev_attr_asym_alg)))
return error;
return 0;
}
int get_sdp_sysfs_asym_alg(void) {
return g_asym_alg;
}
#ifdef CONFIG_SDP_KEY_DUMP
static int kek_dump = 0;
static ssize_t dek_show_key_dump(struct device *dev,
struct device_attribute *attr, char *buf) {
return sprintf(buf, "%d\n", kek_dump);
}
static ssize_t dek_set_key_dump(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count) {
int flag = simple_strtoul(buf, NULL, 10);
kek_dump = flag;
return strlen(buf);
}
static DEVICE_ATTR(key_dump, S_IRUGO | S_IWUGO, dek_show_key_dump, dek_set_key_dump);
int dek_create_sysfs_key_dump(struct device *d) {
int error;
if((error = device_create_file(d, &dev_attr_key_dump)))
return error;
return 0;
}
int get_sdp_sysfs_key_dump(void) {
return kek_dump;
}
#else
int dek_create_sysfs_key_dump(struct device *d) {
printk("key_dump feature not available");
return 0;
}
int get_sdp_sysfs_key_dump(void) {
printk("key_dump feature not available");
return 0;
}
#endif

View File

@ -1,352 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <crypto/internal/hash.h>
#include <crypto/scatterwalk.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/wakelock.h>
#include <linux/sched.h>
#include <linux/netlink.h>
#include <linux/net.h>
#include <net/netlink.h>
#include <net/sock.h>
#include <net/net_namespace.h>
#include <linux/types.h>
#include <linux/wait.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/audit.h>
#include <linux/jiffies.h>
#include <linux/version.h>
#include <sdp/fs_handler.h>
#include <sdp/fs_request.h>
#define RESULT_ARRAY_MAX_LEN 100
#define CRYPTO_MAX_TIMEOUT HZ/5
#define SDP_FS_HANDLER_REQ_TIMEOUT 3000
sdp_fs_handler_control_t g_sdp_fs_handler_control;
DEFINE_MUTEX(g_send_mutex);
static int g_user_pid = 0;
static struct sock* g_sock = NULL;
static int to_netlink_msg(sdp_fs_handler_request_t *req, char **msg);
static void request_send(sdp_fs_handler_control_t *con,
sdp_fs_handler_request_t *req);
static sdp_fs_handler_request_t *request_find(sdp_fs_handler_control_t *con,
u32 request_id);
static sdp_fs_handler_request_t *request_alloc(u32 opcode);
static void request_free(sdp_fs_handler_request_t *req);
static void req_dump(sdp_fs_handler_request_t *req, const char *msg);
/* Debug */
#define SDP_FS_HANDLER_DEBUG 0
#if SDP_FS_HANDLER_DEBUG
#define SDP_FS_HANDLER_LOGD(FMT, ...) printk("SDP_FS_HANDLER[%d] : %s " FMT , current->pid, __func__, ##__VA_ARGS__)
#else
#define SDP_FS_HANDLER_LOGD(FMT, ...)
#endif /* SDP_FS_HANDLER_DEBUG */
#define SDP_FS_HANDLER_LOGE(FMT, ...) printk("SDP_FS_HANDLER[%d] : %s " FMT , current->pid, __func__, ##__VA_ARGS__)
static int __handle_request(sdp_fs_handler_request_t *req, char *ret) {
int rc = 0;
struct sk_buff *skb_in = NULL;
struct sk_buff *skb_out = NULL;
struct nlmsghdr *nlh = NULL;
char *nl_msg = NULL;
int nl_msg_size = 0;
SDP_FS_HANDLER_LOGD("====================== \t entred\n");
if(req == NULL) {
SDP_FS_HANDLER_LOGE("invalid request\n");
return -1;
}
request_send(&g_sdp_fs_handler_control, req);
nl_msg_size = to_netlink_msg(req, &nl_msg);
if(nl_msg_size <= 0) {
SDP_FS_HANDLER_LOGE("invalid opcode %d\n", req->opcode);
return -1;
}
// sending netlink message
skb_in = nlmsg_new(nl_msg_size, 0);
if (!skb_in) {
SDP_FS_HANDLER_LOGE("Failed to allocate new skb: \n");
return -1;
}
nlh = nlmsg_put(skb_in, 0, 0, NLMSG_DONE, nl_msg_size, 0);
NETLINK_CB(skb_in).dst_group = 0;
memcpy(nlmsg_data(nlh), nl_msg, nl_msg_size);
mutex_lock(&g_send_mutex);
rc = nlmsg_unicast(g_sock, skb_in, g_user_pid);
mutex_unlock(&g_send_mutex);
skb_out = skb_dequeue(&g_sock->sk_receive_queue);
if(skb_out) {
kfree_skb(skb_out);
}
return 0;
}
int sdp_fs_request(sdp_fs_command_t *cmd, fs_request_cb_t callback){
sdp_fs_handler_request_t *req = request_alloc(cmd->opcode);
int ret = -1;
req_dump(req, "request allocated");
if(req) {
memcpy(&req->command, cmd, sizeof(sdp_fs_command_t));
req->command.req_id = req->id;
req_dump(req, "__handle_reqeust start");
ret = __handle_request(req, NULL);
req_dump(req, "__handle_reqeust end");
if(ret != 0) {
SDP_FS_HANDLER_LOGE("opcode[%d] failed\n", cmd->opcode);
goto error;
}
} else {
SDP_FS_HANDLER_LOGE("request allocation failed\n");
return -ENOMEM;
}
return 0;
error:
request_free(req);
return -1;
}
static int __recver(struct sk_buff *skb, struct nlmsghdr *nlh)
{
void *data;
u16 msg_type = nlh->nlmsg_type;
u32 err = 0;
struct audit_status *status_get = NULL;
u16 len = 0;
data = NLMSG_DATA(nlh);
len = ntohs(*(uint16_t*) (data+1));
switch (msg_type) {
case SDP_FS_HANDLER_PID_SET:
status_get = (struct audit_status *)data;
g_user_pid = status_get->pid;
break;
case SDP_FS_HANDLER_RESULT:
{
result_t *result = (result_t *)data;
sdp_fs_handler_request_t *req = NULL;
printk("result : req_id[%d], opcode[%d] ret[%d]\n",
result->request_id, result->opcode, result->ret);
spin_lock(&g_sdp_fs_handler_control.lock);
req = request_find(&g_sdp_fs_handler_control, result->request_id);
spin_unlock(&g_sdp_fs_handler_control.lock);
if(req == NULL) {
SDP_FS_HANDLER_LOGE("crypto result :: error! can't find request %d\n",
result->request_id);
} else {
memcpy(&req->result, result, sizeof(result_t));
req->state = SDP_FS_HANDLER_REQ_FINISHED;
if(req->callback)
req->callback(req->opcode, req->result.ret, req->command.ino);
memset(result, 0, sizeof(result_t));
request_free(req);
}
break;
}
default:
SDP_FS_HANDLER_LOGE("unknown message type : %d\n", msg_type);
break;
}
return err;
}
/* Receive messages from netlink socket. */
static void recver(struct sk_buff *skb)
{
struct nlmsghdr *nlh;
int len;
int err;
nlh = nlmsg_hdr(skb);
len = skb->len;
err = __recver(skb, nlh);
}
static int to_netlink_msg(sdp_fs_handler_request_t *req, char **msg)
{
*msg = (char *)&req->command;
return sizeof(sdp_fs_command_t);
}
static u32 get_unique_id(sdp_fs_handler_control_t *control)
{
SDP_FS_HANDLER_LOGD("locked\n");
spin_lock(&control->lock);
control->reqctr++;
/* zero is special */
if (control->reqctr == 0)
control->reqctr = 1;
spin_unlock(&control->lock);
SDP_FS_HANDLER_LOGD("unlocked\n");
return control->reqctr;
}
static void req_dump(sdp_fs_handler_request_t *req, const char *msg) {
#if SDP_FS_HANDLER_DEBUG
SDP_FS_HANDLER_LOGD("DUMP REQUEST [%s] ID[%d] opcode[%d] state[%d]\n", msg, req->id, req->opcode, req->state);
#endif
}
static void request_send(sdp_fs_handler_control_t *con,
sdp_fs_handler_request_t *req) {
spin_lock(&con->lock);
SDP_FS_HANDLER_LOGD("entered, control lock\n");
list_add_tail(&req->list, &con->pending_list);
req->state = SDP_FS_HANDLER_REQ_PENDING;
SDP_FS_HANDLER_LOGD("exit, control unlock\n");
spin_unlock(&con->lock);
}
static sdp_fs_handler_request_t *request_find(sdp_fs_handler_control_t *con,
u32 request_id) {
struct list_head *entry;
list_for_each(entry, &con->pending_list) {
sdp_fs_handler_request_t *req;
req = list_entry(entry, sdp_fs_handler_request_t, list);
if (req->id == request_id)
return req;
}
return NULL;
}
static struct kmem_cache *req_cachep;
static void request_init(sdp_fs_handler_request_t *req, u32 opcode) {
memset(req, 0, sizeof(sdp_fs_handler_request_t));
req->state = SDP_FS_HANDLER_REQ_INIT;
req->id = get_unique_id(&g_sdp_fs_handler_control);
INIT_LIST_HEAD(&req->list);
atomic_set(&req->count, 1);
req->aborted = 0;
req->opcode = opcode;
req->callback = NULL;
}
static sdp_fs_handler_request_t *request_alloc(u32 opcode) {
sdp_fs_handler_request_t *req = kmem_cache_alloc(req_cachep, GFP_KERNEL);
if(req)
request_init(req, opcode);
return req;
}
static void request_free(sdp_fs_handler_request_t *req)
{
if(req) {
req_dump(req, "request freed");
/*
* TODO : lock needed here?
*/
list_del(&req->list);
memset(req, 0, sizeof(sdp_fs_handler_request_t));
kmem_cache_free(req_cachep, req);
} else {
SDP_FS_HANDLER_LOGE("req is NULL, skip free\n");
}
}
static void control_init(sdp_fs_handler_control_t *con) {
SDP_FS_HANDLER_LOGD("sdp_fs_handler_control_init");
spin_lock_init(&con->lock);
INIT_LIST_HEAD(&con->pending_list);
con->reqctr = 0;
}
static int __init sdp_fs_handler_mod_init(void) {
#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,4,0))
struct netlink_kernel_cfg cfg = {
.input = recver,
};
g_sock = netlink_kernel_create(&init_net, SDP_FS_HANDLER_NETLINK, &cfg);
#else
g_sock = netlink_kernel_create(&init_net, SDP_FS_HANDLER_NETLINK, 0, recver, NULL, THIS_MODULE);
#endif
if (!g_sock) {
SDP_FS_HANDLER_LOGE("Failed to create Crypto Netlink Socket .. Exiting \n");
return -ENOMEM;
}
SDP_FS_HANDLER_LOGE("netlink socket is created successfully! \n");
control_init(&g_sdp_fs_handler_control);
req_cachep = kmem_cache_create("sdp_fs_handler_requst",
sizeof(sdp_fs_handler_request_t),
0, 0, NULL);
if (!req_cachep) {
netlink_kernel_release(g_sock);
SDP_FS_HANDLER_LOGE("Failed to create sdp_fs_handler_requst cache mem.. Exiting \n");
return -ENOMEM;
}
return 0;
}
static void __exit sdp_fs_handler_mod_exit(void) {
netlink_kernel_release(g_sock);
kmem_cache_destroy(req_cachep);
}
module_init(sdp_fs_handler_mod_init);
module_exit(sdp_fs_handler_mod_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SDP FS netlink");

View File

@ -1,334 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <sdp/dek_common.h>
typedef struct __kek_pack {
int engine_id;
int user_id;
struct list_head list;
struct list_head kek_list_head;
spinlock_t kek_list_lock;
}kek_pack_t;
typedef struct __kek_item {
struct list_head list;
int kek_type;
kek_t kek;
}kek_item_t;
#define KEK_PACK_DEBUG 0
#if KEK_PACK_DEBUG
#define KEK_PACK_LOGD(FMT, ...) printk("KEK_PACK[%d] %s :: " FMT , current->pid, __func__, ##__VA_ARGS__)
#else
#define KEK_PACK_LOGD(FMT, ...)
#endif /* PUB_CRYPTO_DEBUG */
#define KEK_PACK_LOGE(FMT, ...) printk("KEK_PACK[%d] %s :: " FMT , current->pid, __func__, ##__VA_ARGS__)
struct list_head kek_pack_list_head;
spinlock_t kek_pack_list_lock;
spinlock_t del_kek_pack_lock;
void init_kek_pack(void) {
spin_lock_init(&kek_pack_list_lock);
spin_lock_init(&del_kek_pack_lock);
INIT_LIST_HEAD(&kek_pack_list_head);
}
static kek_pack_t *find_kek_pack(int engine_id) {
struct list_head *entry;
spin_lock(&kek_pack_list_lock);
list_for_each(entry, &kek_pack_list_head) {
kek_pack_t *pack = list_entry(entry, kek_pack_t, list);
if(pack->engine_id == engine_id) {
KEK_PACK_LOGD("Found kek-pack : %d\n", engine_id);
spin_unlock(&kek_pack_list_lock);
return pack;
}
}
spin_unlock(&kek_pack_list_lock);
KEK_PACK_LOGE("Can't find kek-pack : %d\n", engine_id);
return NULL;
}
static int __add_kek(kek_pack_t *pack, kek_t *kek, kek_item_t *item) {
if(kek == NULL) return -EINVAL;
if(pack == NULL) return -EINVAL;
INIT_LIST_HEAD(&item->list);
item->kek_type = kek->type;
memcpy(&item->kek, kek, sizeof(kek_t));
list_add_tail(&item->list, &pack->kek_list_head);
KEK_PACK_LOGD("item %p\n", item);
return 0;
}
static kek_item_t *find_kek_item(kek_pack_t *pack, int kek_type) {
struct list_head *entry;
if(pack == NULL) return NULL;
list_for_each(entry, &pack->kek_list_head) {
kek_item_t *item = list_entry(entry, kek_item_t, list);
if(item->kek_type == kek_type) {
KEK_PACK_LOGD("Found kek-item : %d\n", kek_type);
return item;
}
}
KEK_PACK_LOGD("Can't find kek %d : %d\n", kek_type, pack->engine_id);
return NULL;
}
static void del_kek_item(kek_item_t *item) {
KEK_PACK_LOGD("entered\n");
if(item) {
list_del(&item->list);
kzfree(item);
} else {
KEK_PACK_LOGD("given item is NULL\n");
}
}
int add_kek_pack(int engine_id, int user_id) {
kek_pack_t *new_kek_pack;
KEK_PACK_LOGD("entered\n");
if(find_kek_pack(engine_id)) {
KEK_PACK_LOGE("kek-pack for %d already exists\n", engine_id);
return -EEXIST;
}
new_kek_pack = kmalloc(sizeof(kek_pack_t), GFP_KERNEL);
if(new_kek_pack == NULL) {
KEK_PACK_LOGE("can't alloc memory for kek_pack_t\n");
return -EINVAL;
}
new_kek_pack->engine_id = engine_id;
new_kek_pack->user_id = user_id;
spin_lock_init(&new_kek_pack->kek_list_lock);
INIT_LIST_HEAD(&new_kek_pack->kek_list_head);
spin_lock(&kek_pack_list_lock);
list_add_tail(&new_kek_pack->list, &kek_pack_list_head);
spin_unlock(&kek_pack_list_lock);
return 0;
}
void del_kek_pack(int engine_id) {
struct list_head *entry, *q;
kek_pack_t *pack;
spin_lock(&del_kek_pack_lock);
KEK_PACK_LOGD("entered\n");
pack = find_kek_pack(engine_id);
if (pack == NULL) {
spin_unlock(&del_kek_pack_lock);
return;
}
spin_lock(&pack->kek_list_lock);
list_for_each_safe(entry, q, &pack->kek_list_head) {
kek_item_t *item = list_entry(entry, kek_item_t, list);
KEK_PACK_LOGD("entry %p item %p\n", entry, item);
del_kek_item(item);
}
spin_unlock(&pack->kek_list_lock);
list_del(&pack->list);
kzfree(pack);
spin_unlock(&del_kek_pack_lock);
}
int add_kek(int engine_id, kek_t *kek) {
int rc;
kek_pack_t *pack;
kek_item_t *item;
item = kmalloc(sizeof(kek_item_t), GFP_KERNEL);
if (item == NULL) {
return -ENOMEM;
}
spin_lock(&del_kek_pack_lock);
KEK_PACK_LOGD("entered\n");
pack = find_kek_pack(engine_id);
if (pack == NULL) {
spin_unlock(&del_kek_pack_lock);
kzfree(item);
return -ENOENT;
}
spin_lock(&pack->kek_list_lock);
if (find_kek_item(pack, kek->type)) {
spin_unlock(&pack->kek_list_lock);
spin_unlock(&del_kek_pack_lock);
kzfree(item);
return -EEXIST;
}
rc = __add_kek(pack, kek, item);
spin_unlock(&pack->kek_list_lock);
spin_unlock(&del_kek_pack_lock);
if (rc) {
KEK_PACK_LOGE("%s failed. rc = %d", __func__, rc);
kzfree(item);
}
return rc;
}
int del_kek(int engine_id, int kek_type) {
kek_pack_t *pack;
kek_item_t *item;
KEK_PACK_LOGD("entered\n");
pack = find_kek_pack(engine_id);
if(pack == NULL) return -ENOENT;
spin_lock(&pack->kek_list_lock);
item = find_kek_item(pack, kek_type);
if (item == NULL) {
spin_unlock(&pack->kek_list_lock);
return -ENOENT;
}
del_kek_item(item);
spin_unlock(&pack->kek_list_lock);
return 0;
}
/*
* I wanted to have some ref-count for kek_item_t that doesn't disturb
* ongoing dek process. But the returned kek won't be zero-freed if the process
* never returns.
*
* So allocate new memory and let the user call put accordingly
*/
kek_t *get_kek(int engine_id, int kek_type, int *rc) {
kek_pack_t *pack;
kek_item_t *item;
kek_t *kek;
int userid = current_uid() / PER_USER_RANGE;
KEK_PACK_LOGD("entered [%d]\n", current_uid());
pack = find_kek_pack(engine_id);
if(pack == NULL) {
*rc = -ENOENT;
return NULL;
}
// Across user engine access denied for Knox containers.
if(!is_root() &&
(pack->user_id >= 100 && pack->user_id < 200) &&
(pack->user_id != userid)) {
KEK_PACK_LOGE("Permission denied to get kek\n");
KEK_PACK_LOGE("pack->user_id[%d] != userid[%d]\n",
pack->user_id, userid);
*rc = -EACCES;
return NULL;
}
kek = kmalloc(sizeof(kek_t), GFP_KERNEL);
if (kek == NULL) {
*rc = -ENOMEM;
return NULL;
}
spin_lock(&pack->kek_list_lock);
item = find_kek_item(pack, kek_type);
if (item) {
*rc = 0;
memcpy(kek, &item->kek, sizeof(kek_t));
spin_unlock(&pack->kek_list_lock);
return kek;
} else {
spin_unlock(&pack->kek_list_lock);
kzfree(kek);
}
*rc = -ENOENT;
return NULL;
}
void put_kek(kek_t *kek) {
KEK_PACK_LOGD("entered\n");
if(kek) kzfree(kek);
}
int is_kek_pack(int engine_id) {
kek_pack_t *pack;
KEK_PACK_LOGD("entered\n");
pack = find_kek_pack(engine_id);
if(pack) return 1;
return 0;
}
int is_kek(int engine_id, int kek_type) {
kek_pack_t *pack;
kek_item_t *item;
KEK_PACK_LOGD("entered\n");
pack = find_kek_pack(engine_id);
if(pack == NULL) return 0;
spin_lock(&pack->kek_list_lock);
item = find_kek_item(pack, kek_type);
spin_unlock(&pack->kek_list_lock);
if(item) {
return 1;
}
return 0;
}

View File

@ -1,519 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <crypto/internal/hash.h>
#include <crypto/scatterwalk.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/wakelock.h>
#include <linux/sched.h>
#include <linux/netlink.h>
#include <linux/net.h>
#include <net/netlink.h>
#include <net/sock.h>
#include <net/net_namespace.h>
#include <linux/types.h>
#include <linux/wait.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/audit.h>
#include <linux/jiffies.h>
#include <linux/version.h>
#include <sdp/pub_crypto_emul.h>
#define NETLINK_FIPS_CRYPTO 29
#define PUB_CRYPTO_PID_SET 3001
#define PUB_CRYPTO_RESULT 3002
#define RESULT_ARRAY_MAX_LEN 100
#define CRYPTO_MAX_TIMEOUT HZ/5
#define PUB_CRYPTO_REQ_TIMEOUT 3000
pub_crypto_control_t g_pub_crypto_control;
DEFINE_MUTEX(crypto_send_mutex);
static int user_fipscryptod_pid = 0;
static struct sock* crypto_sock = NULL;
static int pub_crypto_request_get_msg(pub_crypto_request_t *req, char **msg);
static void request_send(pub_crypto_control_t *con,
pub_crypto_request_t *req);
static void request_wait_answer(pub_crypto_control_t *con,
pub_crypto_request_t *req);
static pub_crypto_request_t *request_find(pub_crypto_control_t *con,
u32 request_id);
static pub_crypto_request_t *request_alloc(u32 opcode);
static void request_free(pub_crypto_control_t *con, pub_crypto_request_t *req);
static void req_dump(pub_crypto_request_t *req, const char *msg);
static void dump(unsigned char *buf, int len, const char *msg);
/* Debug */
#define PUB_CRYPTO_DEBUG 0
#if PUB_CRYPTO_DEBUG
#define PUB_CRYPTO_LOGD(FMT, ...) printk("SDP_PUB_CRYPTO[%d] : %s " FMT , current->pid, __func__, ##__VA_ARGS__)
#else
#define PUB_CRYPTO_LOGD(FMT, ...)
#endif /* PUB_CRYPTO_DEBUG */
#define PUB_CRYPTO_LOGE(FMT, ...) printk("SDP_PUB_CRYPTO[%d] : %s " FMT , current->pid, __func__, ##__VA_ARGS__)
#define PUB_CRYPTO_LOGI(FMT, ...) printk("SDP_PUB_CRYPTO[%d] : %s " FMT , current->pid, __func__, ##__VA_ARGS__)
//static char* process_crypto_request(u8 opcode, char* send_msg,
// int send_msg_size, int* result_len, int* ret) {
static int __do_dek_crypt(pub_crypto_request_t *req, char *ret) {
int rc = 0;
struct sk_buff *skb_in = NULL;
struct sk_buff *skb_out = NULL;
struct nlmsghdr *nlh = NULL;
char *nl_msg = NULL;
int nl_msg_size = 0;
PUB_CRYPTO_LOGD("====================== \t entred\n");
if(req == NULL) {
PUB_CRYPTO_LOGE("invalid request\n");
return -1;
}
request_send(&g_pub_crypto_control, req);
nl_msg_size = pub_crypto_request_get_msg(req, &nl_msg);
if(nl_msg_size <= 0) {
PUB_CRYPTO_LOGE("invalid opcode %d\n", req->opcode);
return -1;
}
// sending netlink message
skb_in = nlmsg_new(nl_msg_size, 0);
if (!skb_in) {
PUB_CRYPTO_LOGE("Failed to allocate new skb: \n");
return -1;
}
nlh = nlmsg_put(skb_in, 0, 0, NLMSG_DONE, nl_msg_size, 0);
NETLINK_CB(skb_in).dst_group = 0;
memcpy(nlmsg_data(nlh), nl_msg, nl_msg_size);
mutex_lock(&crypto_send_mutex);
rc = nlmsg_unicast(crypto_sock, skb_in, user_fipscryptod_pid);
mutex_unlock(&crypto_send_mutex);
if (rc < 0) {
PUB_CRYPTO_LOGE("Error while sending bak to user, err id: %d\n", rc);
return -1;
}
/*
* In a very rare case, response comes before request gets into pending list.
*/
if(req->state != PUB_CRYPTO_REQ_FINISHED)
request_wait_answer(&g_pub_crypto_control, req);
else
PUB_CRYPTO_LOGE("request already finished, skip waiting\n");
skb_out = skb_dequeue(&crypto_sock->sk_receive_queue);
if(req->state != PUB_CRYPTO_REQ_FINISHED) {
PUB_CRYPTO_LOGE("FIPS_CRYPTO_ERROR!!!\n");
/*
* TODO :
* Request not finished by an interrupt or abort.
*/
rc = -EINTR;
goto out;
}
if(req->aborted) {
PUB_CRYPTO_LOGE("Request aborted!!!\n");
rc = -ETIMEDOUT;
goto out;
}
if(req->result.ret < 0) {
PUB_CRYPTO_LOGE("failed to opcode(%d)!!!\n", req->opcode);
rc = req->result.ret;
goto out;
}
switch(req->opcode) {
case OP_DH_ENC:
case OP_DH_DEC:
case OP_ECDH_ENC:
case OP_ECDH_DEC:
dump(req->result.dek.buf, req->result.dek.len, "req->result.dek");
memcpy(ret, &(req->result.dek), sizeof(dek_t));
//dump(req->result.dek.buf, req->result.dek.len, "req->result.dek");
rc = 0;
break;
case OP_RSA_ENC:
case OP_RSA_DEC:
memcpy(ret, &(req->result.dek), sizeof(dek_t));
rc = 0;
break;
default:
PUB_CRYPTO_LOGE("Not supported opcode(%d)!!!\n", req->opcode);
rc = -EOPNOTSUPP;
break;
}
out:
if(skb_out) {
kfree_skb(skb_out);
}
if(rc != 0)
req_dump(req, "failed");
return rc;
}
static int pub_crypto_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
void *data;
u16 msg_type = nlh->nlmsg_type;
u32 err = 0;
struct audit_status *status_get = NULL;
u16 len = 0;
data = NLMSG_DATA(nlh);
len = ntohs(*(uint16_t*) (data+1));
switch (msg_type) {
case PUB_CRYPTO_PID_SET:
status_get = (struct audit_status *)data;
user_fipscryptod_pid = status_get->pid;
PUB_CRYPTO_LOGE("crypto_receive_msg: pid = %d\n", user_fipscryptod_pid);
break;
case PUB_CRYPTO_RESULT:
{
result_t *result = (result_t *)data;
pub_crypto_request_t *req = NULL;
req = request_find(&g_pub_crypto_control, result->request_id);
if(req) {
memcpy(&req->result, result, sizeof(result_t));
req->state = PUB_CRYPTO_REQ_FINISHED;
wake_up(&req->waitq);
memset(result, 0, sizeof(result_t));
}
break;
}
default:
PUB_CRYPTO_LOGE("unknown message type : %d\n", msg_type);
break;
}
return err;
}
/* Receive messages from netlink socket. */
static void crypto_recver(struct sk_buff *skb)
{
struct nlmsghdr *nlh;
int len;
int err;
nlh = nlmsg_hdr(skb);
len = skb->len;
err = pub_crypto_recv_msg(skb, nlh);
}
static void dump(unsigned char *buf, int len, const char *msg) {
#if PUB_CRYPTO_DEBUG
int i;
printk("%s len=%d: ", msg, len);
for(i=0;i<len;++i) {
printk("%02x ", (unsigned char)buf[i]);
}
printk("\n");
#else
printk("%s len=%d: ", msg, len);
printk("\n");
#endif
}
int do_dek_crypt(int opcode, dek_t *in, dek_t *out, kek_t *key){
pub_crypto_request_t *req = request_alloc(opcode);
int ret = -1;
if(req) {
switch(req->opcode) {
case OP_RSA_ENC:
case OP_RSA_DEC:
case OP_DH_ENC:
case OP_DH_DEC:
case OP_ECDH_ENC:
case OP_ECDH_DEC:
req->cipher_param.request_id = req->id;
req->cipher_param.opcode = req->opcode;
memcpy(&req->cipher_param.in, (void *) in, sizeof(dek_t));
memcpy(&req->cipher_param.key, (void *) key, sizeof(kek_t));
break;
default:
PUB_CRYPTO_LOGE("opcode[%d] failed, not supported\n", opcode);
goto error;
break;
}
ret = __do_dek_crypt(req, (char *)out);
if(ret != 0) {
PUB_CRYPTO_LOGE("opcode[%d] failed\n", opcode);
goto error;
}
} else {
PUB_CRYPTO_LOGE("request allocation failed\n");
return -ENOMEM;
}
request_free(&g_pub_crypto_control, req);
return 0;
error:
request_free(&g_pub_crypto_control, req);
return -1;
}
int rsa_encryptByPub(dek_t *dek, dek_t *edek, kek_t *key){
return do_dek_crypt(OP_RSA_ENC, dek, edek, key);
}
int rsa_decryptByPair(dek_t *edek, dek_t *dek, kek_t *key){
return do_dek_crypt(OP_RSA_DEC, edek, dek, key);
}
int dh_encryptDEK(dek_t *dek, dek_t *edek, kek_t *key){
return do_dek_crypt(OP_DH_ENC, dek, edek, key);
}
int dh_decryptEDEK(dek_t *edek, dek_t *dek, kek_t *key){
return do_dek_crypt(OP_DH_DEC, edek, dek, key);
}
int ecdh_encryptDEK(dek_t *dek, dek_t *edek, kek_t *key){
return do_dek_crypt(OP_ECDH_ENC, dek, edek, key);
}
int ecdh_decryptEDEK(dek_t *edek, dek_t *dek, kek_t *key){
return do_dek_crypt(OP_ECDH_DEC, edek, dek, key);
}
static int pub_crypto_request_get_msg(pub_crypto_request_t *req, char **msg)
{
int msg_len = -1;
switch(req->opcode) {
case OP_RSA_ENC:
case OP_RSA_DEC:
case OP_DH_DEC:
case OP_DH_ENC:
case OP_ECDH_DEC:
case OP_ECDH_ENC:
*msg = (char *)&req->cipher_param;
msg_len = sizeof(cipher_param_t);
break;
default:
*msg = NULL;
msg_len = -1;
break;
}
return msg_len;
}
static u32 pub_crypto_get_unique_id(pub_crypto_control_t *control)
{
spin_lock(&control->lock);
control->reqctr++;
/* zero is special */
if (control->reqctr == 0)
control->reqctr = 1;
spin_unlock(&control->lock);
return control->reqctr;
}
static void req_dump(pub_crypto_request_t *req, const char *msg) {
PUB_CRYPTO_LOGI("req %s {id:%d op:%d state:%d}\n", msg, req->id, req->opcode, req->state);
}
static void request_send(pub_crypto_control_t *con,
pub_crypto_request_t *req) {
spin_lock(&con->lock);
list_add_tail(&req->list, &con->pending_list);
req->state = PUB_CRYPTO_REQ_PENDING;
req_dump(req, "added");
spin_unlock(&con->lock);
}
static void request_wait_answer(pub_crypto_control_t *con,
pub_crypto_request_t *req) {
int intr;
while (req->state != PUB_CRYPTO_REQ_FINISHED) {
/*
* TODO : can anyone answer what happens when current process gets killed here?
*/
intr = wait_event_interruptible_timeout(req->waitq,
req->state == PUB_CRYPTO_REQ_FINISHED,
msecs_to_jiffies(PUB_CRYPTO_REQ_TIMEOUT));
if(req->state == PUB_CRYPTO_REQ_FINISHED)
break;
if(intr == 0) {
PUB_CRYPTO_LOGE("timeout! %d [ID:%d] \n", intr, req->id);
req->state = PUB_CRYPTO_REQ_FINISHED;
req->aborted = 1;
break;
}
if(intr == -ERESTARTSYS) {
PUB_CRYPTO_LOGE("wait interrupted : intr %d(-ERESTARTSYS) \n", intr);
break;
}
}
}
static pub_crypto_request_t *request_find(pub_crypto_control_t *con,
u32 request_id) {
struct list_head *entry;
spin_lock(&con->lock);
list_for_each(entry, &con->pending_list) {
pub_crypto_request_t *req;
req = list_entry(entry, pub_crypto_request_t, list);
if (req->id == request_id) {
req_dump(req, "found");
spin_unlock(&con->lock);
return req;
}
}
spin_unlock(&con->lock);
PUB_CRYPTO_LOGE("Can't find request %d\n", request_id);
return NULL;
}
static struct kmem_cache *pub_crypto_req_cachep;
static void pub_crypto_request_init(pub_crypto_request_t *req, u32 opcode) {
memset(req, 0, sizeof(pub_crypto_request_t));
req->state = PUB_CRYPTO_REQ_INIT;
req->id = pub_crypto_get_unique_id(&g_pub_crypto_control);
INIT_LIST_HEAD(&req->list);
init_waitqueue_head(&req->waitq);
atomic_set(&req->count, 1);
req->aborted = 0;
req->opcode = opcode;
}
static pub_crypto_request_t *request_alloc(u32 opcode) {
pub_crypto_request_t *req = kmem_cache_alloc(pub_crypto_req_cachep, GFP_KERNEL);
if(req)
pub_crypto_request_init(req, opcode);
return req;
}
static void request_free(pub_crypto_control_t *con, pub_crypto_request_t *req) {
if(req) {
req_dump(req, "freed");
spin_lock(&con->lock);
list_del(&req->list);
memset(req, 0, sizeof(pub_crypto_request_t));
kmem_cache_free(pub_crypto_req_cachep, req);
spin_unlock(&con->lock);
} else {
PUB_CRYPTO_LOGE("req is NULL, skip free\n");
}
}
void pub_crypto_control_init(pub_crypto_control_t *con) {
PUB_CRYPTO_LOGD("pub_crypto_control_init");
spin_lock_init(&con->lock);
INIT_LIST_HEAD(&con->pending_list);
con->reqctr = 0;
}
static int __init pub_crypto_mod_init(void) {
#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,4,0))
struct netlink_kernel_cfg cfg = {
.input = crypto_recver,
};
crypto_sock = netlink_kernel_create(&init_net, NETLINK_FIPS_CRYPTO, &cfg);
#else
crypto_sock = netlink_kernel_create(&init_net, NETLINK_FIPS_CRYPTO, 0, crypto_recver, NULL, THIS_MODULE);
#endif
if (!crypto_sock) {
PUB_CRYPTO_LOGE("Failed to create Crypto Netlink Socket .. Exiting \n");
return -ENOMEM;
}
PUB_CRYPTO_LOGE("netlink socket is created successfully! \n");
pub_crypto_control_init(&g_pub_crypto_control);
pub_crypto_req_cachep = kmem_cache_create("pub_crypto_requst",
sizeof(pub_crypto_request_t),
0, 0, NULL);
if (!pub_crypto_req_cachep) {
netlink_kernel_release(crypto_sock);
PUB_CRYPTO_LOGE("Failed to create pub_crypto_requst cache mem.. Exiting \n");
return -ENOMEM;
}
return 0;
}
static void __exit pub_crypto_mod_exit(void) {
/*
if (crypto_sock && crypto_sock->sk_socket) {
sock_release(crypto_sock->sk_socket);
}
*/
netlink_kernel_release(crypto_sock);
kmem_cache_destroy(pub_crypto_req_cachep);
}
module_init(pub_crypto_mod_init);
module_exit(pub_crypto_mod_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SDP pub crypto");

View File

@ -1,310 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <linux/debugfs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#include <sdp/dlp_ioctl.h>
#include <sdp/sdp_dlp.h>
#define DLP_DUMP_LIST 1 //TODO
static char *DLP_FILE_EXTENSIONS[] = {"xls", "xlsx", "doc", "docx", "ppt", "pptx", "pdf", "jpg", "jpeg", "zip", "mp4", "txt", "asd", "xlam", "htm", "html", "mht", "eml", "msg", "hwp", "gul", "rtf", "mysingle", "png", "gif"};
struct dlp_struct {
int user_id;
long time;
bool lock;
char* extensions;
struct list_head list;
struct mutex list_mutex;
};
struct dlp_struct dlp_info;
#if DLP_DUMP_LIST
static void dlp_dump_list(void) {
struct list_head *entry;
struct dlp_struct *tmp;
printk("============ debug ============\n");
mutex_lock(&dlp_info.list_mutex);
list_for_each(entry, &dlp_info.list) {
tmp = list_entry(entry, struct dlp_struct, list);
printk("DLP : user_id : %d\n", tmp->user_id);
printk("DLP : lock : %s\n", tmp->lock ? "true" : "false");
if (tmp->extensions) {
printk("DLP : extensions : %s\n", tmp->extensions);
} else {
printk("DLP : extensions : (empty)\n");
}
}
mutex_unlock(&dlp_info.list_mutex);
}
#endif
static struct dlp_struct *dlp_find_list(int user_id) {
struct list_head *entry;
struct dlp_struct *tmp;
mutex_lock(&dlp_info.list_mutex);
printk("DLP: user_id %d\n", user_id);
list_for_each(entry, &dlp_info.list) {
tmp = list_entry(entry, struct dlp_struct, list);
printk("DLP: tmp->user_id %d\n", tmp->user_id);
if(tmp->user_id == user_id) {
printk("DLP: found user_id %d\n", user_id); // TODO : deleted
mutex_unlock(&dlp_info.list_mutex);
return tmp;
}
}
mutex_unlock(&dlp_info.list_mutex);
return NULL;
}
bool dlp_is_locked(int user_id) {
struct dlp_struct *tmp;
tmp = dlp_find_list(user_id);
if(tmp){
return tmp->lock;
}
else {
return false;
}
}
static struct dlp_struct *dlp_add_info(int user_id){
struct dlp_struct *new_item;
new_item = kmalloc(sizeof(struct dlp_struct), GFP_KERNEL);
if(new_item == NULL) {
printk("DLP: can't alloc memory for dlp_info\n");
return NULL;
}
new_item->user_id = user_id;
new_item->lock = false;
new_item->extensions = NULL;
mutex_init(&new_item->list_mutex);
INIT_LIST_HEAD(&new_item->list);
mutex_lock(&dlp_info.list_mutex);
list_add_tail(&new_item->list, &dlp_info.list);
mutex_unlock(&dlp_info.list_mutex);
return new_item;
}
static int dlp_lock_setting(void __user *argp, bool lock) {
int ret = 0;
struct dlp_struct *tmp = NULL;
struct _dlp_lock_set dlp_lock_set;
ret = copy_from_user(&dlp_lock_set, (void __user *)argp, sizeof(dlp_lock_set));
if(ret) {
printk("DLP : fail to copy_from_user : dlp_lock_setting\n");
return -EFAULT;
}
tmp = dlp_find_list(dlp_lock_set.user_id);
if(tmp == NULL){
tmp = dlp_add_info(dlp_lock_set.user_id);
if(tmp == NULL){
return -EFAULT;
}
}
mutex_lock(&dlp_info.list_mutex);
tmp->lock = lock;
mutex_unlock(&dlp_info.list_mutex);
return 0;
};
static int dlp_extension_setting(void __user *argp) {
int ret = 0;
struct dlp_struct *tmp = NULL;
struct _dlp_extension_set dlp_ext_set;
ret = copy_from_user(&dlp_ext_set, (void __user *)argp, sizeof(dlp_ext_set));
if(ret) {
printk("DLP : fail to copy_from_user : dlp_extension_setting\n");
return -EFAULT;
}
printk("DLP: dlp_extension_setting called with user_id %d\n", dlp_ext_set.user_id);
tmp = dlp_find_list(dlp_ext_set.user_id);
if(tmp == NULL){
tmp = dlp_add_info(dlp_ext_set.user_id);
if(tmp == NULL){
return -EFAULT;
}
}
/* Delete old extensions and create new */
mutex_lock(&dlp_info.list_mutex);
if(tmp->extensions) {
kfree(tmp->extensions);
tmp->extensions = NULL;
}
if(strlen(dlp_ext_set.extensions)) {
tmp->extensions = kmalloc(strlen(dlp_ext_set.extensions)+1, GFP_KERNEL);
if (!tmp->extensions) {
mutex_unlock(&dlp_info.list_mutex);
return -EFAULT;
}
} else {
mutex_unlock(&dlp_info.list_mutex);
return 0;
}
strcpy(tmp->extensions, dlp_ext_set.extensions);
mutex_unlock(&dlp_info.list_mutex);
return 0;
}
static long dlp_ioctl(struct file *file, unsigned cmd,
unsigned long arg) {
int ret = 0;
void __user *argp = (void __user *) arg;
switch (cmd) {
case DLP_LOCK_ENABLE: {
printk("DLP: DLP_LOCK_ENABLE\n");
ret = dlp_lock_setting(argp, true);
break;
}
case DLP_LOCK_DISABLE: {
printk("DLP: DLP_LOCK_DISABLE\n");
ret = dlp_lock_setting(argp, false);
break;
}
case DLP_EXTENSION_SET: {
printk("DLP: DLP_EXTENSION_SET\n");
ret = dlp_extension_setting(argp);
break;
}
default:
pr_err("DLP : Invalid IOCTL: %d\n", cmd);
return -EINVAL;
}
#if DLP_DUMP_LIST
dlp_dump_list();
#endif
return ret;
}
int dlp_isInterestedFile(int user_id, const char *filename){
int i, j;
char *ext, *ret;
char lower[256];
struct dlp_struct *item = NULL;
ext = strrchr(filename, '.');
printk("DLP: dlp_isInterestedFile : %s\n", filename);
if(ext == NULL){
printk("DLP: Ext not found\n");
return -1;
}else{
ext++;
strncpy(lower, ext, sizeof(lower)-1);
lower[sizeof(lower)-1] = '\0';
for (j=0; j < strlen(lower); j++) {
lower[j] = tolower(lower[j]);
}
printk("DLP: extension : %s\n", lower);
}
item = dlp_find_list(user_id);
if(item == NULL || item->extensions == NULL){
//extensions for DLP is not set ...
// check if the extension is matching with default extensions
printk("DLP: extension set for DLP is not set\n");
for(i=(sizeof(DLP_FILE_EXTENSIONS)/sizeof(char*) -1); i>=0; i--){
if(strcmp(DLP_FILE_EXTENSIONS[i], lower)==0){
return 0;
}
}
printk("DLP: extension not matching with default return -1\n");
return -1;
}
printk("DLP: extension = %s\n", item->extensions);
strcat(lower, ","); // add comma, so that we compare each ext fully (doc vs. docx)
mutex_lock(&dlp_info.list_mutex);
ret = strstr(item->extensions, lower);
mutex_unlock(&dlp_info.list_mutex);
if (ret) {
return 0;
} else {
return -1;
}
}
const struct file_operations dlp_fops_evt = {
.owner = THIS_MODULE,
.unlocked_ioctl = dlp_ioctl,
.compat_ioctl = dlp_ioctl,
};
static struct miscdevice dlp_misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "sdp_dlp",
.fops = &dlp_fops_evt,
};
static int __init dlp_ioctl_init(void) {
int ret;
ret = misc_register(&dlp_misc_dev);
if (unlikely(ret)) {
printk("DLP: failed to register sdp_dlp device!\n");
return ret;
}
INIT_LIST_HEAD(&dlp_info.list);
mutex_init(&dlp_info.list_mutex);
printk("DLP: dlp_ioctl initialized\n");
return 0;
}
static void __exit dlp_ioctl_exit(void) {
misc_deregister(&dlp_misc_dev);
printk("DLP: dlp_ioctl mics_deregister\n");
}
module_init(dlp_ioctl_init);
module_exit(dlp_ioctl_exit);

View File

@ -1,302 +0,0 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Sensitive Data Protection
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define pr_fmt(fmt) "SDP_MM: %s: " fmt, __func__
#include <asm/current.h>
#include <linux/cdev.h>
#include <linux/debugfs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mm_types.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <sdp/sdp_mm.h>
#define SDP_MM_DEV "sdp_mm"
#define SENSITIVE 1
#define PER_USER_RANGE 100000
extern int dek_is_sdp_uid(uid_t uid);
static struct class *driver_class;
static dev_t sdp_mm_device_no;
struct sdp_mm_control {
struct list_head sdp_proc_list_head;
spinlock_t sdp_proc_list_lock;
struct cdev cdev;
unsigned int sensitive_proc_list_len;
unsigned int proc_id[MAX_SENSITIVE_PROC];
};
static struct sdp_mm_control sdp_mm;
static int32_t sdp_mm_query_proc_loaded(void __user *argp)
{
int32_t ret = 0;
struct task_struct *p = NULL;
unsigned long flags = 0;
struct sdp_mm_sensitive_proc_list_resp sdp_resp = {0};
/* foreach process check if 'sensitive' flag is set in task/mm_struct */
/* Copy the relevant information needed for loading the image */
spin_lock_irqsave(&sdp_mm.sdp_proc_list_lock, flags);
for_each_process(p) {
if (p->sensitive == SENSITIVE) {
sdp_resp.sensitive_proc_list[sdp_resp.sensitive_proc_list_len] = p->pid;
sdp_resp.sensitive_proc_list_len++;
}
if (sdp_resp.sensitive_proc_list_len >= MAX_SENSITIVE_PROC) break;
}
spin_unlock_irqrestore(&sdp_mm.sdp_proc_list_lock, flags);
if (copy_to_user(argp, &sdp_resp, sizeof(sdp_resp))) {
pr_err("SDP_MM: copy_to_user_failed\n");
ret = -EFAULT;
}
return ret;
}
int32_t sdp_mm_set_process_sensitive(unsigned int proc_id)
{
int32_t ret = 0;
struct task_struct *task = NULL;
uid_t uid;
/* current.task.sensitive = 1 */
task = pid_task(find_vpid(proc_id), PIDTYPE_PID);
if (task) {
uid = task_uid(task);
if (((uid/PER_USER_RANGE) <= 199) && ((uid/PER_USER_RANGE) >= 100)) {
if (dek_is_sdp_uid(uid)) {
task->sensitive = SENSITIVE;
printk("SDP_MM: set the process as sensitive\n");
} else {
printk("SDP_MM: not a SDP process, failed to mark sensitive\n");
ret = -EINVAL;
goto task_err;
}
}
} else {
printk("SDP_MM; task not present\n");
ret = -EINVAL;
goto task_err;
}
task_err:
return ret;
}
EXPORT_SYMBOL(sdp_mm_set_process_sensitive);
static int32_t sdp_mm_set_proc_sensitive(void __user *argp)
{
unsigned int proc_id = 0;
if (copy_from_user(&proc_id, (void __user *)argp,
sizeof(unsigned int))) {
pr_err("SDP_MM: copy_from_user failed\n");
return -EFAULT;
}
printk("SDP_MM: sensitive process id is %d\n", proc_id);
if (sdp_mm.sensitive_proc_list_len < MAX_SENSITIVE_PROC) {
sdp_mm.proc_id[sdp_mm.sensitive_proc_list_len] = proc_id;
sdp_mm.sensitive_proc_list_len++;
}
return sdp_mm_set_process_sensitive(proc_id);
}
static long sdp_mm_ioctl(struct file *file, unsigned cmd,
unsigned long arg)
{
int ret = 0;
void __user *argp = (void __user *) arg;
printk("SDP_MM: Entering ioctl\n");
switch (cmd) {
case SDP_MM_IOCTL_PROC_SENSITIVE_QUERY_REQ: {
printk("SDP_MM: SENSITIVE_PROC_QUERY\n");
ret = sdp_mm_query_proc_loaded(argp);
break;
}
case SDP_MM_IOCTL_SET_SENSITIVE_PROC_REQ: {
printk("SDP_MM: SET_PROC_SENSITIVE\n");
ret = sdp_mm_set_proc_sensitive(argp);
break;
}
default:
pr_err("Invalid IOCTL: %d\n", cmd);
return -EINVAL;
}
return ret;
}
static int sdp_mm_open(struct inode *inode, struct file *file)
{
int ret = 0;
printk("SDP_MM: entering open\n");
return ret;
}
static const struct file_operations sdp_mm_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = sdp_mm_ioctl,
.open = sdp_mm_open,
};
static int sdp_mm_probe(struct platform_device *pdev)
{
int rc;
struct device *class_dev;
printk("SDP_MM: entering probe\n");
rc = alloc_chrdev_region(&sdp_mm_device_no, 0, 1, SDP_MM_DEV);
if (rc < 0) {
pr_err("alloc_chrdev_region failed %d\n", rc);
return rc;
}
driver_class = class_create(THIS_MODULE, SDP_MM_DEV);
if (IS_ERR(driver_class)) {
rc = -ENOMEM;
pr_err("SDP_MM: class_create failed %d\n", rc);
goto exit_unreg_chrdev_region;
}
class_dev = device_create(driver_class, NULL, sdp_mm_device_no, NULL,
SDP_MM_DEV);
if (!class_dev) {
pr_err("SDP_MM: class_device_create failed %d\n", rc);
rc = -ENOMEM;
goto exit_destroy_class;
}
cdev_init(&sdp_mm.cdev, &sdp_mm_fops);
sdp_mm.cdev.owner = THIS_MODULE;
rc = cdev_add(&sdp_mm.cdev, MKDEV(MAJOR(sdp_mm_device_no), 0), 1);
if (rc < 0) {
pr_err("SDP_MM: cdev_add failed %d\n", rc);
goto exit_destroy_device;
}
INIT_LIST_HEAD(&sdp_mm.sdp_proc_list_head);
spin_lock_init(&sdp_mm.sdp_proc_list_lock);
return 0;
exit_destroy_device:
device_destroy(driver_class, sdp_mm_device_no);
exit_destroy_class:
class_destroy(driver_class);
exit_unreg_chrdev_region:
unregister_chrdev_region(sdp_mm_device_no, 1);
return rc;
}
static int sdp_mm_remove(struct platform_device *pdev)
{
int ret = 0;
cdev_del(&sdp_mm.cdev);
device_destroy(driver_class, sdp_mm_device_no);
class_destroy(driver_class);
unregister_chrdev_region(sdp_mm_device_no, 1);
return ret;
}
static struct platform_driver sdp_mm_plat_driver = {
.probe = sdp_mm_probe,
.remove = sdp_mm_remove,
.driver = {
.name = "sdp_mm",
.owner = THIS_MODULE,
},
};
static int __init sdp_mm_init(void)
{
int rc;
struct device *class_dev;
printk("SDP_MM: entering************************************************\n");
rc = alloc_chrdev_region(&sdp_mm_device_no, 0, 1, SDP_MM_DEV);
if (rc < 0) {
pr_err("SDP_MM: Alloc_chrdev_region failed %d\n", rc);
return rc;
}
driver_class = class_create(THIS_MODULE, SDP_MM_DEV);
if (IS_ERR(driver_class)) {
rc = -ENOMEM;
pr_err("SDP_MM: class_create failed %d\n", rc);
goto exit_unreg_chrdev_region;
}
class_dev = device_create(driver_class, NULL, sdp_mm_device_no, NULL,
SDP_MM_DEV);
if (!class_dev) {
pr_err("SDP_MM: class_device_create failed %d\n", rc);
rc = -ENOMEM;
goto exit_destroy_class;
}
cdev_init(&sdp_mm.cdev, &sdp_mm_fops);
sdp_mm.cdev.owner = THIS_MODULE;
rc = cdev_add(&sdp_mm.cdev, MKDEV(MAJOR(sdp_mm_device_no), 0), 1);
if (rc < 0) {
pr_err("SDP_MM: cdev_add failed %d\n", rc);
goto exit_destroy_device;
}
INIT_LIST_HEAD(&sdp_mm.sdp_proc_list_head);
spin_lock_init(&sdp_mm.sdp_proc_list_lock);
return 0;
exit_destroy_device:
device_destroy(driver_class, sdp_mm_device_no);
exit_destroy_class:
class_destroy(driver_class);
exit_unreg_chrdev_region:
unregister_chrdev_region(sdp_mm_device_no, 1);
return rc;
}
static void __exit sdp_mm_exit(void)
{
platform_driver_unregister(&sdp_mm_plat_driver);
}
module_init(sdp_mm_init);
module_exit(sdp_mm_exit);
MODULE_AUTHOR("HP");
MODULE_LICENSE("GPL");