⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cryptocop.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	cdesc->dma_descr->wait = 1;	cdesc->dma_descr->out_eop = 1; /* Since this is a pad output is pushed.  EOP is ok here since the padded unit is the only one active. */	cdesc->dma_descr->buf = (char*)virt_to_phys((char*)pad);	cdesc->dma_descr->after = cdesc->dma_descr->buf + plen;	cdesc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_out, mo);	*pad_desc = cdesc;	return 0; error_cleanup:	if (cdesc) free_cdesc(cdesc);	return -1;}static int setup_key_dl_desc(struct cryptocop_tfrm_ctx *tc, struct cryptocop_dma_desc **kd, int alloc_flag){	struct cryptocop_dma_desc  *key_desc = alloc_cdesc(alloc_flag);	struct strcop_meta_out     mo = {0};	DEBUG(printk("setup_key_dl_desc\n"));	if (!key_desc) {		DEBUG_API(printk("setup_key_dl_desc: failed descriptor allocation.\n"));		return -ENOMEM;	}	/* Download key. */	if ((tc->tctx->init.alg == cryptocop_alg_aes) && (tc->tcfg->flags & CRYPTOCOP_DECRYPT)) {		/* Precook the AES decrypt key. */		if (!tc->tctx->dec_key_set){			get_aes_decrypt_key(tc->tctx->dec_key, tc->tctx->init.key, tc->tctx->init.keylen);			tc->tctx->dec_key_set = 1;		}		key_desc->dma_descr->buf = (char*)virt_to_phys(tc->tctx->dec_key);		key_desc->dma_descr->after = key_desc->dma_descr->buf + tc->tctx->init.keylen/8;	} else {		key_desc->dma_descr->buf = (char*)virt_to_phys(tc->tctx->init.key);		key_desc->dma_descr->after = key_desc->dma_descr->buf + tc->tctx->init.keylen/8;	}	/* Setup metadata. */	mo.dlkey = 1;	switch (tc->tctx->init.keylen) {	case 64:		mo.decrypt = 0;		mo.hashmode = 0;		break;	case 128:		mo.decrypt = 0;		mo.hashmode = 1;		break;	case 192:		mo.decrypt = 1;		mo.hashmode = 0;		break;	case 256:		mo.decrypt = 1;		mo.hashmode = 1;		break;	default:		break;	}	mo.ciphsel = mo.hashsel = mo.csumsel = src_none;	key_desc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_out, mo);	key_desc->dma_descr->out_eop = 1;	key_desc->dma_descr->wait = 1;	key_desc->dma_descr->intr = 0;	*kd = key_desc;	return 0;}static int setup_cipher_iv_desc(struct cryptocop_tfrm_ctx *tc, struct cryptocop_dma_desc **id, int alloc_flag){	struct cryptocop_dma_desc  *iv_desc = alloc_cdesc(alloc_flag);	struct strcop_meta_out     mo = {0};	DEBUG(printk("setup_cipher_iv_desc\n"));	if (!iv_desc) {		DEBUG_API(printk("setup_cipher_iv_desc: failed CBC IV descriptor allocation.\n"));		return -ENOMEM;	}	/* Download IV. */	iv_desc->dma_descr->buf = (char*)virt_to_phys(tc->tcfg->iv);	iv_desc->dma_descr->after = iv_desc->dma_descr->buf + tc->blocklength;	/* Setup metadata. */	mo.hashsel = mo.csumsel = src_none;	mo.ciphsel = src_dma;	mo.ciphconf = tc->ciph_conf;	mo.cbcmode = tc->cbcmode;	iv_desc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_out, mo);	iv_desc->dma_descr->out_eop = 0;	iv_desc->dma_descr->wait = 1;	iv_desc->dma_descr->intr = 0;	*id = iv_desc;	return 0;}/* Map the ouput length of the transform to operation output starting on the inject index. */static int create_input_descriptors(struct cryptocop_operation *operation, struct cryptocop_tfrm_ctx *tc, struct cryptocop_dma_desc **id, int alloc_flag){	int                        err = 0;	struct cryptocop_dma_desc  head = {0};	struct cryptocop_dma_desc  *outdesc = &head;	size_t                     iov_offset = 0;	size_t                     out_ix = 0;	int                        outiov_ix = 0;	struct strcop_meta_in      mi = {0};	size_t                     out_length = tc->produced;	int                        rem_length;	int                        dlength;	assert(out_length != 0);	if (((tc->produced + tc->tcfg->inject_ix) > operation->tfrm_op.outlen) || (tc->produced && (operation->tfrm_op.outlen == 0))) {		DEBUG_API(printk("create_input_descriptors: operation outdata too small\n"));		return -EINVAL;	}	/* Traverse the out iovec until the result inject index is reached. */	while ((outiov_ix < operation->tfrm_op.outcount) && ((out_ix + operation->tfrm_op.outdata[outiov_ix].iov_len) <= tc->tcfg->inject_ix)){		out_ix += operation->tfrm_op.outdata[outiov_ix].iov_len;		outiov_ix++;	}	if (outiov_ix >= operation->tfrm_op.outcount){		DEBUG_API(printk("create_input_descriptors: operation outdata too small\n"));		return -EINVAL;	}	iov_offset = tc->tcfg->inject_ix - out_ix;	mi.dmasel = tc->unit_no;	/* Setup the output descriptors. */	while ((out_length > 0) && (outiov_ix < operation->tfrm_op.outcount)) {		outdesc->next = alloc_cdesc(alloc_flag);		if (!outdesc->next) {			DEBUG_API(printk("create_input_descriptors: alloc_cdesc\n"));			err = -ENOMEM;			goto error_cleanup;		}		outdesc = outdesc->next;		rem_length = operation->tfrm_op.outdata[outiov_ix].iov_len - iov_offset;		dlength = (out_length < rem_length) ? out_length : rem_length;		DEBUG(printk("create_input_descriptors:\n"			     "outiov_ix=%d, rem_length=%d, dlength=%d\n"			     "iov_offset=%d, outdata[outiov_ix].iov_len=%d\n"			     "outcount=%d, outiov_ix=%d\n",			     outiov_ix, rem_length, dlength, iov_offset, operation->tfrm_op.outdata[outiov_ix].iov_len, operation->tfrm_op.outcount, outiov_ix));		outdesc->dma_descr->buf = (char*)virt_to_phys(operation->tfrm_op.outdata[outiov_ix].iov_base + iov_offset);		outdesc->dma_descr->after = outdesc->dma_descr->buf + dlength;		outdesc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_in, mi);		out_length -= dlength;		iov_offset += dlength;		if (iov_offset >= operation->tfrm_op.outdata[outiov_ix].iov_len) {			iov_offset = 0;			++outiov_ix;		}	}	if (out_length > 0){		DEBUG_API(printk("create_input_descriptors: not enough room for output, %d remained\n", out_length));		err = -EINVAL;		goto error_cleanup;	}	/* Set sync in last descriptor. */	mi.sync = 1;	outdesc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_in, mi);	*id = head.next;	return 0; error_cleanup:	while (head.next) {		outdesc = head.next->next;		free_cdesc(head.next);		head.next = outdesc;	}	return err;}static int create_output_descriptors(struct cryptocop_operation *operation, int *iniov_ix, int *iniov_offset, size_t desc_len, struct cryptocop_dma_desc **current_out_cdesc, struct strcop_meta_out *meta_out, int alloc_flag){	while (desc_len != 0) {		struct cryptocop_dma_desc  *cdesc;		int                        rem_length = operation->tfrm_op.indata[*iniov_ix].iov_len - *iniov_offset;		int                        dlength = (desc_len < rem_length) ? desc_len : rem_length;		cdesc = alloc_cdesc(alloc_flag);		if (!cdesc) {			DEBUG_API(printk("create_output_descriptors: alloc_cdesc\n"));			return -ENOMEM;		}		(*current_out_cdesc)->next = cdesc;		(*current_out_cdesc) = cdesc;		cdesc->free_buf = NULL;		cdesc->dma_descr->buf = (char*)virt_to_phys(operation->tfrm_op.indata[*iniov_ix].iov_base + *iniov_offset);		cdesc->dma_descr->after = cdesc->dma_descr->buf + dlength;		desc_len -= dlength;		*iniov_offset += dlength;		assert(desc_len >= 0);		if (*iniov_offset >= operation->tfrm_op.indata[*iniov_ix].iov_len) {			*iniov_offset = 0;			++(*iniov_ix);			if (*iniov_ix > operation->tfrm_op.incount) {				DEBUG_API(printk("create_output_descriptors: not enough indata in operation."));				return  -EINVAL;			}		}		cdesc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_out, (*meta_out));	} /* while (desc_len != 0) */	/* Last DMA descriptor gets a 'wait' bit to signal expected change in metadata. */	(*current_out_cdesc)->dma_descr->wait = 1; /* This will set extraneous WAIT in some situations, e.g. when padding hashes and checksums. */	return 0;}static int append_input_descriptors(struct cryptocop_operation *operation, struct cryptocop_dma_desc **current_in_cdesc, struct cryptocop_dma_desc **current_out_cdesc, struct cryptocop_tfrm_ctx *tc, int alloc_flag){	DEBUG(printk("append_input_descriptors, tc=0x%p, unit_no=%d\n", tc, tc->unit_no));	if (tc->tcfg) {		int                        failed = 0;		struct cryptocop_dma_desc  *idescs = NULL;		DEBUG(printk("append_input_descriptors: pushing output, consumed %d produced %d bytes.\n", tc->consumed, tc->produced));		if (tc->pad_descs) {			DEBUG(printk("append_input_descriptors: append pad descriptors to DMA out list.\n"));			while (tc->pad_descs) {				DEBUG(printk("append descriptor 0x%p\n", tc->pad_descs));				(*current_out_cdesc)->next = tc->pad_descs;				tc->pad_descs = tc->pad_descs->next;				(*current_out_cdesc) = (*current_out_cdesc)->next;			}		}		/* Setup and append output descriptors to DMA in list. */		if (tc->unit_no == src_dma){			/* mem2mem.  Setup DMA in descriptors to discard all input prior to the requested mem2mem data. */			struct strcop_meta_in mi = {.sync = 0, .dmasel = src_dma};			unsigned int start_ix = tc->start_ix;			while (start_ix){				unsigned int desclen = start_ix < MEM2MEM_DISCARD_BUF_LENGTH ? start_ix : MEM2MEM_DISCARD_BUF_LENGTH;				(*current_in_cdesc)->next = alloc_cdesc(alloc_flag);				if (!(*current_in_cdesc)->next){					DEBUG_API(printk("append_input_descriptors: alloc_cdesc mem2mem discard failed\n"));					return -ENOMEM;				}				(*current_in_cdesc) = (*current_in_cdesc)->next;				(*current_in_cdesc)->dma_descr->buf = (char*)virt_to_phys(mem2mem_discard_buf);				(*current_in_cdesc)->dma_descr->after = (*current_in_cdesc)->dma_descr->buf + desclen;				(*current_in_cdesc)->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_in, mi);				start_ix -= desclen;			}			mi.sync = 1;			(*current_in_cdesc)->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_in, mi);		}		failed = create_input_descriptors(operation, tc, &idescs, alloc_flag);		if (failed){			DEBUG_API(printk("append_input_descriptors: output descriptor setup failed\n"));			return failed;		}		DEBUG(printk("append_input_descriptors: append output descriptors to DMA in list.\n"));		while (idescs) {			DEBUG(printk("append descriptor 0x%p\n", idescs));			(*current_in_cdesc)->next = idescs;			idescs = idescs->next;			(*current_in_cdesc) = (*current_in_cdesc)->next;		}	}	return 0;}static int cryptocop_setup_dma_list(struct cryptocop_operation *operation, struct cryptocop_int_operation **int_op, int alloc_flag){	struct cryptocop_session *sess;	struct cryptocop_transform_ctx *tctx;	struct cryptocop_tfrm_ctx digest_ctx = {		.previous_src = src_none,		.current_src = src_none,		.start_ix = 0,		.requires_padding = 1,		.strict_block_length = 0,		.hash_conf = 0,		.hash_mode = 0,		.ciph_conf = 0,		.cbcmode = 0,		.decrypt = 0,		.consumed = 0,		.produced = 0,		.pad_descs = NULL,		.active = 0,		.done = 0,		.prev_src = NULL,		.curr_src = NULL,		.tcfg = NULL};	struct cryptocop_tfrm_ctx cipher_ctx = {		.previous_src = src_none,		.current_src = src_none,		.start_ix = 0,		.requires_padding = 0,		.strict_block_length = 1,		.hash_conf = 0,		.hash_mode = 0,		.ciph_conf = 0,		.cbcmode = 0,		.decrypt = 0,		.consumed = 0,		.produced = 0,		.pad_descs = NULL,		.active = 0,		.done = 0,		.prev_src = NULL,		.curr_src = NULL,		.tcfg = NULL};	struct cryptocop_tfrm_ctx csum_ctx = {		.previous_src = src_none,		.current_src = src_none,		.start_ix = 0,		.blocklength = 2,		.requires_padding = 1,		.strict_block_length = 0,		.hash_conf = 0,		.hash_mode = 0,		.ciph_conf = 0,		.cbcmode = 0,		.decrypt = 0,		.consumed = 0,		.produced = 0,		.pad_descs = NULL,		.active = 0,		.done = 0,		.tcfg = NULL,		.prev_src = NULL,		.curr_src = NULL,		.unit_no = src_csum};	struct cryptocop_tfrm_cfg *tcfg = operation->tfrm_op.tfrm_cfg;	unsigned int indata_ix = 0;	/* iovec accounting. */	int iniov_ix = 0;	int iniov_offset = 0;	/* Operation descriptor cfg traversal pointer. */	struct cryptocop_desc *odsc;	int failed = 0;	/* List heads for allocated descriptors. */	struct cryptocop_dma_desc out_cdesc_head = {0};	struct cryptocop_dma_desc in_cdesc_head = {0};	struct cryptocop_dma_desc *current_out_cdesc = &out_cdesc_head;	struct cryptocop_dma_desc *current_in_cdesc = &in_cdesc_head;	struct cryptocop_tfrm_ctx *output_tc = NULL;	void                      *iop_alloc_ptr;	assert(operation != NULL);	assert(int_op != NULL);	DEBUG(printk("cryptocop_setup_dma_list: start\n"));	DEBUG(print_cryptocop_operation(operation));	sess = get_session(operation->sid);	if (!sess) {		DEBUG_API(printk("cryptocop_setup_dma_list: no session found for operation.\n"));		failed = -EINVAL;		goto error_cleanup;	}	iop_alloc_ptr = kmalloc(DESCR_ALLOC_PAD + sizeof(struct cryptocop_int_operation), alloc_flag);	if (!iop_alloc_ptr) {		DEBUG_API(printk("cryptocop_setup_dma_list:  kmalloc cryptocop_int_operation\n"));		failed = -ENOMEM;		goto error_cleanup;	}	(*int_op) = (struct cryptocop_int_operation*)(((unsigned long int)(iop_alloc_ptr + DESCR_ALLOC_PAD + offsetof(struct cryptocop_int_operation, ctx_out)) & ~0x0000001F) - offsetof(struct cryptocop_int_operation, ctx_out));	DEBUG(memset((*int_op), 0xff, sizeof(struct cryptocop_int_operation)));	(*int_op)->alloc_ptr = iop_alloc_ptr;	DEBUG(printk("cryptocop_setup_dma_list: *int_op=0x%p, alloc_ptr=0x%p\n", *int_op, (*int_op)->alloc_ptr));	(*int_op)->sid = operation->sid;	(*int_op)->cdesc_out = NULL;	(*int_op)->cdesc_in = NULL;	(*int_op)->tdes_mode = cryptocop_3des_ede;	(*int_op)->csum_mode = cryptocop_csum_le;	(*int_op)->ddesc_out = NULL;	(*int_op)->ddesc_in = NULL;	/* Scan operation->tfrm_op.tfrm_cfg for bad configuration and set up the local contexts. */	if (!tcfg) {		DEBUG_API(printk("cryptocop_setup_dma_list: no configured transforms in operation.\n"));		failed = -EINVAL;		goto error_cleanup;	}	while (tcfg) {		tctx = get_transform_ctx(sess, tcfg->tid);

⌨️ 快捷键说明

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