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->userid, &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->userid, &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, 1);
	if (rc < 0) {
		DEK_LOGE("Error converting dek [FLAG]; rc = [%d]\n", rc);
		goto out;
	}
out:
	memset(&DEK, 0, sizeof(dek_t));
	return rc;
}
static int ecryptfs_sdp_set_sensitive(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;

	memcpy(DEK.buf, crypt_stat->key, crypt_stat->key_size);
	DEK.len = crypt_stat->key_size;
	DEK.type = DEK_TYPE_PLAIN;

	rc = dek_encrypt_dek_efs(crypt_stat->userid, &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;
	}
	memset(crypt_stat->key, 0, crypt_stat->key_size);
	crypt_stat->flags &= ~(ECRYPTFS_KEY_SET);
	ecryptfs_update_crypt_flag(dentry, 1);
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;
	if (fp_dentry->d_name.len <= NAME_MAX)
			memcpy(filename, fp_dentry->d_name.name,
					fp_dentry->d_name.len + 1);

	DEK_LOGD("ecryptfs_do_sdp_ioctl\n");

	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);
			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;
			}
			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_GET_FEK: {
		dek_arg_get_fek req;

		DEK_LOGD("ECRYPTFS_IOCTL_GET_FEK\n");
	
		if (crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
			DEK_LOGE("don't return FEK of sensitive file\n");
			return -EFAULT;
		}

		memset(&req, 0, sizeof(dek_arg_get_fek));
		if(copy_from_user(&req, ubuf, sizeof(req))) {
			DEK_LOGE("can't copy from user\n");
			memset(&req, 0, sizeof(dek_arg_get_fek));
			return -EFAULT;
		} else {
			mutex_lock(&crypt_stat->cs_mutex);
			memcpy(req.dek.buf, crypt_stat->key, crypt_stat->key_size);
			req.dek.len = crypt_stat->key_size;
			req.dek.type = DEK_TYPE_PLAIN;
			mutex_unlock(&crypt_stat->cs_mutex);
		}
		if(copy_to_user(ubuf, &req, sizeof(req))) {
			DEK_LOGE("can't copy to user\n");
			memset(&req, 0, sizeof(dek_arg_get_fek));
			return -EFAULT;
		}
		memset(&req, 0, sizeof(dek_arg_get_fek));
		break;
		}

	case ECRYPTFS_IOCTL_GET_EFEK: {
		dek_arg_get_efek req;

		DEK_LOGD("ECRYPTFS_IOCTL_GET_EFEK\n");
	
		memset(&req, 0, sizeof(dek_arg_get_efek));
		if(copy_from_user(&req, ubuf, sizeof(req))) {
			DEK_LOGE("can't copy from user\n");
			memset(&req, 0, sizeof(dek_arg_get_efek));
			return -EFAULT;
		} else {
			mutex_lock(&crypt_stat->cs_mutex);
			memcpy(req.dek.buf, crypt_stat->sdp_dek.buf, crypt_stat->sdp_dek.len);
			req.dek.len = crypt_stat->sdp_dek.len;
			req.dek.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");
			memset(&req, 0, sizeof(dek_arg_get_efek));
			return -EFAULT;
		}
		memset(&req, 0, sizeof(dek_arg_get_efek));
		break;
		}

	case ECRYPTFS_IOCTL_SET_EFEK: {
		dek_arg_set_efek req;

		DEK_LOGD("ECRYPTFS_IOCTL_SET_EFEK\n");
	
		memset(&req, 0, sizeof(dek_arg_set_efek));
		if(copy_from_user(&req, ubuf, sizeof(req))) {
			DEK_LOGE("can't copy from user\n");
			memset(&req, 0, sizeof(dek_arg_set_efek));
			return -EFAULT;
		} else {
			if(req.dek.len > DEK_MAXLEN) {
				DEK_LOGE("ECRYPTFS_IOCTL_SET_EFEK invalid EFEK len %d\n",
						req.dek.len);
				return -EINVAL;
			}

			if (req.dek.type != DEK_TYPE_PLAIN) {
				mutex_lock(&crypt_stat->cs_mutex);
				memcpy(crypt_stat->sdp_dek.buf, req.dek.buf, req.dek.len);
				crypt_stat->sdp_dek.len = req.dek.len;
				crypt_stat->sdp_dek.type = req.dek.type;
				memset(crypt_stat->key, 0, crypt_stat->key_size);
				crypt_stat->flags &= ~(ECRYPTFS_KEY_SET);
				mutex_unlock(&crypt_stat->cs_mutex);
				ecryptfs_update_crypt_flag(ecryptfs_dentry, 1);
			} else {
				DEK_LOGE("failed to set EFEK\n");
				memset(&req, 0, sizeof(dek_arg_set_efek));
				return -EFAULT;
			}
		}
		memset(&req, 0, sizeof(dek_arg_set_efek));
		break;
		}
	default: {
		return -EINVAL;
		break;
		}

	}
	return 0;
}