z90main.c

来自「h内核」· C语言 代码 · 共 2,511 行 · 第 1/5 页

C
2,511
字号
	}	return status;}static inline unsigned char *get_status_qdepth_mask(unsigned char qdepth[Z90CRYPT_NUM_APS]){	int i, ix;	memset(qdepth, 0, Z90CRYPT_NUM_APS);	for (i = 0; i < get_status_totalcount(); i++) {		ix = SHRT2LONG(i);		qdepth[ix] = LONG2DEVPTR(ix)->dev_caller_count;	}	return qdepth;}static inline unsigned int *get_status_perdevice_reqcnt(unsigned int reqcnt[Z90CRYPT_NUM_APS]){	int i, ix;	memset(reqcnt, 0, Z90CRYPT_NUM_APS * sizeof(int));	for (i = 0; i < get_status_totalcount(); i++) {		ix = SHRT2LONG(i);		reqcnt[ix] = LONG2DEVPTR(ix)->dev_total_req_cnt;	}	return reqcnt;}static inline voidinit_work_element(struct work_element *we_p,		  struct priv_data *priv_data, pid_t pid){	int step;	we_p->requestptr = (unsigned char *)we_p + sizeof(struct work_element);	/* Come up with a unique id for this caller. */	step = atomic_inc_return(&z90crypt_step);	memcpy(we_p->caller_id+0, (void *) &pid, sizeof(pid));	memcpy(we_p->caller_id+4, (void *) &step, sizeof(step));	we_p->pid = pid;	we_p->priv_data = priv_data;	we_p->status[0] = STAT_DEFAULT;	we_p->audit[0] = 0x00;	we_p->audit[1] = 0x00;	we_p->audit[2] = 0x00;	we_p->resp_buff_size = 0;	we_p->retcode = 0;	we_p->devindex = -1;	we_p->devtype = -1;	atomic_set(&we_p->alarmrung, 0);	init_waitqueue_head(&we_p->waitq);	INIT_LIST_HEAD(&(we_p->liste));}static inline intallocate_work_element(struct work_element **we_pp,		      struct priv_data *priv_data_p, pid_t pid){	struct work_element *we_p;	we_p = (struct work_element *) get_zeroed_page(GFP_KERNEL);	if (!we_p)		return -ENOMEM;	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++;}/** * Bitlength limits for each card * * There are new MCLs which allow more bitlengths. See the table for details. * The MCL must be applied and the newer bitlengths enabled for these to work. * * Card Type    Old limit    New limit * PCICC         512-1024     512-2048 * PCIXCC_MCL2   512-2048     no change (applying this MCL == card is MCL3+) * PCIXCC_MCL3   512-2048     128-2048 * CEX2C         512-2048     128-2048 * * ext_bitlens (extended bitlengths) is a global, since you should not apply an * MCL to just one card in a machine. We assume, at first, that all cards have * these capabilities. */int ext_bitlens = 1; // This is global#define PCIXCC_MIN_MOD_SIZE	 16	//  128 bits#define OLD_PCIXCC_MIN_MOD_SIZE	 64	//  512 bits#define PCICC_MIN_MOD_SIZE	 64	//  512 bits#define OLD_PCICC_MAX_MOD_SIZE	128	// 1024 bits#define MAX_MOD_SIZE		256	// 2048 bitsstatic inline intselect_device_type(int *dev_type_p, int bytelength){	static int count = 0;	int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, index_to_use;	struct status *stat;	if ((*dev_type_p != PCICC) && (*dev_type_p != PCICA) &&	    (*dev_type_p != PCIXCC_MCL2) && (*dev_type_p != PCIXCC_MCL3) &&	    (*dev_type_p != CEX2C) && (*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;	}	/* Assumption: PCICA, PCIXCC_MCL3, and CEX2C are all similar in speed */	stat = &z90crypt.hdware_info->type_mask[PCICA];	PCICA_avail = stat->st_count -			(stat->disabled_count + stat->user_disabled_count);	stat = &z90crypt.hdware_info->type_mask[PCIXCC_MCL3];	PCIXCC_MCL3_avail = stat->st_count -			(stat->disabled_count + stat->user_disabled_count);	stat = &z90crypt.hdware_info->type_mask[CEX2C];	CEX2C_avail = stat->st_count -			(stat->disabled_count + stat->user_disabled_count);	if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail) {		/**		 * bitlength is a factor, PCICA is the most capable, even with		 * the new MCL.		 */		if ((bytelength < PCIXCC_MIN_MOD_SIZE) ||		    (!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) {			if (!PCICA_avail)				return -1;			else {				*dev_type_p = PCICA;				return 0;			}		}		index_to_use = count % (PCICA_avail + PCIXCC_MCL3_avail +					CEX2C_avail);		if (index_to_use < PCICA_avail)			*dev_type_p = PCICA;		else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail))			*dev_type_p = PCIXCC_MCL3;		else			*dev_type_p = CEX2C;		count++;		return 0;	}	/* Less than OLD_PCIXCC_MIN_MOD_SIZE cannot go to a PCIXCC_MCL2 */	if (bytelength < OLD_PCIXCC_MIN_MOD_SIZE)		return -1;	stat = &z90crypt.hdware_info->type_mask[PCIXCC_MCL2];	if (stat->st_count >	    (stat->disabled_count + stat->user_disabled_count)) {		*dev_type_p = PCIXCC_MCL2;		return 0;	}	/**	 * Less than PCICC_MIN_MOD_SIZE or more than OLD_PCICC_MAX_MOD_SIZE	 * (if we don't have the MCL applied and the newer bitlengths enabled)	 * cannot go to a PCICC	 */	if ((bytelength < PCICC_MIN_MOD_SIZE) ||	    (!ext_bitlens && (bytelength > OLD_PCICC_MAX_MOD_SIZE))) {		return -1;	}	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 bytelength){	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, bytelength) == -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;	int bytelen = ((struct ica_rsa_modexpo *)we_p->buffer)->inputdatalength;	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, bytelen) == -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};/** * 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_MCL2) && (we_p->devtype != PCIXCC_MCL3) &&	    (we_p->devtype != CEX2C))		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_init(&caller_p->caller_liste);			device_p->dev_caller_count--;		}	memset(caller_p->caller_id, 0, sizeof(caller_p->caller_id));}static inline intget_crypto_request_buffer(struct work_element *we_p)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?