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; }