static int dek_encrypt_dek(int userid, dek_t *plainDek, dek_t *encDek) { int ret = 0; int key_arr_idx = PERSONA_KEY_ARR_IDX(userid); if (!dek_is_persona(userid)) { DEK_LOGE("%s invalid userid %d\n", __func__, userid); return -EFAULT; } #if DEK_DEBUG DEK_LOGD("plainDek from user: "******"aes encrypt failed\n"); dek_add_to_log(userid, "aes encrypt failed"); encDek->len = 0; } else { encDek->len = plainDek->len; encDek->type = DEK_TYPE_AES_ENC; } } else { #ifdef CONFIG_PUB_CRYPTO /* * Do an asymmetric crypto */ if(SDPK_Dpub[key_arr_idx].len > 0) { ret = dh_encryptDEK(plainDek, encDek, &SDPK_Dpub[key_arr_idx]); }else{ DEK_LOGE("SDPK_Dpub for id: %d\n", userid); dek_add_to_log(userid, "encrypt failed, no SDPK_Dpub"); return -EIO; } #else DEK_LOGE("pub crypto not supported : %d\n", userid); dek_add_to_log(userid, "encrypt failed, no key"); return -EOPNOTSUPP; #endif } if (encDek->len <= 0 || encDek->len > DEK_MAXLEN) { DEK_LOGE("dek_encrypt_dek, incorrect len=%d\n", encDek->len); zero_out((char *)encDek, sizeof(dek_t)); return -EFAULT; } #if DEK_DEBUG else { DEK_LOGD("encDek to user: "); dump(encDek->buf, encDek->len); } #endif return ret; }
static int ecryptfs_release(struct inode *inode, struct file *file) { #ifdef CONFIG_SDP struct ecryptfs_crypt_stat *crypt_stat; crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; if(crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) { #if 0 #ifdef SYNC_ONLY_CURRENT_SB struct super_block *sb = inode->i_sb; sync_inodes_sb(sb); writeback_inodes_sb(sb, WB_REASON_SYNC); #else sys_sync(); #endif DEK_LOGD("%s() sensitive inode being closed. [ino:%lu, state:%lu ref_count:%d efs_flag:0x%0.8x]\n", __func__, inode->i_ino, inode->i_state, atomic_read(&inode->i_count), crypt_stat->flags); spin_lock(&inode->i_lock); if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) || (inode->i_mapping->nrpages == 0)) { spin_unlock(&inode->i_lock); } else { printk("freeing sensitive inode\n"); invalidate_mapping_pages(inode->i_mapping, 0, -1); } spin_unlock(&inode->i_lock); #else DEK_LOGD("%s() sensitive inode being closed. [ino:%lu, state:%lu ref_count:%d]\n", __func__, inode->i_ino, inode->i_state, atomic_read(&inode->i_count)); ecryptfs_clean_sdp_dek(crypt_stat); if(ecryptfs_is_persona_locked(crypt_stat->userid)) ecryptfs_mm_drop_cache(crypt_stat->userid); } #endif #endif ecryptfs_put_lower_file(inode); kmem_cache_free(ecryptfs_file_info_cache, ecryptfs_file_to_private(file)); return 0; }
int ecryptfs_get_sdp_dek(unsigned char *sig, int *sig_len, struct ecryptfs_crypt_stat *crypt_stat) { int rc = 0; if(crypt_stat != NULL && (crypt_stat->flags & ECRYPTFS_DEK_SDP_ENABLED)) { if((crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE)) { dek_t DEK; #if ECRYPTFS_DEK_DEBUG DEK_LOGD("get_sdp_dek: sensitive, dek type: %d\n", crypt_stat->sdp_dek.type); ecryptfs_dumpkey(crypt_stat->userid, "sdp_dek:", crypt_stat->sdp_dek.buf, crypt_stat->sdp_dek.len); #endif if (crypt_stat->sdp_dek.type != DEK_TYPE_PLAIN) { rc = dek_decrypt_dek_efs(crypt_stat->userid, &crypt_stat->sdp_dek, &DEK); } else { DEK_LOGE("Error, DEK already plaintext"); rc = -1; } if (rc < 0) { DEK_LOGE("Error decypting dek; rc = [%d]\n", rc); rc = -1; /* * TODO : olic.moon * When we return -1 here, ECRYPTFS_ENCRYPTED is somehow gone * later. then it occurs error while updating EDEK */ rc = 0; memset(&DEK, 0, sizeof(dek_t)); goto out; } #if ECRYPTFS_DEK_DEBUG ecryptfs_dumpkey(crypt_stat->userid, "decrypted:", DEK.buf, DEK.len); DEK_LOGD("decrypted key size is %d\n", DEK.len); #endif memcpy(sig, DEK.buf, DEK.len); (*sig_len) = DEK.len; memset(&DEK, 0, sizeof(dek_t)); } else { #if ECRYPTFS_DEK_DEBUG DEK_LOGD("file is not sensitive\n"); #endif } } out: if(!rc) sdp_mm_set_process_sensitive(current->pid); return rc; }
static ssize_t dek_read_log(struct file *file, char __user *buffer, size_t len, loff_t *off) { int ret = 0; struct log_struct *tmp = NULL; char log_buf[256]; int log_buf_len; // build error //DEK_LOGD("dek_read_log, len=%d, off=%ld, log_count=%d\n", // len, (long int)*off, log_count); if (list_empty(&log_buffer.list)) { DEK_LOGD("process %i (%s) going to sleep\n", current->pid, current->comm); flag = 0; wait_event_interruptible(wq, flag != 0); } flag = 0; spin_lock(&log_buffer.list_lock); if (!list_empty(&log_buffer.list)) { tmp = list_first_entry(&log_buffer.list, struct log_struct, list); if (tmp != NULL) { memcpy(&log_buf, tmp->buf, tmp->len); log_buf_len = tmp->len; list_del(&tmp->list); kfree(tmp); log_count--; spin_unlock(&log_buffer.list_lock); ret = copy_to_user(buffer, log_buf, log_buf_len); if (ret) { DEK_LOGE("dek_read_log, copy_to_user fail, ret=%d, len=%d\n", ret, log_buf_len); return -EFAULT; } len = log_buf_len; *off = log_buf_len; } else { DEK_LOGD("dek_read_log, tmp == null\n"); len = 0; spin_unlock(&log_buffer.list_lock); } } else {
int ecryptfs_super_block_get_userid(struct super_block *sb) { int userid = ecryptfs_superblock_to_private(sb)->userid; #if ECRYPTFS_DEK_DEBUG DEK_LOGD("sdp id is %d\n", userid); #endif return userid; }
static int is_system_server(void) { uid_t uid = current_uid(); switch(uid) { #if 0 case 0: //root DEK_LOGD("allowing root to access SDP device files\n"); #endif case 1000: return 1; default: break; } return 0; }
static void ecryptfs_dumpkey(int userid, char *tag, unsigned char *buf, int len) { int i; char s[512]; s[0] = 0; for(i=0;i<len && i<16;++i) { char tmp[8]; sprintf(tmp, " %02x", buf[i]); strcat(s, tmp); } if (len > 16) { char tmp[8]; sprintf(tmp, " ..."); strcat(s, tmp); } DEK_LOGD("id:%d, %s [%s len=%d]\n", userid, tag, s, len); }
int dek_generate_dek(int userid, dek_t *newDek) { if (!dek_is_persona(userid)) { DEK_LOGE("%s invalid userid %d\n", __func__, userid); return -EFAULT; } newDek->len = DEK_LEN; get_random_bytes(newDek->buf, newDek->len); if (newDek->len <= 0 || newDek->len > DEK_LEN) { zero_out((char *)newDek, sizeof(dek_t)); return -EFAULT; } #if DEK_DEBUG else { DEK_LOGD("DEK: "); dek_dump(newDek->buf, newDek->len); } #endif 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; (*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) { crypt_stat->sdp_dek.type = get_unaligned_be32(data + *packet_size); (*packet_size) += 4; crypt_stat->sdp_dek.len = get_unaligned_be32(data + *packet_size); (*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 long dek_do_ioctl_evt(unsigned int minor, unsigned int cmd, unsigned long arg) { long ret = 0; void __user *ubuf = (void __user *)arg; void *cleanup = NULL; unsigned int size; switch (cmd) { /* * Event while booting. * * This event comes per persona, the driver is responsible to * verify things good whether it's compromised. */ case DEK_ON_BOOT: { dek_arg_on_boot *evt = kzalloc(sizeof(dek_arg_on_boot), GFP_KERNEL); DEK_LOGD("DEK_ON_BOOT\n"); if (evt == NULL) { ret = -ENOMEM; goto err; } cleanup = evt; size = sizeof(dek_arg_on_boot); if(copy_from_user(evt, ubuf, size)) { DEK_LOGE("can't copy from user evt\n"); ret = -EFAULT; goto err; } ret = dek_on_boot(evt); if (ret < 0) { dek_add_to_log(evt->userid, "Boot failed"); goto err; } dek_add_to_log(evt->userid, "Booted"); break; } /* * Event when device is locked. * * Nullify private key which prevents decryption. */ case DEK_ON_DEVICE_LOCKED: { dek_arg_on_device_locked *evt = kzalloc(sizeof(dek_arg_on_device_locked), GFP_KERNEL); DEK_LOGD("DEK_ON_DEVICE_LOCKED\n"); if (evt == NULL) { ret = -ENOMEM; goto err; } cleanup = evt; size = sizeof(dek_arg_on_device_locked); if(copy_from_user(evt, ubuf, size)) { DEK_LOGE("can't copy from user evt\n"); ret = -EFAULT; goto err; } ret = dek_on_device_locked(evt); if (ret < 0) { dek_add_to_log(evt->userid, "Lock failed"); goto err; } dek_add_to_log(evt->userid, "Locked"); break; } /* * Event when device unlocked. * * Read private key and decrypt with user password. */ case DEK_ON_DEVICE_UNLOCKED: { dek_arg_on_device_unlocked *evt = kzalloc(sizeof(dek_arg_on_device_unlocked), GFP_KERNEL); DEK_LOGD("DEK_ON_DEVICE_UNLOCKED\n"); if (evt == NULL) { ret = -ENOMEM; goto err; } cleanup = evt; size = sizeof(dek_arg_on_device_unlocked); if(copy_from_user(evt, ubuf, size)) { DEK_LOGE("can't copy from user evt\n"); ret = -EFAULT; goto err; } ret = dek_on_device_unlocked(evt); if (ret < 0) { dek_add_to_log(evt->userid, "Unlock failed"); goto err; } dek_add_to_log(evt->userid, "Unlocked"); break; } /* * Event when new user(persona) added. * * Generate RSA public key and encrypt private key with given * password. Also pub-key and encryped priv-key have to be stored * in a file system. */ case DEK_ON_USER_ADDED: { dek_arg_on_user_added *evt = kzalloc(sizeof(dek_arg_on_user_added), GFP_KERNEL); DEK_LOGD("DEK_ON_USER_ADDED\n"); if (evt == NULL) { ret = -ENOMEM; goto err; } cleanup = evt; size = sizeof(dek_arg_on_user_added); if(copy_from_user(evt, ubuf, size)) { DEK_LOGE("can't copy from user evt\n"); ret = -EFAULT; goto err; } ret = dek_on_user_added(evt); if (ret < 0) { dek_add_to_log(evt->userid, "Add user failed"); goto err; } dek_add_to_log(evt->userid, "Added user"); break; } /* * Event when user is removed. * * Remove pub-key file & encrypted priv-key file. */ case DEK_ON_USER_REMOVED: { dek_arg_on_user_removed *evt = kzalloc(sizeof(dek_arg_on_user_removed), GFP_KERNEL); DEK_LOGD("DEK_ON_USER_REMOVED\n"); if (evt == NULL) { ret = -ENOMEM; goto err; } cleanup = evt; size = sizeof(dek_arg_on_user_removed); if(copy_from_user(evt, ubuf, size)) { DEK_LOGE("can't copy from user evt\n"); ret = -EFAULT; goto err; } ret = dek_on_user_removed(evt); if (ret < 0) { dek_add_to_log(evt->userid, "Remove user failed"); goto err; } dek_add_to_log(evt->userid, "Removed user"); break; } /* * Event when password changed. * * Encrypt SDPK_Rpri with new password and store it. */ case DEK_ON_CHANGE_PASSWORD: { DEK_LOGD("DEK_ON_CHANGE_PASSWORD << deprecated. SKIP\n"); ret = 0; dek_add_to_log(0, "Changed password << deprecated"); break; } case DEK_DISK_CACHE_CLEANUP: { dek_arg_disk_cache_cleanup *evt = kzalloc(sizeof(dek_arg_disk_cache_cleanup), GFP_KERNEL); DEK_LOGD("DEK_DISK_CACHE_CLEANUP\n"); if (evt == NULL) { ret = -ENOMEM; goto err; } cleanup = evt; size = sizeof(dek_arg_on_user_removed); if(copy_from_user(evt, ubuf, size)) { DEK_LOGE("can't copy from user evt\n"); ret = -EFAULT; goto err; } if (!dek_is_persona(evt->userid)) { DEK_LOGE("%s invalid userid %d\n", __func__, evt->userid); ret = -EFAULT; goto err; } ecryptfs_mm_drop_cache(evt->userid); ret = 0; dek_add_to_log(evt->userid, "Disk cache clean up"); break; } default: DEK_LOGE("%s case default\n", __func__); ret = -EINVAL; break; } err: if (cleanup) { zero_out((char *)cleanup, size); kfree(cleanup); } return ret; }
static int dek_decrypt_dek(int userid, dek_t *encDek, dek_t *plainDek) { int key_arr_idx; int dek_type = encDek->type; if (!dek_is_persona(userid)) { DEK_LOGE("%s invalid userid %d\n", __func__, userid); return -EFAULT; } key_arr_idx = PERSONA_KEY_ARR_IDX(userid); #if DEK_DEBUG DEK_LOGD("encDek from user: "******"aes decrypt failed\n"); dek_add_to_log(userid, "aes decrypt failed"); plainDek->len = 0; } else { plainDek->len = encDek->len; plainDek->type = DEK_TYPE_PLAIN; } } else { DEK_LOGE("no SDPK_sym key for id: %d\n", userid); dek_add_to_log(userid, "decrypt failed, persona locked"); return -EIO; } return 0; } case DEK_TYPE_RSA_ENC: { #ifdef CONFIG_PUB_CRYPTO if(SDPK_Rpri[key_arr_idx].len > 0) { if(rsa_decryptByPair(encDek, plainDek, &SDPK_Rpri[key_arr_idx])){ DEK_LOGE("rsa_decryptByPair failed"); return -1; } }else{ DEK_LOGE("SDPK_Rpri for id: %d\n", userid); dek_add_to_log(userid, "encrypt failed, no SDPK_Rpri"); return -EIO; } #else DEK_LOGE("Not supported key type: %d\n", encDek->type); dek_add_to_log(userid, "decrypt failed, DH type not supported"); return -EOPNOTSUPP; #endif return 0; } case DEK_TYPE_DH_ENC: { #ifdef CONFIG_PUB_CRYPTO if(SDPK_Dpri[key_arr_idx].len > 0) { if(dh_decryptEDEK(encDek, plainDek, &SDPK_Dpri[key_arr_idx])){ DEK_LOGE("dh_decryptEDEK failed"); return -1; } }else{ DEK_LOGE("SDPK_Dpri for id: %d\n", userid); dek_add_to_log(userid, "encrypt failed, no SDPK_Dpri"); return -EIO; } #else DEK_LOGE("Not supported key type: %d\n", encDek->type); dek_add_to_log(userid, "decrypt failed, DH type not supported"); return -EOPNOTSUPP; #endif return 0; } case DEK_TYPE_ECDH256_ENC: { #ifdef CONFIG_PUB_CRYPTO #if DEK_DEBUG printk("DEK_TYPE_ECDH256_ENC encDek:"); dek_dump(encDek->buf, encDek->len); #endif if(SDPK_EDpri[key_arr_idx].len > 0) { if(ecdh_decryptEDEK(encDek, plainDek, &SDPK_EDpri[key_arr_idx])){ DEK_LOGE("ecdh_decryptEDEK failed"); return -1; } }else{ DEK_LOGE("SDPK_EDpri for id: %d\n", userid); dek_add_to_log(userid, "encrypt failed, no SDPK_EDpri"); return -EIO; } #else DEK_LOGE("Not supported key type: %d\n", encDek->type); dek_add_to_log(userid, "decrypt failed, ECDH type not supported"); return -EOPNOTSUPP; #endif return 0; } default: { DEK_LOGE("Unsupported edek type: %d\n", encDek->type); dek_add_to_log(userid, "decrypt failed, unsupported key type"); return -EFAULT; } } }
static int dek_release_log(struct inode *ignored, struct file *file) { DEK_LOGD("dek_release_log\n"); return 0; }
static int dek_open_log(struct inode *inode, struct file *file) { DEK_LOGD("dek_open_log\n"); return 0; }
static int dek_decrypt_dek(int userid, dek_t *encDek, dek_t *plainDek) { int key_arr_idx = PERSONA_KEY_ARR_IDX(userid); if (!dek_is_persona(userid)) { DEK_LOGE("%s invalid userid %d\n", __func__, userid); return -EFAULT; } #if DEK_DEBUG DEK_LOGD("encDek from user: "******"aes decrypt failed\n"); dek_add_to_log(userid, "aes decrypt failed"); plainDek->len = 0; } else { plainDek->len = encDek->len; plainDek->type = DEK_TYPE_PLAIN; } } else { DEK_LOGE("no SDPK_sym key for id: %d\n", userid); dek_add_to_log(userid, "decrypt failed, persona locked"); return -EIO; } } else if (encDek->type == DEK_TYPE_RSA_ENC) { DEK_LOGE("Not supported key type: %d\n", encDek->type); dek_add_to_log(userid, "decrypt failed, RSA type not supported"); return -EFAULT; } else if (encDek->type == DEK_TYPE_DH_ENC) { #ifdef CONFIG_PUB_CRYPTO if(SDPK_Dpri[key_arr_idx].len > 0) { if(dh_decryptEDEK(encDek, plainDek, &SDPK_Dpri[key_arr_idx])){ DEK_LOGE("dh_decryptEDEK failed"); return -1; } }else{ DEK_LOGE("SDPK_Dpri for id: %d\n", userid); dek_add_to_log(userid, "encrypt failed, no SDPK_Dpri"); return -EIO; } #else DEK_LOGE("Not supported key type: %d\n", encDek->type); dek_add_to_log(userid, "decrypt failed, DH type not supported"); return -EOPNOTSUPP; #endif } else { DEK_LOGE("Unsupported decrypt key type: %d\n", encDek->type); dek_add_to_log(userid, "decrypt failed, unsupported key type"); return -EFAULT; } if (plainDek->len <= 0 || plainDek->len > DEK_LEN) { DEK_LOGE("dek_decrypt_dek, incorrect len=%d\n", plainDek->len); zero_out((char *)plainDek, sizeof(dek_t)); return -EFAULT; } else { #if DEK_DEBUG DEK_LOGD("plainDek to user: "); dump(plainDek->buf, plainDek->len); #endif } return 0; }
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; }
static int ecryptfs_update_crypt_flag(struct dentry *dentry, int is_sensitive) { int rc = 0; struct dentry *lower_dentry; struct inode *inode; struct inode *lower_inode; struct ecryptfs_crypt_stat *crypt_stat; struct ecryptfs_mount_crypt_stat *mount_crypt_stat; crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->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); lower_dentry = ecryptfs_dentry_to_lower(dentry); mutex_lock(&crypt_stat->cs_mutex); mount_crypt_stat = &ecryptfs_superblock_to_private( dentry->d_sb)->mount_crypt_stat; 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); goto out; } if (is_sensitive) { crypt_stat->flags |= ECRYPTFS_DEK_IS_SENSITIVE; /* * Set sensirive for all the pages in the inode */ set_sensitive_mapping_pages(inode->i_mapping, 0, -1); } else{ crypt_stat->flags &= ~ECRYPTFS_DEK_IS_SENSITIVE; } rc = ecryptfs_write_metadata(dentry, inode); if (rc) { if (!(mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { rc = -EIO; DEK_LOGE("Either the lower file " "is not in a valid eCryptfs format, " "or the key could not be retrieved. " "Plaintext passthrough mode is not " "enabled; returning -EIO\n"); mutex_unlock(&crypt_stat->cs_mutex); DEK_LOGD("ecryptfs_write_metadata rc=%d\n", rc); goto out; } rc = 0; crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED | ECRYPTFS_ENCRYPTED); } rc = ecryptfs_write_inode_size_to_metadata(inode); if (rc) { mutex_unlock(&crypt_stat->cs_mutex); DEK_LOGE("Problem with " "ecryptfs_write_inode_size_to_metadata; " "rc = [%d]\n", rc); goto out; } ecryptfs_put_lower_file(inode); mutex_unlock(&crypt_stat->cs_mutex); out: fsstack_copy_attr_all(inode, lower_inode); return rc; }
static long dek_do_ioctl_req(unsigned int minor, unsigned int cmd, unsigned long arg) { long ret = 0; void __user *ubuf = (void __user *)arg; switch (cmd) { case DEK_IS_KEK_AVAIL: { dek_arg_is_kek_avail req; DEK_LOGD("DEK_IS_KEK_AVAIL\n"); memset(&req, 0, sizeof(dek_arg_is_kek_avail)); if(copy_from_user(&req, ubuf, sizeof(req))) { DEK_LOGE("can't copy from user\n"); ret = -EFAULT; goto err; } req.ret = is_kek_available(req.userid, req.kek_type); if(req.ret < 0) { DEK_LOGE("is_kek_available(id:%d, kek:%d) error\n", req.userid, req.kek_type); ret = -ENOENT; goto err; } if(copy_to_user(ubuf, &req, sizeof(req))) { DEK_LOGE("can't copy to user req\n"); zero_out((char *)&req, sizeof(dek_arg_is_kek_avail)); ret = -EFAULT; goto err; } ret = 0; } break; /* * Request to generate DEK. * Generate DEK and return to the user */ case DEK_GENERATE_DEK: { dek_arg_generate_dek req; DEK_LOGD("DEK_GENERATE_DEK\n"); memset(&req, 0, sizeof(dek_arg_generate_dek)); if(copy_from_user(&req, ubuf, sizeof(req))) { DEK_LOGE("can't copy from user req\n"); ret = -EFAULT; goto err; } dek_generate_dek(req.userid, &req.dek); if(copy_to_user(ubuf, &req, sizeof(req))) { DEK_LOGE("can't copy to user req\n"); zero_out((char *)&req, sizeof(dek_arg_generate_dek)); ret = -EFAULT; goto err; } zero_out((char *)&req, sizeof(dek_arg_generate_dek)); break; } /* * Request to encrypt given DEK. * * encrypt dek and return to the user */ case DEK_ENCRYPT_DEK: { dek_arg_encrypt_dek req; DEK_LOGD("DEK_ENCRYPT_DEK\n"); memset(&req, 0, sizeof(dek_arg_encrypt_dek)); if(copy_from_user(&req, ubuf, sizeof(req))) { DEK_LOGE("can't copy from user req\n"); zero_out((char *)&req, sizeof(dek_arg_encrypt_dek)); ret = -EFAULT; goto err; } ret = dek_encrypt_dek(req.userid, &req.plain_dek, &req.enc_dek); if (ret < 0) { zero_out((char *)&req, sizeof(dek_arg_encrypt_dek)); goto err; } if(copy_to_user(ubuf, &req, sizeof(req))) { DEK_LOGE("can't copy to user req\n"); zero_out((char *)&req, sizeof(dek_arg_encrypt_dek)); ret = -EFAULT; goto err; } zero_out((char *)&req, sizeof(dek_arg_encrypt_dek)); break; } /* * Request to decrypt given DEK. * * Decrypt dek and return to the user. * When device is locked, private key is not available, so * the driver must return EPERM or some kind of error. */ case DEK_DECRYPT_DEK: { dek_arg_decrypt_dek req; DEK_LOGD("DEK_DECRYPT_DEK\n"); memset(&req, 0, sizeof(dek_arg_decrypt_dek)); if(copy_from_user(&req, ubuf, sizeof(req))) { DEK_LOGE("can't copy from user req\n"); zero_out((char *)&req, sizeof(dek_arg_decrypt_dek)); ret = -EFAULT; goto err; } ret = dek_decrypt_dek(req.userid, &req.enc_dek, &req.plain_dek); if (ret < 0) { zero_out((char *)&req, sizeof(dek_arg_decrypt_dek)); goto err; } if(copy_to_user(ubuf, &req, sizeof(req))) { DEK_LOGE("can't copy to user req\n"); zero_out((char *)&req, sizeof(dek_arg_decrypt_dek)); ret = -EFAULT; goto err; } zero_out((char *)&req, sizeof(dek_arg_decrypt_dek)); break; } default: DEK_LOGE("%s case default\n", __func__); ret = -EINVAL; break; } return ret; err: return ret; }
static long dek_do_ioctl_kek(unsigned int minor, unsigned int cmd, unsigned long arg) { long ret = 0; void __user *ubuf = (void __user *)arg; switch (cmd) { case DEK_GET_KEK: { dek_arg_get_kek req; int requested_type = 0; int userid; int key_arr_idx; DEK_LOGD("DEK_GET_KEK\n"); memset(&req, 0, sizeof(dek_arg_get_kek)); if(copy_from_user(&req, ubuf, sizeof(req))) { DEK_LOGE("can't copy from user kek\n"); ret = -EFAULT; goto err; } userid = req.userid; if (!dek_is_persona(userid)) { DEK_LOGE("%s invalid userid %d\n", __func__, userid); return -EFAULT; } key_arr_idx = PERSONA_KEY_ARR_IDX(userid); requested_type = req.kek_type; req.key.len = 0; req.key.type = -1; switch(requested_type) { case KEK_TYPE_SYM: if (SDPK_sym[key_arr_idx].len > 0) { copy_kek(&req.key, &SDPK_sym[key_arr_idx], KEK_TYPE_SYM); DEK_LOGD("SDPK_sym len : %d\n", req.key.len); }else{ DEK_LOGE("SDPK_sym not-available\n"); ret = -EIO; goto err; } break; case KEK_TYPE_RSA_PUB: if (SDPK_Rpub[key_arr_idx].len > 0) { copy_kek(&req.key, &SDPK_Rpub[key_arr_idx], KEK_TYPE_RSA_PUB); DEK_LOGD("SDPK_Rpub len : %d\n", req.key.len); } else { DEK_LOGE("SDPK_Rpub not-available\n"); ret = -EIO; goto err; } break; case KEK_TYPE_RSA_PRIV: #ifdef CONFIG_SDP_IOCTL_PRIV if (SDPK_Rpri[key_arr_idx].len > 0) { copy_kek(&req.key, &SDPK_Rpri[key_arr_idx], KEK_TYPE_RSA_PRIV); DEK_LOGD("SDPK_Rpri len : %d\n", req.key.len); } else { DEK_LOGE("SDPK_Rpri not-available\n"); ret = -EIO; goto err; } #else DEK_LOGE("SDPK_Rpri not exposed\n"); ret = -EOPNOTSUPP; goto err; #endif break; case KEK_TYPE_DH_PUB: if (SDPK_Dpub[key_arr_idx].len > 0) { copy_kek(&req.key, &SDPK_Dpub[key_arr_idx], KEK_TYPE_DH_PUB); DEK_LOGD("SDPK_Dpub len : %d\n", req.key.len); } else { DEK_LOGE("SDPK_Dpub not-available\n"); ret = -EIO; goto err; } break; case KEK_TYPE_DH_PRIV: #ifdef CONFIG_SDP_IOCTL_PRIV if (SDPK_Dpri[key_arr_idx].len > 0) { copy_kek(&req.key, &SDPK_Dpri[key_arr_idx], KEK_TYPE_DH_PRIV); DEK_LOGD("SDPK_Dpri len : %d\n", req.key.len); } else { DEK_LOGE("SDPK_Dpri not-available\n"); ret = -EIO; goto err; } #else DEK_LOGE("SDPK_Dpri not exposed\n"); ret = -EOPNOTSUPP; goto err; #endif break; case KEK_TYPE_ECDH256_PUB: if (SDPK_EDpub[key_arr_idx].len > 0) { copy_kek(&req.key, &SDPK_EDpub[key_arr_idx], KEK_TYPE_ECDH256_PUB); DEK_LOGD("SDPK_EDpub len : %d\n", req.key.len); } else { DEK_LOGE("SDPK_EDpub not-available\n"); ret = -EIO; goto err; } break; case KEK_TYPE_ECDH256_PRIV: #ifdef CONFIG_SDP_IOCTL_PRIV if (SDPK_EDpri[key_arr_idx].len > 0) { copy_kek(&req.key, &SDPK_EDpub[key_arr_idx], KEK_TYPE_ECDH256_PRIV); DEK_LOGD("SDPK_EDpri len : %d\n", req.key.len); } else { DEK_LOGE("SDPK_EDpri not-available\n"); ret = -EIO; goto err; } #else DEK_LOGE("SDPK_EDpri not exposed\n"); ret = -EOPNOTSUPP; goto err; #endif break; default: DEK_LOGE("invalid key type\n"); ret = -EINVAL; goto err; break; } if(copy_to_user(ubuf, &req, sizeof(req))) { DEK_LOGE("can't copy to user kek\n"); zero_out((char *)&req, sizeof(dek_arg_get_kek)); ret = -EFAULT; goto err; } zero_out((char *)&req, sizeof(dek_arg_get_kek)); break; } default: DEK_LOGE("%s case default\n", __func__); ret = -EINVAL; break; } return ret; err: return ret; }