📄 z90main.c
字号:
init_work_element(we_p, priv_data_p, pid); *we_pp = we_p; return 0;}static inline voidremove_device(struct device *device_p){ if (!device_p || device_p->disabled != 0) return; device_p->disabled = 1; z90crypt.hdware_info->type_mask[device_p->dev_type].disabled_count++; z90crypt.hdware_info->hdware_mask.disabled_count++;}static inline intselect_device_type(int *dev_type_p){ struct status *stat; if ((*dev_type_p != PCICC) && (*dev_type_p != PCICA) && (*dev_type_p != PCIXCC) && (*dev_type_p != ANYDEV)) return -1; if (*dev_type_p != ANYDEV) { stat = &z90crypt.hdware_info->type_mask[*dev_type_p]; if (stat->st_count > stat->disabled_count + stat->user_disabled_count) return 0; return -1; } stat = &z90crypt.hdware_info->type_mask[PCICA]; if (stat->st_count > stat->disabled_count + stat->user_disabled_count) { *dev_type_p = PCICA; return 0; } stat = &z90crypt.hdware_info->type_mask[PCIXCC]; if (stat->st_count > stat->disabled_count + stat->user_disabled_count) { *dev_type_p = PCIXCC; return 0; } stat = &z90crypt.hdware_info->type_mask[PCICC]; if (stat->st_count > stat->disabled_count + stat->user_disabled_count) { *dev_type_p = PCICC; return 0; } return -1;}/** * Try the selected number, then the selected type (can be ANYDEV) */static inline intselect_device(int *dev_type_p, int *device_nr_p){ int i, indx, devTp, low_count, low_indx; struct device_x *index_p; struct device *dev_ptr; PDEBUG("device type = %d, index = %d\n", *dev_type_p, *device_nr_p); if ((*device_nr_p >= 0) && (*device_nr_p < Z90CRYPT_NUM_DEVS)) { PDEBUG("trying index = %d\n", *device_nr_p); dev_ptr = z90crypt.device_p[*device_nr_p]; if (dev_ptr && dev_ptr->dev_stat != DEV_GONE && dev_ptr->disabled == 0 && dev_ptr->user_disabled == 0) { PDEBUG("selected by number, index = %d\n", *device_nr_p); *dev_type_p = dev_ptr->dev_type; return *device_nr_p; } } *device_nr_p = -1; PDEBUG("trying type = %d\n", *dev_type_p); devTp = *dev_type_p; if (select_device_type(&devTp) == -1) { PDEBUG("failed to select by type\n"); return -1; } PDEBUG("selected type = %d\n", devTp); index_p = &z90crypt.hdware_info->type_x_addr[devTp]; low_count = 0x0000FFFF; low_indx = -1; for (i = 0; i < z90crypt.hdware_info->type_mask[devTp].st_count; i++) { indx = index_p->device_index[i]; dev_ptr = z90crypt.device_p[indx]; if (dev_ptr && dev_ptr->dev_stat != DEV_GONE && dev_ptr->disabled == 0 && dev_ptr->user_disabled == 0 && devTp == dev_ptr->dev_type && low_count > dev_ptr->dev_caller_count) { low_count = dev_ptr->dev_caller_count; low_indx = indx; } } *device_nr_p = low_indx; return low_indx;}static inline intsend_to_crypto_device(struct work_element *we_p){ struct caller *caller_p; struct device *device_p; int dev_nr; if (!we_p->requestptr) return SEN_FATAL_ERROR; caller_p = (struct caller *)we_p->requestptr; dev_nr = we_p->devindex; if (select_device(&we_p->devtype, &dev_nr) == -1) { if (z90crypt.hdware_info->hdware_mask.st_count != 0) return SEN_RETRY; else return SEN_NOT_AVAIL; } we_p->devindex = dev_nr; device_p = z90crypt.device_p[dev_nr]; if (!device_p) return SEN_NOT_AVAIL; if (device_p->dev_type != we_p->devtype) return SEN_RETRY; if (device_p->dev_caller_count >= device_p->dev_q_depth) return SEN_QUEUE_FULL; PDEBUG("device number prior to send: %d\n", dev_nr); switch (send_to_AP(dev_nr, z90crypt.cdx, caller_p->caller_dev_dep_req_l, caller_p->caller_dev_dep_req_p)) { case DEV_SEN_EXCEPTION: PRINTKC("Exception during send to device %d\n", dev_nr); z90crypt.terminating = 1; return SEN_FATAL_ERROR; case DEV_GONE: PRINTK("Device %d not available\n", dev_nr); remove_device(device_p); return SEN_NOT_AVAIL; case DEV_EMPTY: return SEN_NOT_AVAIL; case DEV_NO_WORK: return SEN_FATAL_ERROR; case DEV_BAD_MESSAGE: return SEN_USER_ERROR; case DEV_QUEUE_FULL: return SEN_QUEUE_FULL; default: case DEV_ONLINE: break; } list_add_tail(&(caller_p->caller_liste), &(device_p->dev_caller_list)); device_p->dev_caller_count++; return 0;}/** * Send puts the user's work on one of two queues: * the pending queue if the send was successful * the request queue if the send failed because device full or busy */static inline intz90crypt_send(struct work_element *we_p, const char *buf){ int rv; PDEBUG("PID %d\n", PID()); if (CHK_RDWRMASK(we_p->status[0]) != STAT_NOWORK) { PDEBUG("PID %d tried to send more work but has outstanding " "work.\n", PID()); return -EWORKPEND; } we_p->devindex = -1; // Reset device number spin_lock_irq(&queuespinlock); rv = send_to_crypto_device(we_p); switch (rv) { case 0: we_p->requestsent = jiffies; we_p->audit[0] |= FP_SENT; list_add_tail(&we_p->liste, &pending_list); ++pendingq_count; we_p->audit[0] |= FP_PENDING; break; case SEN_BUSY: case SEN_QUEUE_FULL: rv = 0; we_p->devindex = -1; // any device will do we_p->requestsent = jiffies; list_add_tail(&we_p->liste, &request_list); ++requestq_count; we_p->audit[0] |= FP_REQUEST; break; case SEN_RETRY: rv = -ERESTARTSYS; break; case SEN_NOT_AVAIL: PRINTK("*** No devices available.\n"); rv = we_p->retcode = -ENODEV; we_p->status[0] |= STAT_FAILED; break; case REC_OPERAND_INV: case REC_OPERAND_SIZE: case REC_EVEN_MOD: case REC_INVALID_PAD: rv = we_p->retcode = -EINVAL; we_p->status[0] |= STAT_FAILED; break; default: we_p->retcode = rv; we_p->status[0] |= STAT_FAILED; break; } if (rv != -ERESTARTSYS) SET_RDWRMASK(we_p->status[0], STAT_WRITTEN); spin_unlock_irq(&queuespinlock); if (rv == 0) tasklet_schedule(&reader_tasklet); return rv;}/** * process_results copies the user's work from kernel space. */static inline intz90crypt_process_results(struct work_element *we_p, char __user *buf){ int rv; PDEBUG("we_p %p (PID %d)\n", we_p, PID()); LONG2DEVPTR(we_p->devindex)->dev_total_req_cnt++; SET_RDWRMASK(we_p->status[0], STAT_READPEND); rv = 0; if (!we_p->buffer) { PRINTK("we_p %p PID %d in STAT_READPEND: buffer NULL.\n", we_p, PID()); rv = -ENOBUFF; } if (!rv) if ((rv = copy_to_user(buf, we_p->buffer, we_p->buff_size))) { PDEBUG("copy_to_user failed: rv = %d\n", rv); rv = -EFAULT; } if (!rv) rv = we_p->retcode; if (!rv) if (we_p->resp_buff_size && copy_to_user(we_p->resp_addr, we_p->resp_buff, we_p->resp_buff_size)) rv = -EFAULT; SET_RDWRMASK(we_p->status[0], STAT_NOWORK); return rv;}static unsigned char NULL_psmid[8] ={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};/** * MIN_MOD_SIZE is a PCICC and PCIXCC limit. * MAX_PCICC_MOD_SIZE is a hard limit for the PCICC. * MAX_MOD_SIZE is a hard limit for the PCIXCC and PCICA. */#define MIN_MOD_SIZE 64#define MAX_PCICC_MOD_SIZE 128#define MAX_MOD_SIZE 256/** * Used in device configuration functions */#define MAX_RESET 90/** * This is used only for PCICC support */static inline intis_PKCS11_padded(unsigned char *buffer, int length){ int i; if ((buffer[0] != 0x00) || (buffer[1] != 0x01)) return 0; for (i = 2; i < length; i++) if (buffer[i] != 0xFF) break; if ((i < 10) || (i == length)) return 0; if (buffer[i] != 0x00) return 0; return 1;}/** * This is used only for PCICC support */static inline intis_PKCS12_padded(unsigned char *buffer, int length){ int i; if ((buffer[0] != 0x00) || (buffer[1] != 0x02)) return 0; for (i = 2; i < length; i++) if (buffer[i] == 0x00) break; if ((i < 10) || (i == length)) return 0; if (buffer[i] != 0x00) return 0; return 1;}/** * builds struct caller and converts message from generic format to * device-dependent format * func is ICARSAMODEXPO or ICARSACRT * function is PCI_FUNC_KEY_ENCRYPT or PCI_FUNC_KEY_DECRYPT */static inline intbuild_caller(struct work_element *we_p, short function){ int rv; struct caller *caller_p = (struct caller *)we_p->requestptr; if ((we_p->devtype != PCICC) && (we_p->devtype != PCICA) && (we_p->devtype != PCIXCC)) return SEN_NOT_AVAIL; memcpy(caller_p->caller_id, we_p->caller_id, sizeof(caller_p->caller_id)); caller_p->caller_dev_dep_req_p = caller_p->caller_dev_dep_req; caller_p->caller_dev_dep_req_l = MAX_RESPONSE_SIZE; caller_p->caller_buf_p = we_p->buffer; INIT_LIST_HEAD(&(caller_p->caller_liste)); rv = convert_request(we_p->buffer, we_p->funccode, function, z90crypt.cdx, we_p->devtype, &caller_p->caller_dev_dep_req_l, caller_p->caller_dev_dep_req_p); if (rv) { if (rv == SEN_NOT_AVAIL) PDEBUG("request can't be processed on hdwr avail\n"); else PRINTK("Error from convert_request: %d\n", rv); } else memcpy(&(caller_p->caller_dev_dep_req_p[4]), we_p->caller_id,8); return rv;}static inline voidunbuild_caller(struct device *device_p, struct caller *caller_p){ if (!caller_p) return; if (caller_p->caller_liste.next && caller_p->caller_liste.prev) if (!list_empty(&caller_p->caller_liste)) { list_del(&caller_p->caller_liste); device_p->dev_caller_count--; INIT_LIST_HEAD(&caller_p->caller_liste); } memset(caller_p->caller_id, 0, sizeof(caller_p->caller_id));}static inline intget_crypto_request_buffer(struct work_element *we_p){ struct ica_rsa_modexpo *mex_p; struct ica_rsa_modexpo_crt *crt_p; unsigned char *temp_buffer; short function; int rv; mex_p = (struct ica_rsa_modexpo *) we_p->buffer; crt_p = (struct ica_rsa_modexpo_crt *) we_p->buffer; PDEBUG("device type input = %d\n", we_p->devtype); if (z90crypt.terminating) return REC_NO_RESPONSE; if (memcmp(we_p->caller_id, NULL_psmid, 8) == 0) { PRINTK("psmid zeroes\n"); return SEN_FATAL_ERROR; } if (!we_p->buffer) { PRINTK("buffer pointer NULL\n"); return SEN_USER_ERROR; } if (!we_p->requestptr) { PRINTK("caller pointer NULL\n"); return SEN_USER_ERROR; } if ((we_p->devtype != PCICA) && (we_p->devtype != PCICC) && (we_p->devtype != PCIXCC) && (we_p->devtype != ANYDEV)) { PRINTK("invalid device type\n"); return SEN_USER_ERROR; } if ((mex_p->inputdatalength < 1) || (mex_p->inputdatalength > MAX_MOD_SIZE)) { PRINTK("inputdatalength[%d] is not valid\n", mex_p->inputdatalength); return SEN_USER_ERROR; } if (mex_p->outputdatalength < mex_p->inputdatalength) { PRINTK("outputdatalength[%d] < inputdatalength[%d]\n", mex_p->outputdatalength, mex_p->inputdatalength); return SEN_USER_ERROR; } if (!mex_p->inputdata || !mex_p->outputdata) { PRINTK("inputdata[%p] or outputdata[%p] is NULL\n", mex_p->outputdata, mex_p->inputdata); return SEN_USER_ERROR; } /** * As long as outputdatalength is big enough, we can set the * outputdatalength equal to the inputdatalength, since that is the * number of bytes we will copy in any case */ mex_p->outputdatalength = mex_p->inputdatalength; rv = 0; switch (we_p->funccode) { case ICARSAMODEXPO: if (!mex_p->b_key || !mex_p->n_modulus) rv = SEN_USER_ERROR; break; case ICARSACRT: if (!IS_EVEN(crt_p->inputdatalength)) { PRINTK("inputdatalength[%d] is odd, CRT form\n", crt_p->inputdatalength); rv = SEN_USER_ERROR; break; } if (!crt_p->bp_key || !crt_p->bq_key || !crt_p->np_prime || !crt_p->nq_prime || !crt_p->u_mult_inv) { PRINTK("CRT form, bad data: %p/%p/%p/%p/%p\n", crt_p->bp_key, crt_p->bq_key, crt_p->np_prime, crt_p->nq_prime, crt_p->u_mult_inv); rv = SEN_USER_ERROR; } break; default: PRINTK("bad func = %d\n", we_p->funccode); rv = SEN_USER_ERROR; break; } if (rv != 0) return rv; if (select_device_type(&we_p->devtype) < 0) return SEN_NOT_AVAIL; temp_buffer = (unsigned char *)we_p + sizeof(struct work_element) + sizeof(struct caller); if (copy_from_user(temp_buffer, mex_p->inputdata, mex_p->inputdatalength) != 0) return SEN_RELEASED; function = PCI_FUNC_KEY_ENCRYPT; switch (we_p->devtype) { /* PCICA does everything with a simple RSA mod-expo operation */ case PCICA: function = PCI_FUNC_KEY_ENCRYPT; break; /** * PCIXCC does all Mod-Expo form with a simple RSA mod-expo * operation, and all CRT forms with a PKCS-1.2 format decrypt. */ case PCIXCC: /* Anything less than MIN_MOD_SIZE MUST go to a PCICA */ if (mex_p->inputdatalength < MIN_MOD_SIZE) return SEN_NOT_AVAIL; if (we_p->funccode == ICARSAMODEXPO) function = PCI_FUNC_KEY_ENCRYPT; else function = PCI_FUNC_KEY_DECRYPT; break; /** * PCICC does everything as a PKCS-1.2 format request */ case PCICC: /* Anything less than MIN_MOD_SIZE MUST go to a PCICA */ if (mex_p->inputdatalength < MIN_MOD_SIZE) { return SEN_NOT_AVAIL; } /* Anythings over MAX_PCICC_MOD_SIZE MUST go to a PCICA */ if (mex_p->inputdatalength > MAX_PCICC_MOD_SIZE) { return SEN_NOT_AVAIL; } /* PCICC cannot handle input that is is PKCS#1.1 padded */ if (is_PKCS11_padded(temp_buffer, mex_p->inputdatalength)) { return SEN_NOT_AVAIL; } if (we_p->funccode == ICARSAMODEXPO) { if (is_PKCS12_padded(temp_buffer, mex_p->inputdatalength)) function = PCI_FUNC_KEY_ENCRYPT; else function = PCI_FUNC_KEY_DECRYPT; } else /* all CRT forms are decrypts */ function = PCI_FUNC_KEY_DECRYPT; break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -