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

📄 cryptocop.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
				current_out_cdesc->next = ed;				current_out_cdesc = ed;			} else {				/* Set EOP in the current out descriptor since the only active module is				 * the one needing the EOP. */				current_out_cdesc->dma_descr->out_eop = 1;			}		}		if (cipher_ctx.done && cipher_ctx.active) cipher_ctx.active = 0;		if (digest_ctx.done && digest_ctx.active) digest_ctx.active = 0;		if (csum_ctx.done && csum_ctx.active) csum_ctx.active = 0;		indata_ix += odsc->length;		odsc = odsc->next;	} /* while (odsc) */ /* Process descriptors. */	DEBUG(printk("cryptocop_setup_dma_list: done parsing operation descriptors\n"));	if (cipher_ctx.tcfg && (cipher_ctx.active || !cipher_ctx.done)){		DEBUG_API(printk("cryptocop_setup_dma_list: cipher operation not terminated.\n"));		failed = -EINVAL;		goto error_cleanup;	}	if (digest_ctx.tcfg && (digest_ctx.active || !digest_ctx.done)){		DEBUG_API(printk("cryptocop_setup_dma_list: digest operation not terminated.\n"));		failed = -EINVAL;		goto error_cleanup;	}	if (csum_ctx.tcfg && (csum_ctx.active || !csum_ctx.done)){		DEBUG_API(printk("cryptocop_setup_dma_list: csum operation not terminated.\n"));		failed = -EINVAL;		goto error_cleanup;	}	failed = append_input_descriptors(operation, &current_in_cdesc, &current_out_cdesc, &cipher_ctx, alloc_flag);	if (failed){		DEBUG_API(printk("cryptocop_setup_dma_list: append_input_descriptors cipher_ctx %d\n", failed));		goto error_cleanup;	}	failed = append_input_descriptors(operation, &current_in_cdesc, &current_out_cdesc, &digest_ctx, alloc_flag);	if (failed){		DEBUG_API(printk("cryptocop_setup_dma_list: append_input_descriptors cipher_ctx %d\n", failed));		goto error_cleanup;	}	failed = append_input_descriptors(operation, &current_in_cdesc, &current_out_cdesc, &csum_ctx, alloc_flag);	if (failed){		DEBUG_API(printk("cryptocop_setup_dma_list: append_input_descriptors cipher_ctx %d\n", failed));		goto error_cleanup;	}	DEBUG(printk("cryptocop_setup_dma_list: int_op=0x%p, *int_op=0x%p\n", int_op, *int_op));	(*int_op)->cdesc_out = out_cdesc_head.next;	(*int_op)->cdesc_in = in_cdesc_head.next;	DEBUG(printk("cryptocop_setup_dma_list: out_cdesc_head=0x%p in_cdesc_head=0x%p\n", (*int_op)->cdesc_out, (*int_op)->cdesc_in));	setup_descr_chain(out_cdesc_head.next);	setup_descr_chain(in_cdesc_head.next);	/* Last but not least: mark the last DMA in descriptor for a INTR and EOL and the the	 * last DMA out descriptor for EOL.	 */	current_in_cdesc->dma_descr->intr = 1;	current_in_cdesc->dma_descr->eol = 1;	current_out_cdesc->dma_descr->eol = 1;	/* Setup DMA contexts. */	(*int_op)->ctx_out.next = NULL;	(*int_op)->ctx_out.eol = 1;	(*int_op)->ctx_out.intr = 0;	(*int_op)->ctx_out.store_mode = 0;	(*int_op)->ctx_out.en = 0;	(*int_op)->ctx_out.dis = 0;	(*int_op)->ctx_out.md0 = 0;	(*int_op)->ctx_out.md1 = 0;	(*int_op)->ctx_out.md2 = 0;	(*int_op)->ctx_out.md3 = 0;	(*int_op)->ctx_out.md4 = 0;	(*int_op)->ctx_out.saved_data = (dma_descr_data*)virt_to_phys((*int_op)->cdesc_out->dma_descr);	(*int_op)->ctx_out.saved_data_buf = (*int_op)->cdesc_out->dma_descr->buf; /* Already physical address. */	(*int_op)->ctx_in.next = NULL;	(*int_op)->ctx_in.eol = 1;	(*int_op)->ctx_in.intr = 0;	(*int_op)->ctx_in.store_mode = 0;	(*int_op)->ctx_in.en = 0;	(*int_op)->ctx_in.dis = 0;	(*int_op)->ctx_in.md0 = 0;	(*int_op)->ctx_in.md1 = 0;	(*int_op)->ctx_in.md2 = 0;	(*int_op)->ctx_in.md3 = 0;	(*int_op)->ctx_in.md4 = 0;	(*int_op)->ctx_in.saved_data = (dma_descr_data*)virt_to_phys((*int_op)->cdesc_in->dma_descr);	(*int_op)->ctx_in.saved_data_buf = (*int_op)->cdesc_in->dma_descr->buf; /* Already physical address. */	DEBUG(printk("cryptocop_setup_dma_list: done\n"));	return 0;error_cleanup:	{		/* Free all allocated resources. */		struct cryptocop_dma_desc *tmp_cdesc;		while (digest_ctx.pad_descs){			tmp_cdesc = digest_ctx.pad_descs->next;			free_cdesc(digest_ctx.pad_descs);			digest_ctx.pad_descs = tmp_cdesc;		}		while (csum_ctx.pad_descs){			tmp_cdesc = csum_ctx.pad_descs->next;			free_cdesc(csum_ctx.pad_descs);			csum_ctx.pad_descs = tmp_cdesc;		}		assert(cipher_ctx.pad_descs == NULL); /* The ciphers are never padded. */		if (*int_op != NULL) delete_internal_operation(*int_op);	}	DEBUG_API(printk("cryptocop_setup_dma_list: done with error %d\n", failed));	return failed;}static void delete_internal_operation(struct cryptocop_int_operation *iop){	void                      *ptr = iop->alloc_ptr;	struct cryptocop_dma_desc *cd = iop->cdesc_out;	struct cryptocop_dma_desc *next;	DEBUG(printk("delete_internal_operation: iop=0x%p, alloc_ptr=0x%p\n", iop, ptr));	while (cd) {		next = cd->next;		free_cdesc(cd);		cd = next;	}	cd = iop->cdesc_in;	while (cd) {		next = cd->next;		free_cdesc(cd);		cd = next;	}	kfree(ptr);}#define MD5_MIN_PAD_LENGTH (9)#define MD5_PAD_LENGTH_FIELD_LENGTH (8)static int create_md5_pad(int alloc_flag, unsigned long long hashed_length, char **pad, size_t *pad_length){	size_t                  padlen = MD5_BLOCK_LENGTH - (hashed_length % MD5_BLOCK_LENGTH);	unsigned char           *p;	int                     i;	unsigned long long int  bit_length = hashed_length << 3;	if (padlen < MD5_MIN_PAD_LENGTH) padlen += MD5_BLOCK_LENGTH;	p = kmalloc(padlen, alloc_flag);	if (!pad) return -ENOMEM;	*p = 0x80;	memset(p+1, 0, padlen - 1);	DEBUG(printk("create_md5_pad: hashed_length=%lld bits == %lld bytes\n", bit_length, hashed_length));	i = padlen - MD5_PAD_LENGTH_FIELD_LENGTH;	while (bit_length != 0){		p[i++] = bit_length % 0x100;		bit_length >>= 8;	}	*pad = (char*)p;	*pad_length = padlen;	return 0;}#define SHA1_MIN_PAD_LENGTH (9)#define SHA1_PAD_LENGTH_FIELD_LENGTH (8)static int create_sha1_pad(int alloc_flag, unsigned long long hashed_length, char **pad, size_t *pad_length){	size_t                  padlen = SHA1_BLOCK_LENGTH - (hashed_length % SHA1_BLOCK_LENGTH);	unsigned char           *p;	int                     i;	unsigned long long int  bit_length = hashed_length << 3;	if (padlen < SHA1_MIN_PAD_LENGTH) padlen += SHA1_BLOCK_LENGTH;	p = kmalloc(padlen, alloc_flag);	if (!pad) return -ENOMEM;	*p = 0x80;	memset(p+1, 0, padlen - 1);	DEBUG(printk("create_sha1_pad: hashed_length=%lld bits == %lld bytes\n", bit_length, hashed_length));	i = padlen - 1;	while (bit_length != 0){		p[i--] = bit_length % 0x100;		bit_length >>= 8;	}	*pad = (char*)p;	*pad_length = padlen;	return 0;}static int transform_ok(struct cryptocop_transform_init *tinit){	switch (tinit->alg){	case cryptocop_alg_csum:		switch (tinit->csum_mode){		case cryptocop_csum_le:		case cryptocop_csum_be:			break;		default:			DEBUG_API(printk("transform_ok: Bad mode set for csum transform\n"));			return -EINVAL;		}	case cryptocop_alg_mem2mem:	case cryptocop_alg_md5:	case cryptocop_alg_sha1:		if (tinit->keylen != 0) {			DEBUG_API(printk("transform_ok: non-zero keylength, %d, for a digest/csum algorithm\n", tinit->keylen));			return -EINVAL; /* This check is a bit strict. */		}		break;	case cryptocop_alg_des:		if (tinit->keylen != 64) {			DEBUG_API(printk("transform_ok: keylen %d invalid for DES\n", tinit->keylen));			return -EINVAL;		}		break;	case cryptocop_alg_3des:		if (tinit->keylen != 192) {			DEBUG_API(printk("transform_ok: keylen %d invalid for 3DES\n", tinit->keylen));			return -EINVAL;		}		break;	case cryptocop_alg_aes:		if (tinit->keylen != 128 && tinit->keylen != 192 && tinit->keylen != 256) {			DEBUG_API(printk("transform_ok: keylen %d invalid for AES\n", tinit->keylen));			return -EINVAL;		}		break;	case cryptocop_no_alg:	default:		DEBUG_API(printk("transform_ok: no such algorithm %d\n", tinit->alg));		return -EINVAL;	}	switch (tinit->alg){	case cryptocop_alg_des:	case cryptocop_alg_3des:	case cryptocop_alg_aes:		if (tinit->cipher_mode != cryptocop_cipher_mode_ecb && tinit->cipher_mode != cryptocop_cipher_mode_cbc) return -EINVAL;	default:		 break;	}	return 0;}int cryptocop_new_session(cryptocop_session_id *sid, struct cryptocop_transform_init *tinit, int alloc_flag){	struct cryptocop_session         *sess;	struct cryptocop_transform_init  *tfrm_in = tinit;	struct cryptocop_transform_init  *tmp_in;	int                              no_tfrms = 0;	int                              i;	unsigned long int                flags;	init_stream_coprocessor(); /* For safety if we are called early */	while (tfrm_in){		int err;		++no_tfrms;		if ((err = transform_ok(tfrm_in))) {			DEBUG_API(printk("cryptocop_new_session, bad transform\n"));			return err;		}		tfrm_in = tfrm_in->next;	}	if (0 == no_tfrms) {		DEBUG_API(printk("cryptocop_new_session, no transforms specified\n"));		return -EINVAL;	}	sess = kmalloc(sizeof(struct cryptocop_session), alloc_flag);	if (!sess){		DEBUG_API(printk("cryptocop_new_session, kmalloc cryptocop_session\n"));		return -ENOMEM;	}	sess->tfrm_ctx = kmalloc(no_tfrms * sizeof(struct cryptocop_transform_ctx), alloc_flag);	if (!sess->tfrm_ctx) {		DEBUG_API(printk("cryptocop_new_session, kmalloc cryptocop_transform_ctx\n"));		kfree(sess);		return -ENOMEM;	}	tfrm_in = tinit;	for (i = 0; i < no_tfrms; i++){		tmp_in = tfrm_in->next;		while (tmp_in){			if (tmp_in->tid == tfrm_in->tid) {				DEBUG_API(printk("cryptocop_new_session, duplicate transform ids\n"));				kfree(sess->tfrm_ctx);				kfree(sess);				return -EINVAL;			}			tmp_in = tmp_in->next;		}		memcpy(&sess->tfrm_ctx[i].init, tfrm_in, sizeof(struct cryptocop_transform_init));		sess->tfrm_ctx[i].dec_key_set = 0;		sess->tfrm_ctx[i].next = &sess->tfrm_ctx[i] + 1;		tfrm_in = tfrm_in->next;	}	sess->tfrm_ctx[i-1].next = NULL;	spin_lock_irqsave(&cryptocop_sessions_lock, flags);	sess->sid = next_sid;	next_sid++;	/* TODO If we are really paranoid we should do duplicate check to handle sid wraparound.	 *      OTOH 2^64 is a really large number of session. */	if (next_sid == 0) next_sid = 1;	/* Prepend to session list. */	sess->next = cryptocop_sessions;	cryptocop_sessions = sess;	spin_unlock_irqrestore(&cryptocop_sessions_lock, flags);	*sid = sess->sid;	return 0;}int cryptocop_free_session(cryptocop_session_id sid){	struct cryptocop_transform_ctx    *tc;	struct cryptocop_session          *sess = NULL;	struct cryptocop_session          *psess = NULL;	unsigned long int                 flags;	int                               i;	LIST_HEAD(remove_list);	struct list_head                  *node, *tmp;	struct cryptocop_prio_job         *pj;	DEBUG(printk("cryptocop_free_session: sid=%lld\n", sid));	spin_lock_irqsave(&cryptocop_sessions_lock, flags);	sess = cryptocop_sessions;	while (sess && sess->sid != sid){		psess = sess;		sess = sess->next;	}	if (sess){		if (psess){			psess->next = sess->next;		} else {			cryptocop_sessions = sess->next;		}	}	spin_unlock_irqrestore(&cryptocop_sessions_lock, flags);	if (!sess) return -EINVAL;	/* Remove queued jobs. */	spin_lock_irqsave(&cryptocop_job_queue_lock, flags);	for (i = 0; i < cryptocop_prio_no_prios; i++){		if (!list_empty(&(cryptocop_job_queues[i].jobs))){			list_for_each_safe(node, tmp, &(cryptocop_job_queues[i].jobs)) {				pj = list_entry(node, struct cryptocop_prio_job, node);				if (pj->oper->sid == sid) {					list_move_tail(node, &remove_list);				}			}		}	}	spin_unlock_irqrestore(&cryptocop_job_queue_lock, flags);	list_for_each_safe(node, tmp, &remove_list) {		list_del(node);		pj = list_entry(node, struct cryptocop_prio_job, node);		pj->oper->operation_status = -EAGAIN;  /* EAGAIN is not ideal for job/session terminated but it's the best choice I know of. */		DEBUG(printk("cryptocop_free_session: pj=0x%p, pj->oper=0x%p, pj->iop=0x%p\n", pj, pj->oper, pj->iop));		pj->oper->cb(pj->oper, pj->oper->cb_data);		delete_internal_operation(pj->iop);		kfree(pj);	}	tc = sess->tfrm_ctx;	/* Erase keying data. */	while (tc){		DEBUG(printk("cryptocop_free_session: memset keys, tfrm id=%d\n", tc->init.tid));		memset(tc->init.key, 0xff, CRYPTOCOP_MAX_KEY_LENGTH);		memset(tc->dec_key, 0xff, CRYPTOCOP_MAX_KEY_LENGTH);		tc = tc->next;	}	kfree(sess->tfrm_ctx);	kfree(sess);	return 0;}static struct cryptocop_session *get_session(cryptocop_session_id sid){	struct cryptocop_session    *sess;	unsigned long int           flags;

⌨️ 快捷键说明

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