Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cris-mirror.git] / arch / cris / arch-v32 / drivers / cryptocop.c
blob2081d8b45f061b37e117f46f66bc03c5b481fe0f
1 /*
2 * Stream co-processor driver for the ETRAX FS
4 * Copyright (C) 2003-2007 Axis Communications AB
5 */
7 #include <linux/init.h>
8 #include <linux/sched.h>
9 #include <linux/module.h>
10 #include <linux/slab.h>
11 #include <linux/string.h>
12 #include <linux/fs.h>
13 #include <linux/mm.h>
14 #include <linux/spinlock.h>
15 #include <linux/stddef.h>
17 #include <asm/uaccess.h>
18 #include <asm/io.h>
19 #include <linux/atomic.h>
21 #include <linux/list.h>
22 #include <linux/interrupt.h>
24 #include <asm/signal.h>
25 #include <asm/irq.h>
27 #include <dma.h>
28 #include <hwregs/dma.h>
29 #include <hwregs/reg_map.h>
30 #include <hwregs/reg_rdwr.h>
31 #include <hwregs/intr_vect_defs.h>
33 #include <hwregs/strcop.h>
34 #include <hwregs/strcop_defs.h>
35 #include <cryptocop.h>
37 #ifdef CONFIG_ETRAXFS
38 #define IN_DMA 9
39 #define OUT_DMA 8
40 #define IN_DMA_INST regi_dma9
41 #define OUT_DMA_INST regi_dma8
42 #define DMA_IRQ DMA9_INTR_VECT
43 #else
44 #define IN_DMA 3
45 #define OUT_DMA 2
46 #define IN_DMA_INST regi_dma3
47 #define OUT_DMA_INST regi_dma2
48 #define DMA_IRQ DMA3_INTR_VECT
49 #endif
51 #define DESCR_ALLOC_PAD (31)
53 struct cryptocop_dma_desc {
54 char *free_buf; /* If non-null will be kfreed in free_cdesc() */
55 dma_descr_data *dma_descr;
57 unsigned char dma_descr_buf[sizeof(dma_descr_data) + DESCR_ALLOC_PAD];
59 unsigned int from_pool:1; /* If 1 'allocated' from the descriptor pool. */
60 struct cryptocop_dma_desc *next;
64 struct cryptocop_int_operation{
65 void *alloc_ptr;
66 cryptocop_session_id sid;
68 dma_descr_context ctx_out;
69 dma_descr_context ctx_in;
71 /* DMA descriptors allocated by driver. */
72 struct cryptocop_dma_desc *cdesc_out;
73 struct cryptocop_dma_desc *cdesc_in;
75 /* Strcop config to use. */
76 cryptocop_3des_mode tdes_mode;
77 cryptocop_csum_type csum_mode;
79 /* DMA descrs provided by consumer. */
80 dma_descr_data *ddesc_out;
81 dma_descr_data *ddesc_in;
85 struct cryptocop_tfrm_ctx {
86 cryptocop_tfrm_id tid;
87 unsigned int blocklength;
89 unsigned int start_ix;
91 struct cryptocop_tfrm_cfg *tcfg;
92 struct cryptocop_transform_ctx *tctx;
94 unsigned char previous_src;
95 unsigned char current_src;
97 /* Values to use in metadata out. */
98 unsigned char hash_conf;
99 unsigned char hash_mode;
100 unsigned char ciph_conf;
101 unsigned char cbcmode;
102 unsigned char decrypt;
104 unsigned int requires_padding:1;
105 unsigned int strict_block_length:1;
106 unsigned int active:1;
107 unsigned int done:1;
108 size_t consumed;
109 size_t produced;
111 /* Pad (input) descriptors to put in the DMA out list when the transform
112 * output is put on the DMA in list. */
113 struct cryptocop_dma_desc *pad_descs;
115 struct cryptocop_tfrm_ctx *prev_src;
116 struct cryptocop_tfrm_ctx *curr_src;
118 /* Mapping to HW. */
119 unsigned char unit_no;
123 struct cryptocop_private{
124 cryptocop_session_id sid;
125 struct cryptocop_private *next;
128 /* Session list. */
130 struct cryptocop_transform_ctx{
131 struct cryptocop_transform_init init;
132 unsigned char dec_key[CRYPTOCOP_MAX_KEY_LENGTH];
133 unsigned int dec_key_set:1;
135 struct cryptocop_transform_ctx *next;
139 struct cryptocop_session{
140 cryptocop_session_id sid;
142 struct cryptocop_transform_ctx *tfrm_ctx;
144 struct cryptocop_session *next;
147 /* Priority levels for jobs sent to the cryptocop. Checksum operations from
148 kernel have highest priority since TCPIP stack processing must not
149 be a bottleneck. */
150 typedef enum {
151 cryptocop_prio_kernel_csum = 0,
152 cryptocop_prio_kernel = 1,
153 cryptocop_prio_user = 2,
154 cryptocop_prio_no_prios = 3
155 } cryptocop_queue_priority;
157 struct cryptocop_prio_queue{
158 struct list_head jobs;
159 cryptocop_queue_priority prio;
162 struct cryptocop_prio_job{
163 struct list_head node;
164 cryptocop_queue_priority prio;
166 struct cryptocop_operation *oper;
167 struct cryptocop_int_operation *iop;
170 struct ioctl_job_cb_ctx {
171 unsigned int processed:1;
175 static struct cryptocop_session *cryptocop_sessions = NULL;
176 spinlock_t cryptocop_sessions_lock;
178 /* Next Session ID to assign. */
179 static cryptocop_session_id next_sid = 1;
181 /* Pad for checksum. */
182 static const char csum_zero_pad[1] = {0x00};
184 /* Trash buffer for mem2mem operations. */
185 #define MEM2MEM_DISCARD_BUF_LENGTH (512)
186 static unsigned char mem2mem_discard_buf[MEM2MEM_DISCARD_BUF_LENGTH];
188 /* Descriptor pool. */
189 /* FIXME Tweak this value. */
190 #define CRYPTOCOP_DESCRIPTOR_POOL_SIZE (100)
191 static struct cryptocop_dma_desc descr_pool[CRYPTOCOP_DESCRIPTOR_POOL_SIZE];
192 static struct cryptocop_dma_desc *descr_pool_free_list;
193 static int descr_pool_no_free;
194 static spinlock_t descr_pool_lock;
196 /* Lock to stop cryptocop to start processing of a new operation. The holder
197 of this lock MUST call cryptocop_start_job() after it is unlocked. */
198 spinlock_t cryptocop_process_lock;
200 static struct cryptocop_prio_queue cryptocop_job_queues[cryptocop_prio_no_prios];
201 static spinlock_t cryptocop_job_queue_lock;
202 static struct cryptocop_prio_job *cryptocop_running_job = NULL;
203 static spinlock_t running_job_lock;
205 /* The interrupt handler appends completed jobs to this list. The scehduled
206 * tasklet removes them upon sending the response to the crypto consumer. */
207 static struct list_head cryptocop_completed_jobs;
208 static spinlock_t cryptocop_completed_jobs_lock;
210 DECLARE_WAIT_QUEUE_HEAD(cryptocop_ioc_process_wq);
213 /** Local functions. **/
215 static int cryptocop_open(struct inode *, struct file *);
217 static int cryptocop_release(struct inode *, struct file *);
219 static long cryptocop_ioctl(struct file *file,
220 unsigned int cmd, unsigned long arg);
222 static void cryptocop_start_job(void);
224 static int cryptocop_job_queue_insert(cryptocop_queue_priority prio, struct cryptocop_operation *operation);
225 static int cryptocop_job_setup(struct cryptocop_prio_job **pj, struct cryptocop_operation *operation);
227 static int cryptocop_job_queue_init(void);
228 static void cryptocop_job_queue_close(void);
230 static int create_md5_pad(int alloc_flag, unsigned long long hashed_length, char **pad, size_t *pad_length);
232 static int create_sha1_pad(int alloc_flag, unsigned long long hashed_length, char **pad, size_t *pad_length);
234 static int transform_ok(struct cryptocop_transform_init *tinit);
236 static struct cryptocop_session *get_session(cryptocop_session_id sid);
238 static struct cryptocop_transform_ctx *get_transform_ctx(struct cryptocop_session *sess, cryptocop_tfrm_id tid);
240 static void delete_internal_operation(struct cryptocop_int_operation *iop);
242 static void get_aes_decrypt_key(unsigned char *dec_key, const unsigned char *key, unsigned int keylength);
244 static int init_stream_coprocessor(void);
246 static void __exit exit_stream_coprocessor(void);
248 /*#define LDEBUG*/
249 #ifdef LDEBUG
250 #define DEBUG(s) s
251 #define DEBUG_API(s) s
252 static void print_cryptocop_operation(struct cryptocop_operation *cop);
253 static void print_dma_descriptors(struct cryptocop_int_operation *iop);
254 static void print_strcop_crypto_op(struct strcop_crypto_op *cop);
255 static void print_lock_status(void);
256 static void print_user_dma_lists(struct cryptocop_dma_list_operation *dma_op);
257 #define assert(s) do{if (!(s)) panic(#s);} while(0);
258 #else
259 #define DEBUG(s)
260 #define DEBUG_API(s)
261 #define assert(s)
262 #endif
265 /* Transform constants. */
266 #define DES_BLOCK_LENGTH (8)
267 #define AES_BLOCK_LENGTH (16)
268 #define MD5_BLOCK_LENGTH (64)
269 #define SHA1_BLOCK_LENGTH (64)
270 #define CSUM_BLOCK_LENGTH (2)
271 #define MD5_STATE_LENGTH (16)
272 #define SHA1_STATE_LENGTH (20)
274 /* The device number. */
275 #define CRYPTOCOP_MAJOR (254)
276 #define CRYPTOCOP_MINOR (0)
280 const struct file_operations cryptocop_fops = {
281 .owner = THIS_MODULE,
282 .open = cryptocop_open,
283 .release = cryptocop_release,
284 .unlocked_ioctl = cryptocop_ioctl,
285 .llseek = noop_llseek,
289 static void free_cdesc(struct cryptocop_dma_desc *cdesc)
291 DEBUG(printk("free_cdesc: cdesc 0x%p, from_pool=%d\n", cdesc, cdesc->from_pool));
292 kfree(cdesc->free_buf);
294 if (cdesc->from_pool) {
295 unsigned long int flags;
296 spin_lock_irqsave(&descr_pool_lock, flags);
297 cdesc->next = descr_pool_free_list;
298 descr_pool_free_list = cdesc;
299 ++descr_pool_no_free;
300 spin_unlock_irqrestore(&descr_pool_lock, flags);
301 } else {
302 kfree(cdesc);
307 static struct cryptocop_dma_desc *alloc_cdesc(int alloc_flag)
309 int use_pool = (alloc_flag & GFP_ATOMIC) ? 1 : 0;
310 struct cryptocop_dma_desc *cdesc;
312 if (use_pool) {
313 unsigned long int flags;
314 spin_lock_irqsave(&descr_pool_lock, flags);
315 if (!descr_pool_free_list) {
316 spin_unlock_irqrestore(&descr_pool_lock, flags);
317 DEBUG_API(printk("alloc_cdesc: pool is empty\n"));
318 return NULL;
320 cdesc = descr_pool_free_list;
321 descr_pool_free_list = descr_pool_free_list->next;
322 --descr_pool_no_free;
323 spin_unlock_irqrestore(&descr_pool_lock, flags);
324 cdesc->from_pool = 1;
325 } else {
326 cdesc = kmalloc(sizeof(struct cryptocop_dma_desc), alloc_flag);
327 if (!cdesc) {
328 DEBUG_API(printk("alloc_cdesc: kmalloc\n"));
329 return NULL;
331 cdesc->from_pool = 0;
333 cdesc->dma_descr = (dma_descr_data*)(((unsigned long int)cdesc + offsetof(struct cryptocop_dma_desc, dma_descr_buf) + DESCR_ALLOC_PAD) & ~0x0000001F);
335 cdesc->next = NULL;
337 cdesc->free_buf = NULL;
338 cdesc->dma_descr->out_eop = 0;
339 cdesc->dma_descr->in_eop = 0;
340 cdesc->dma_descr->intr = 0;
341 cdesc->dma_descr->eol = 0;
342 cdesc->dma_descr->wait = 0;
343 cdesc->dma_descr->buf = NULL;
344 cdesc->dma_descr->after = NULL;
346 DEBUG_API(printk("alloc_cdesc: return 0x%p, cdesc->dma_descr=0x%p, from_pool=%d\n", cdesc, cdesc->dma_descr, cdesc->from_pool));
347 return cdesc;
351 static void setup_descr_chain(struct cryptocop_dma_desc *cd)
353 DEBUG(printk("setup_descr_chain: entering\n"));
354 while (cd) {
355 if (cd->next) {
356 cd->dma_descr->next = (dma_descr_data*)virt_to_phys(cd->next->dma_descr);
357 } else {
358 cd->dma_descr->next = NULL;
360 cd = cd->next;
362 DEBUG(printk("setup_descr_chain: exit\n"));
366 /* Create a pad descriptor for the transform.
367 * Return -1 for error, 0 if pad created. */
368 static int create_pad_descriptor(struct cryptocop_tfrm_ctx *tc, struct cryptocop_dma_desc **pad_desc, int alloc_flag)
370 struct cryptocop_dma_desc *cdesc = NULL;
371 int error = 0;
372 struct strcop_meta_out mo = {
373 .ciphsel = src_none,
374 .hashsel = src_none,
375 .csumsel = src_none
377 char *pad;
378 size_t plen;
380 DEBUG(printk("create_pad_descriptor: start.\n"));
381 /* Setup pad descriptor. */
383 DEBUG(printk("create_pad_descriptor: setting up padding.\n"));
384 cdesc = alloc_cdesc(alloc_flag);
385 if (!cdesc){
386 DEBUG_API(printk("create_pad_descriptor: alloc pad desc\n"));
387 goto error_cleanup;
389 switch (tc->unit_no) {
390 case src_md5:
391 error = create_md5_pad(alloc_flag, tc->consumed, &pad, &plen);
392 if (error){
393 DEBUG_API(printk("create_pad_descriptor: create_md5_pad_failed\n"));
394 goto error_cleanup;
396 cdesc->free_buf = pad;
397 mo.hashsel = src_dma;
398 mo.hashconf = tc->hash_conf;
399 mo.hashmode = tc->hash_mode;
400 break;
401 case src_sha1:
402 error = create_sha1_pad(alloc_flag, tc->consumed, &pad, &plen);
403 if (error){
404 DEBUG_API(printk("create_pad_descriptor: create_sha1_pad_failed\n"));
405 goto error_cleanup;
407 cdesc->free_buf = pad;
408 mo.hashsel = src_dma;
409 mo.hashconf = tc->hash_conf;
410 mo.hashmode = tc->hash_mode;
411 break;
412 case src_csum:
413 if (tc->consumed % tc->blocklength){
414 pad = (char*)csum_zero_pad;
415 plen = 1;
416 } else {
417 pad = (char*)cdesc; /* Use any pointer. */
418 plen = 0;
420 mo.csumsel = src_dma;
421 break;
423 cdesc->dma_descr->wait = 1;
424 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. */
425 cdesc->dma_descr->buf = (char*)virt_to_phys((char*)pad);
426 cdesc->dma_descr->after = cdesc->dma_descr->buf + plen;
428 cdesc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_out, mo);
429 *pad_desc = cdesc;
431 return 0;
433 error_cleanup:
434 if (cdesc) free_cdesc(cdesc);
435 return -1;
439 static int setup_key_dl_desc(struct cryptocop_tfrm_ctx *tc, struct cryptocop_dma_desc **kd, int alloc_flag)
441 struct cryptocop_dma_desc *key_desc = alloc_cdesc(alloc_flag);
442 struct strcop_meta_out mo = {0};
444 DEBUG(printk("setup_key_dl_desc\n"));
446 if (!key_desc) {
447 DEBUG_API(printk("setup_key_dl_desc: failed descriptor allocation.\n"));
448 return -ENOMEM;
451 /* Download key. */
452 if ((tc->tctx->init.alg == cryptocop_alg_aes) && (tc->tcfg->flags & CRYPTOCOP_DECRYPT)) {
453 /* Precook the AES decrypt key. */
454 if (!tc->tctx->dec_key_set){
455 get_aes_decrypt_key(tc->tctx->dec_key, tc->tctx->init.key, tc->tctx->init.keylen);
456 tc->tctx->dec_key_set = 1;
458 key_desc->dma_descr->buf = (char*)virt_to_phys(tc->tctx->dec_key);
459 key_desc->dma_descr->after = key_desc->dma_descr->buf + tc->tctx->init.keylen/8;
460 } else {
461 key_desc->dma_descr->buf = (char*)virt_to_phys(tc->tctx->init.key);
462 key_desc->dma_descr->after = key_desc->dma_descr->buf + tc->tctx->init.keylen/8;
464 /* Setup metadata. */
465 mo.dlkey = 1;
466 switch (tc->tctx->init.keylen) {
467 case 64:
468 mo.decrypt = 0;
469 mo.hashmode = 0;
470 break;
471 case 128:
472 mo.decrypt = 0;
473 mo.hashmode = 1;
474 break;
475 case 192:
476 mo.decrypt = 1;
477 mo.hashmode = 0;
478 break;
479 case 256:
480 mo.decrypt = 1;
481 mo.hashmode = 1;
482 break;
483 default:
484 break;
486 mo.ciphsel = mo.hashsel = mo.csumsel = src_none;
487 key_desc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_out, mo);
489 key_desc->dma_descr->out_eop = 1;
490 key_desc->dma_descr->wait = 1;
491 key_desc->dma_descr->intr = 0;
493 *kd = key_desc;
494 return 0;
497 static int setup_cipher_iv_desc(struct cryptocop_tfrm_ctx *tc, struct cryptocop_dma_desc **id, int alloc_flag)
499 struct cryptocop_dma_desc *iv_desc = alloc_cdesc(alloc_flag);
500 struct strcop_meta_out mo = {0};
502 DEBUG(printk("setup_cipher_iv_desc\n"));
504 if (!iv_desc) {
505 DEBUG_API(printk("setup_cipher_iv_desc: failed CBC IV descriptor allocation.\n"));
506 return -ENOMEM;
508 /* Download IV. */
509 iv_desc->dma_descr->buf = (char*)virt_to_phys(tc->tcfg->iv);
510 iv_desc->dma_descr->after = iv_desc->dma_descr->buf + tc->blocklength;
512 /* Setup metadata. */
513 mo.hashsel = mo.csumsel = src_none;
514 mo.ciphsel = src_dma;
515 mo.ciphconf = tc->ciph_conf;
516 mo.cbcmode = tc->cbcmode;
518 iv_desc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_out, mo);
520 iv_desc->dma_descr->out_eop = 0;
521 iv_desc->dma_descr->wait = 1;
522 iv_desc->dma_descr->intr = 0;
524 *id = iv_desc;
525 return 0;
528 /* Map the output length of the transform to operation output starting on the inject index. */
529 static int create_input_descriptors(struct cryptocop_operation *operation, struct cryptocop_tfrm_ctx *tc, struct cryptocop_dma_desc **id, int alloc_flag)
531 int err = 0;
532 struct cryptocop_dma_desc head = {0};
533 struct cryptocop_dma_desc *outdesc = &head;
534 size_t iov_offset = 0;
535 size_t out_ix = 0;
536 int outiov_ix = 0;
537 struct strcop_meta_in mi = {0};
539 size_t out_length = tc->produced;
540 int rem_length;
541 int dlength;
543 assert(out_length != 0);
544 if (((tc->produced + tc->tcfg->inject_ix) > operation->tfrm_op.outlen) || (tc->produced && (operation->tfrm_op.outlen == 0))) {
545 DEBUG_API(printk("create_input_descriptors: operation outdata too small\n"));
546 return -EINVAL;
548 /* Traverse the out iovec until the result inject index is reached. */
549 while ((outiov_ix < operation->tfrm_op.outcount) && ((out_ix + operation->tfrm_op.outdata[outiov_ix].iov_len) <= tc->tcfg->inject_ix)){
550 out_ix += operation->tfrm_op.outdata[outiov_ix].iov_len;
551 outiov_ix++;
553 if (outiov_ix >= operation->tfrm_op.outcount){
554 DEBUG_API(printk("create_input_descriptors: operation outdata too small\n"));
555 return -EINVAL;
557 iov_offset = tc->tcfg->inject_ix - out_ix;
558 mi.dmasel = tc->unit_no;
560 /* Setup the output descriptors. */
561 while ((out_length > 0) && (outiov_ix < operation->tfrm_op.outcount)) {
562 outdesc->next = alloc_cdesc(alloc_flag);
563 if (!outdesc->next) {
564 DEBUG_API(printk("create_input_descriptors: alloc_cdesc\n"));
565 err = -ENOMEM;
566 goto error_cleanup;
568 outdesc = outdesc->next;
569 rem_length = operation->tfrm_op.outdata[outiov_ix].iov_len - iov_offset;
570 dlength = (out_length < rem_length) ? out_length : rem_length;
572 DEBUG(printk("create_input_descriptors:\n"
573 "outiov_ix=%d, rem_length=%d, dlength=%d\n"
574 "iov_offset=%d, outdata[outiov_ix].iov_len=%d\n"
575 "outcount=%d, outiov_ix=%d\n",
576 outiov_ix, rem_length, dlength, iov_offset, operation->tfrm_op.outdata[outiov_ix].iov_len, operation->tfrm_op.outcount, outiov_ix));
578 outdesc->dma_descr->buf = (char*)virt_to_phys(operation->tfrm_op.outdata[outiov_ix].iov_base + iov_offset);
579 outdesc->dma_descr->after = outdesc->dma_descr->buf + dlength;
580 outdesc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_in, mi);
582 out_length -= dlength;
583 iov_offset += dlength;
584 if (iov_offset >= operation->tfrm_op.outdata[outiov_ix].iov_len) {
585 iov_offset = 0;
586 ++outiov_ix;
589 if (out_length > 0){
590 DEBUG_API(printk("create_input_descriptors: not enough room for output, %d remained\n", out_length));
591 err = -EINVAL;
592 goto error_cleanup;
594 /* Set sync in last descriptor. */
595 mi.sync = 1;
596 outdesc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_in, mi);
598 *id = head.next;
599 return 0;
601 error_cleanup:
602 while (head.next) {
603 outdesc = head.next->next;
604 free_cdesc(head.next);
605 head.next = outdesc;
607 return err;
611 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)
613 while (desc_len != 0) {
614 struct cryptocop_dma_desc *cdesc;
615 int rem_length = operation->tfrm_op.indata[*iniov_ix].iov_len - *iniov_offset;
616 int dlength = (desc_len < rem_length) ? desc_len : rem_length;
618 cdesc = alloc_cdesc(alloc_flag);
619 if (!cdesc) {
620 DEBUG_API(printk("create_output_descriptors: alloc_cdesc\n"));
621 return -ENOMEM;
623 (*current_out_cdesc)->next = cdesc;
624 (*current_out_cdesc) = cdesc;
626 cdesc->free_buf = NULL;
628 cdesc->dma_descr->buf = (char*)virt_to_phys(operation->tfrm_op.indata[*iniov_ix].iov_base + *iniov_offset);
629 cdesc->dma_descr->after = cdesc->dma_descr->buf + dlength;
631 assert(desc_len >= dlength);
632 desc_len -= dlength;
633 *iniov_offset += dlength;
634 if (*iniov_offset >= operation->tfrm_op.indata[*iniov_ix].iov_len) {
635 *iniov_offset = 0;
636 ++(*iniov_ix);
637 if (*iniov_ix > operation->tfrm_op.incount) {
638 DEBUG_API(printk("create_output_descriptors: not enough indata in operation."));
639 return -EINVAL;
642 cdesc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_out, (*meta_out));
643 } /* while (desc_len != 0) */
644 /* Last DMA descriptor gets a 'wait' bit to signal expected change in metadata. */
645 (*current_out_cdesc)->dma_descr->wait = 1; /* This will set extraneous WAIT in some situations, e.g. when padding hashes and checksums. */
647 return 0;
651 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)
653 DEBUG(printk("append_input_descriptors, tc=0x%p, unit_no=%d\n", tc, tc->unit_no));
654 if (tc->tcfg) {
655 int failed = 0;
656 struct cryptocop_dma_desc *idescs = NULL;
657 DEBUG(printk("append_input_descriptors: pushing output, consumed %d produced %d bytes.\n", tc->consumed, tc->produced));
658 if (tc->pad_descs) {
659 DEBUG(printk("append_input_descriptors: append pad descriptors to DMA out list.\n"));
660 while (tc->pad_descs) {
661 DEBUG(printk("append descriptor 0x%p\n", tc->pad_descs));
662 (*current_out_cdesc)->next = tc->pad_descs;
663 tc->pad_descs = tc->pad_descs->next;
664 (*current_out_cdesc) = (*current_out_cdesc)->next;
668 /* Setup and append output descriptors to DMA in list. */
669 if (tc->unit_no == src_dma){
670 /* mem2mem. Setup DMA in descriptors to discard all input prior to the requested mem2mem data. */
671 struct strcop_meta_in mi = {.sync = 0, .dmasel = src_dma};
672 unsigned int start_ix = tc->start_ix;
673 while (start_ix){
674 unsigned int desclen = start_ix < MEM2MEM_DISCARD_BUF_LENGTH ? start_ix : MEM2MEM_DISCARD_BUF_LENGTH;
675 (*current_in_cdesc)->next = alloc_cdesc(alloc_flag);
676 if (!(*current_in_cdesc)->next){
677 DEBUG_API(printk("append_input_descriptors: alloc_cdesc mem2mem discard failed\n"));
678 return -ENOMEM;
680 (*current_in_cdesc) = (*current_in_cdesc)->next;
681 (*current_in_cdesc)->dma_descr->buf = (char*)virt_to_phys(mem2mem_discard_buf);
682 (*current_in_cdesc)->dma_descr->after = (*current_in_cdesc)->dma_descr->buf + desclen;
683 (*current_in_cdesc)->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_in, mi);
684 start_ix -= desclen;
686 mi.sync = 1;
687 (*current_in_cdesc)->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_in, mi);
690 failed = create_input_descriptors(operation, tc, &idescs, alloc_flag);
691 if (failed){
692 DEBUG_API(printk("append_input_descriptors: output descriptor setup failed\n"));
693 return failed;
695 DEBUG(printk("append_input_descriptors: append output descriptors to DMA in list.\n"));
696 while (idescs) {
697 DEBUG(printk("append descriptor 0x%p\n", idescs));
698 (*current_in_cdesc)->next = idescs;
699 idescs = idescs->next;
700 (*current_in_cdesc) = (*current_in_cdesc)->next;
703 return 0;
708 static int cryptocop_setup_dma_list(struct cryptocop_operation *operation, struct cryptocop_int_operation **int_op, int alloc_flag)
710 struct cryptocop_session *sess;
711 struct cryptocop_transform_ctx *tctx;
713 struct cryptocop_tfrm_ctx digest_ctx = {
714 .previous_src = src_none,
715 .current_src = src_none,
716 .start_ix = 0,
717 .requires_padding = 1,
718 .strict_block_length = 0,
719 .hash_conf = 0,
720 .hash_mode = 0,
721 .ciph_conf = 0,
722 .cbcmode = 0,
723 .decrypt = 0,
724 .consumed = 0,
725 .produced = 0,
726 .pad_descs = NULL,
727 .active = 0,
728 .done = 0,
729 .prev_src = NULL,
730 .curr_src = NULL,
731 .tcfg = NULL};
732 struct cryptocop_tfrm_ctx cipher_ctx = {
733 .previous_src = src_none,
734 .current_src = src_none,
735 .start_ix = 0,
736 .requires_padding = 0,
737 .strict_block_length = 1,
738 .hash_conf = 0,
739 .hash_mode = 0,
740 .ciph_conf = 0,
741 .cbcmode = 0,
742 .decrypt = 0,
743 .consumed = 0,
744 .produced = 0,
745 .pad_descs = NULL,
746 .active = 0,
747 .done = 0,
748 .prev_src = NULL,
749 .curr_src = NULL,
750 .tcfg = NULL};
751 struct cryptocop_tfrm_ctx csum_ctx = {
752 .previous_src = src_none,
753 .current_src = src_none,
754 .start_ix = 0,
755 .blocklength = 2,
756 .requires_padding = 1,
757 .strict_block_length = 0,
758 .hash_conf = 0,
759 .hash_mode = 0,
760 .ciph_conf = 0,
761 .cbcmode = 0,
762 .decrypt = 0,
763 .consumed = 0,
764 .produced = 0,
765 .pad_descs = NULL,
766 .active = 0,
767 .done = 0,
768 .tcfg = NULL,
769 .prev_src = NULL,
770 .curr_src = NULL,
771 .unit_no = src_csum};
772 struct cryptocop_tfrm_cfg *tcfg = operation->tfrm_op.tfrm_cfg;
774 unsigned int indata_ix = 0;
776 /* iovec accounting. */
777 int iniov_ix = 0;
778 int iniov_offset = 0;
780 /* Operation descriptor cfg traversal pointer. */
781 struct cryptocop_desc *odsc;
783 int failed = 0;
784 /* List heads for allocated descriptors. */
785 struct cryptocop_dma_desc out_cdesc_head = {0};
786 struct cryptocop_dma_desc in_cdesc_head = {0};
788 struct cryptocop_dma_desc *current_out_cdesc = &out_cdesc_head;
789 struct cryptocop_dma_desc *current_in_cdesc = &in_cdesc_head;
791 struct cryptocop_tfrm_ctx *output_tc = NULL;
792 void *iop_alloc_ptr;
794 assert(operation != NULL);
795 assert(int_op != NULL);
797 DEBUG(printk("cryptocop_setup_dma_list: start\n"));
798 DEBUG(print_cryptocop_operation(operation));
800 sess = get_session(operation->sid);
801 if (!sess) {
802 DEBUG_API(printk("cryptocop_setup_dma_list: no session found for operation.\n"));
803 failed = -EINVAL;
804 goto error_cleanup;
806 iop_alloc_ptr = kmalloc(DESCR_ALLOC_PAD + sizeof(struct cryptocop_int_operation), alloc_flag);
807 if (!iop_alloc_ptr) {
808 DEBUG_API(printk("cryptocop_setup_dma_list: kmalloc cryptocop_int_operation\n"));
809 failed = -ENOMEM;
810 goto error_cleanup;
812 (*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));
813 DEBUG(memset((*int_op), 0xff, sizeof(struct cryptocop_int_operation)));
814 (*int_op)->alloc_ptr = iop_alloc_ptr;
815 DEBUG(printk("cryptocop_setup_dma_list: *int_op=0x%p, alloc_ptr=0x%p\n", *int_op, (*int_op)->alloc_ptr));
817 (*int_op)->sid = operation->sid;
818 (*int_op)->cdesc_out = NULL;
819 (*int_op)->cdesc_in = NULL;
820 (*int_op)->tdes_mode = cryptocop_3des_ede;
821 (*int_op)->csum_mode = cryptocop_csum_le;
822 (*int_op)->ddesc_out = NULL;
823 (*int_op)->ddesc_in = NULL;
825 /* Scan operation->tfrm_op.tfrm_cfg for bad configuration and set up the local contexts. */
826 if (!tcfg) {
827 DEBUG_API(printk("cryptocop_setup_dma_list: no configured transforms in operation.\n"));
828 failed = -EINVAL;
829 goto error_cleanup;
831 while (tcfg) {
832 tctx = get_transform_ctx(sess, tcfg->tid);
833 if (!tctx) {
834 DEBUG_API(printk("cryptocop_setup_dma_list: no transform id %d in session.\n", tcfg->tid));
835 failed = -EINVAL;
836 goto error_cleanup;
838 if (tcfg->inject_ix > operation->tfrm_op.outlen){
839 DEBUG_API(printk("cryptocop_setup_dma_list: transform id %d inject_ix (%d) > operation->tfrm_op.outlen(%d)", tcfg->tid, tcfg->inject_ix, operation->tfrm_op.outlen));
840 failed = -EINVAL;
841 goto error_cleanup;
843 switch (tctx->init.alg){
844 case cryptocop_alg_mem2mem:
845 if (cipher_ctx.tcfg != NULL){
846 DEBUG_API(printk("cryptocop_setup_dma_list: multiple ciphers in operation.\n"));
847 failed = -EINVAL;
848 goto error_cleanup;
850 /* mem2mem is handled as a NULL cipher. */
851 cipher_ctx.cbcmode = 0;
852 cipher_ctx.decrypt = 0;
853 cipher_ctx.blocklength = 1;
854 cipher_ctx.ciph_conf = 0;
855 cipher_ctx.unit_no = src_dma;
856 cipher_ctx.tcfg = tcfg;
857 cipher_ctx.tctx = tctx;
858 break;
859 case cryptocop_alg_des:
860 case cryptocop_alg_3des:
861 case cryptocop_alg_aes:
862 /* cipher */
863 if (cipher_ctx.tcfg != NULL){
864 DEBUG_API(printk("cryptocop_setup_dma_list: multiple ciphers in operation.\n"));
865 failed = -EINVAL;
866 goto error_cleanup;
868 cipher_ctx.tcfg = tcfg;
869 cipher_ctx.tctx = tctx;
870 if (cipher_ctx.tcfg->flags & CRYPTOCOP_DECRYPT){
871 cipher_ctx.decrypt = 1;
873 switch (tctx->init.cipher_mode) {
874 case cryptocop_cipher_mode_ecb:
875 cipher_ctx.cbcmode = 0;
876 break;
877 case cryptocop_cipher_mode_cbc:
878 cipher_ctx.cbcmode = 1;
879 break;
880 default:
881 DEBUG_API(printk("cryptocop_setup_dma_list: cipher_ctx, bad cipher mode==%d\n", tctx->init.cipher_mode));
882 failed = -EINVAL;
883 goto error_cleanup;
885 DEBUG(printk("cryptocop_setup_dma_list: cipher_ctx, set CBC mode==%d\n", cipher_ctx.cbcmode));
886 switch (tctx->init.alg){
887 case cryptocop_alg_des:
888 cipher_ctx.ciph_conf = 0;
889 cipher_ctx.unit_no = src_des;
890 cipher_ctx.blocklength = DES_BLOCK_LENGTH;
891 break;
892 case cryptocop_alg_3des:
893 cipher_ctx.ciph_conf = 1;
894 cipher_ctx.unit_no = src_des;
895 cipher_ctx.blocklength = DES_BLOCK_LENGTH;
896 break;
897 case cryptocop_alg_aes:
898 cipher_ctx.ciph_conf = 2;
899 cipher_ctx.unit_no = src_aes;
900 cipher_ctx.blocklength = AES_BLOCK_LENGTH;
901 break;
902 default:
903 panic("cryptocop_setup_dma_list: impossible algorithm %d\n", tctx->init.alg);
905 (*int_op)->tdes_mode = tctx->init.tdes_mode;
906 break;
907 case cryptocop_alg_md5:
908 case cryptocop_alg_sha1:
909 /* digest */
910 if (digest_ctx.tcfg != NULL){
911 DEBUG_API(printk("cryptocop_setup_dma_list: multiple digests in operation.\n"));
912 failed = -EINVAL;
913 goto error_cleanup;
915 digest_ctx.tcfg = tcfg;
916 digest_ctx.tctx = tctx;
917 digest_ctx.hash_mode = 0; /* Don't use explicit IV in this API. */
918 switch (tctx->init.alg){
919 case cryptocop_alg_md5:
920 digest_ctx.blocklength = MD5_BLOCK_LENGTH;
921 digest_ctx.unit_no = src_md5;
922 digest_ctx.hash_conf = 1; /* 1 => MD-5 */
923 break;
924 case cryptocop_alg_sha1:
925 digest_ctx.blocklength = SHA1_BLOCK_LENGTH;
926 digest_ctx.unit_no = src_sha1;
927 digest_ctx.hash_conf = 0; /* 0 => SHA-1 */
928 break;
929 default:
930 panic("cryptocop_setup_dma_list: impossible digest algorithm\n");
932 break;
933 case cryptocop_alg_csum:
934 /* digest */
935 if (csum_ctx.tcfg != NULL){
936 DEBUG_API(printk("cryptocop_setup_dma_list: multiple checksums in operation.\n"));
937 failed = -EINVAL;
938 goto error_cleanup;
940 (*int_op)->csum_mode = tctx->init.csum_mode;
941 csum_ctx.tcfg = tcfg;
942 csum_ctx.tctx = tctx;
943 break;
944 default:
945 /* no algorithm. */
946 DEBUG_API(printk("cryptocop_setup_dma_list: invalid algorithm %d specified in tfrm %d.\n", tctx->init.alg, tcfg->tid));
947 failed = -EINVAL;
948 goto error_cleanup;
950 tcfg = tcfg->next;
952 /* Download key if a cipher is used. */
953 if (cipher_ctx.tcfg && (cipher_ctx.tctx->init.alg != cryptocop_alg_mem2mem)){
954 struct cryptocop_dma_desc *key_desc = NULL;
956 failed = setup_key_dl_desc(&cipher_ctx, &key_desc, alloc_flag);
957 if (failed) {
958 DEBUG_API(printk("cryptocop_setup_dma_list: setup key dl\n"));
959 goto error_cleanup;
961 current_out_cdesc->next = key_desc;
962 current_out_cdesc = key_desc;
963 indata_ix += (unsigned int)(key_desc->dma_descr->after - key_desc->dma_descr->buf);
965 /* Download explicit IV if a cipher is used and CBC mode and explicit IV selected. */
966 if ((cipher_ctx.tctx->init.cipher_mode == cryptocop_cipher_mode_cbc) && (cipher_ctx.tcfg->flags & CRYPTOCOP_EXPLICIT_IV)) {
967 struct cryptocop_dma_desc *iv_desc = NULL;
969 DEBUG(printk("cryptocop_setup_dma_list: setup cipher CBC IV descriptor.\n"));
971 failed = setup_cipher_iv_desc(&cipher_ctx, &iv_desc, alloc_flag);
972 if (failed) {
973 DEBUG_API(printk("cryptocop_setup_dma_list: CBC IV descriptor.\n"));
974 goto error_cleanup;
976 current_out_cdesc->next = iv_desc;
977 current_out_cdesc = iv_desc;
978 indata_ix += (unsigned int)(iv_desc->dma_descr->after - iv_desc->dma_descr->buf);
982 /* Process descriptors. */
983 odsc = operation->tfrm_op.desc;
984 while (odsc) {
985 struct cryptocop_desc_cfg *dcfg = odsc->cfg;
986 struct strcop_meta_out meta_out = {0};
987 size_t desc_len = odsc->length;
988 int active_count, eop_needed_count;
990 output_tc = NULL;
992 DEBUG(printk("cryptocop_setup_dma_list: parsing an operation descriptor\n"));
994 while (dcfg) {
995 struct cryptocop_tfrm_ctx *tc = NULL;
997 DEBUG(printk("cryptocop_setup_dma_list: parsing an operation descriptor configuration.\n"));
998 /* Get the local context for the transform and mark it as the output unit if it produces output. */
999 if (digest_ctx.tcfg && (digest_ctx.tcfg->tid == dcfg->tid)){
1000 tc = &digest_ctx;
1001 } else if (cipher_ctx.tcfg && (cipher_ctx.tcfg->tid == dcfg->tid)){
1002 tc = &cipher_ctx;
1003 } else if (csum_ctx.tcfg && (csum_ctx.tcfg->tid == dcfg->tid)){
1004 tc = &csum_ctx;
1006 if (!tc) {
1007 DEBUG_API(printk("cryptocop_setup_dma_list: invalid transform %d specified in descriptor.\n", dcfg->tid));
1008 failed = -EINVAL;
1009 goto error_cleanup;
1011 if (tc->done) {
1012 DEBUG_API(printk("cryptocop_setup_dma_list: completed transform %d reused.\n", dcfg->tid));
1013 failed = -EINVAL;
1014 goto error_cleanup;
1016 if (!tc->active) {
1017 tc->start_ix = indata_ix;
1018 tc->active = 1;
1021 tc->previous_src = tc->current_src;
1022 tc->prev_src = tc->curr_src;
1023 /* Map source unit id to DMA source config. */
1024 switch (dcfg->src){
1025 case cryptocop_source_dma:
1026 tc->current_src = src_dma;
1027 break;
1028 case cryptocop_source_des:
1029 tc->current_src = src_des;
1030 break;
1031 case cryptocop_source_3des:
1032 tc->current_src = src_des;
1033 break;
1034 case cryptocop_source_aes:
1035 tc->current_src = src_aes;
1036 break;
1037 case cryptocop_source_md5:
1038 case cryptocop_source_sha1:
1039 case cryptocop_source_csum:
1040 case cryptocop_source_none:
1041 default:
1042 /* We do not allow using accumulating style units (SHA-1, MD5, checksum) as sources to other units.
1044 DEBUG_API(printk("cryptocop_setup_dma_list: bad unit source configured %d.\n", dcfg->src));
1045 failed = -EINVAL;
1046 goto error_cleanup;
1048 if (tc->current_src != src_dma) {
1049 /* Find the unit we are sourcing from. */
1050 if (digest_ctx.unit_no == tc->current_src){
1051 tc->curr_src = &digest_ctx;
1052 } else if (cipher_ctx.unit_no == tc->current_src){
1053 tc->curr_src = &cipher_ctx;
1054 } else if (csum_ctx.unit_no == tc->current_src){
1055 tc->curr_src = &csum_ctx;
1057 if ((tc->curr_src == tc) && (tc->unit_no != src_dma)){
1058 DEBUG_API(printk("cryptocop_setup_dma_list: unit %d configured to source from itself.\n", tc->unit_no));
1059 failed = -EINVAL;
1060 goto error_cleanup;
1062 } else {
1063 tc->curr_src = NULL;
1066 /* Detect source switch. */
1067 DEBUG(printk("cryptocop_setup_dma_list: tc->active=%d tc->unit_no=%d tc->current_src=%d tc->previous_src=%d, tc->curr_src=0x%p, tc->prev_srv=0x%p\n", tc->active, tc->unit_no, tc->current_src, tc->previous_src, tc->curr_src, tc->prev_src));
1068 if (tc->active && (tc->current_src != tc->previous_src)) {
1069 /* Only allow source switch when both the old source unit and the new one have
1070 * no pending data to process (i.e. the consumed length must be a multiple of the
1071 * transform blocklength). */
1072 /* Note: if the src == NULL we are actually sourcing from DMA out. */
1073 if (((tc->prev_src != NULL) && (tc->prev_src->consumed % tc->prev_src->blocklength)) ||
1074 ((tc->curr_src != NULL) && (tc->curr_src->consumed % tc->curr_src->blocklength)))
1076 DEBUG_API(printk("cryptocop_setup_dma_list: can only disconnect from or connect to a unit on a multiple of the blocklength, old: cons=%d, prod=%d, block=%d, new: cons=%d prod=%d, block=%d.\n", tc->prev_src ? tc->prev_src->consumed : INT_MIN, tc->prev_src ? tc->prev_src->produced : INT_MIN, tc->prev_src ? tc->prev_src->blocklength : INT_MIN, tc->curr_src ? tc->curr_src->consumed : INT_MIN, tc->curr_src ? tc->curr_src->produced : INT_MIN, tc->curr_src ? tc->curr_src->blocklength : INT_MIN));
1077 failed = -EINVAL;
1078 goto error_cleanup;
1081 /* Detect unit deactivation. */
1082 if (dcfg->last) {
1083 /* Length check of this is handled below. */
1084 tc->done = 1;
1086 dcfg = dcfg->next;
1087 } /* while (dcfg) */
1088 DEBUG(printk("cryptocop_setup_dma_list: parsing operation descriptor configuration complete.\n"));
1090 if (cipher_ctx.active && (cipher_ctx.curr_src != NULL) && !cipher_ctx.curr_src->active){
1091 DEBUG_API(printk("cryptocop_setup_dma_list: cipher source from inactive unit %d\n", cipher_ctx.curr_src->unit_no));
1092 failed = -EINVAL;
1093 goto error_cleanup;
1095 if (digest_ctx.active && (digest_ctx.curr_src != NULL) && !digest_ctx.curr_src->active){
1096 DEBUG_API(printk("cryptocop_setup_dma_list: digest source from inactive unit %d\n", digest_ctx.curr_src->unit_no));
1097 failed = -EINVAL;
1098 goto error_cleanup;
1100 if (csum_ctx.active && (csum_ctx.curr_src != NULL) && !csum_ctx.curr_src->active){
1101 DEBUG_API(printk("cryptocop_setup_dma_list: cipher source from inactive unit %d\n", csum_ctx.curr_src->unit_no));
1102 failed = -EINVAL;
1103 goto error_cleanup;
1106 /* Update consumed and produced lengths.
1108 The consumed length accounting here is actually cheating. If a unit source from DMA (or any
1109 other unit that process data in blocks of one octet) it is correct, but if it source from a
1110 block processing unit, i.e. a cipher, it will be temporarily incorrect at some times. However
1111 since it is only allowed--by the HW--to change source to or from a block processing unit at times where that
1112 unit has processed an exact multiple of its block length the end result will be correct.
1113 Beware that if the source change restriction change this code will need to be (much) reworked.
1115 DEBUG(printk("cryptocop_setup_dma_list: desc->length=%d, desc_len=%d.\n", odsc->length, desc_len));
1117 if (csum_ctx.active) {
1118 csum_ctx.consumed += desc_len;
1119 if (csum_ctx.done) {
1120 csum_ctx.produced = 2;
1122 DEBUG(printk("cryptocop_setup_dma_list: csum_ctx producing: consumed=%d, produced=%d, blocklength=%d.\n", csum_ctx.consumed, csum_ctx.produced, csum_ctx.blocklength));
1124 if (digest_ctx.active) {
1125 digest_ctx.consumed += desc_len;
1126 if (digest_ctx.done) {
1127 if (digest_ctx.unit_no == src_md5) {
1128 digest_ctx.produced = MD5_STATE_LENGTH;
1129 } else {
1130 digest_ctx.produced = SHA1_STATE_LENGTH;
1133 DEBUG(printk("cryptocop_setup_dma_list: digest_ctx producing: consumed=%d, produced=%d, blocklength=%d.\n", digest_ctx.consumed, digest_ctx.produced, digest_ctx.blocklength));
1135 if (cipher_ctx.active) {
1136 /* Ciphers are allowed only to source from DMA out. That is filtered above. */
1137 assert(cipher_ctx.current_src == src_dma);
1138 cipher_ctx.consumed += desc_len;
1139 cipher_ctx.produced = cipher_ctx.blocklength * (cipher_ctx.consumed / cipher_ctx.blocklength);
1140 if (cipher_ctx.cbcmode && !(cipher_ctx.tcfg->flags & CRYPTOCOP_EXPLICIT_IV) && cipher_ctx.produced){
1141 cipher_ctx.produced -= cipher_ctx.blocklength; /* Compensate for CBC iv. */
1143 DEBUG(printk("cryptocop_setup_dma_list: cipher_ctx producing: consumed=%d, produced=%d, blocklength=%d.\n", cipher_ctx.consumed, cipher_ctx.produced, cipher_ctx.blocklength));
1146 /* Setup the DMA out descriptors. */
1147 /* Configure the metadata. */
1148 active_count = 0;
1149 eop_needed_count = 0;
1150 if (cipher_ctx.active) {
1151 ++active_count;
1152 if (cipher_ctx.unit_no == src_dma){
1153 /* mem2mem */
1154 meta_out.ciphsel = src_none;
1155 } else {
1156 meta_out.ciphsel = cipher_ctx.current_src;
1158 meta_out.ciphconf = cipher_ctx.ciph_conf;
1159 meta_out.cbcmode = cipher_ctx.cbcmode;
1160 meta_out.decrypt = cipher_ctx.decrypt;
1161 DEBUG(printk("set ciphsel=%d ciphconf=%d cbcmode=%d decrypt=%d\n", meta_out.ciphsel, meta_out.ciphconf, meta_out.cbcmode, meta_out.decrypt));
1162 if (cipher_ctx.done) ++eop_needed_count;
1163 } else {
1164 meta_out.ciphsel = src_none;
1167 if (digest_ctx.active) {
1168 ++active_count;
1169 meta_out.hashsel = digest_ctx.current_src;
1170 meta_out.hashconf = digest_ctx.hash_conf;
1171 meta_out.hashmode = 0; /* Explicit mode is not used here. */
1172 DEBUG(printk("set hashsel=%d hashconf=%d hashmode=%d\n", meta_out.hashsel, meta_out.hashconf, meta_out.hashmode));
1173 if (digest_ctx.done) {
1174 assert(digest_ctx.pad_descs == NULL);
1175 failed = create_pad_descriptor(&digest_ctx, &digest_ctx.pad_descs, alloc_flag);
1176 if (failed) {
1177 DEBUG_API(printk("cryptocop_setup_dma_list: failed digest pad creation.\n"));
1178 goto error_cleanup;
1181 } else {
1182 meta_out.hashsel = src_none;
1185 if (csum_ctx.active) {
1186 ++active_count;
1187 meta_out.csumsel = csum_ctx.current_src;
1188 if (csum_ctx.done) {
1189 assert(csum_ctx.pad_descs == NULL);
1190 failed = create_pad_descriptor(&csum_ctx, &csum_ctx.pad_descs, alloc_flag);
1191 if (failed) {
1192 DEBUG_API(printk("cryptocop_setup_dma_list: failed csum pad creation.\n"));
1193 goto error_cleanup;
1196 } else {
1197 meta_out.csumsel = src_none;
1199 DEBUG(printk("cryptocop_setup_dma_list: %d eop needed, %d active units\n", eop_needed_count, active_count));
1200 /* Setup DMA out descriptors for the indata. */
1201 failed = create_output_descriptors(operation, &iniov_ix, &iniov_offset, desc_len, &current_out_cdesc, &meta_out, alloc_flag);
1202 if (failed) {
1203 DEBUG_API(printk("cryptocop_setup_dma_list: create_output_descriptors %d\n", failed));
1204 goto error_cleanup;
1206 /* Setup out EOP. If there are active units that are not done here they cannot get an EOP
1207 * so we ust setup a zero length descriptor to DMA to signal EOP only to done units.
1208 * If there is a pad descriptor EOP for the padded unit will be EOPed by it.
1210 assert(active_count >= eop_needed_count);
1211 assert((eop_needed_count == 0) || (eop_needed_count == 1));
1212 if (eop_needed_count) {
1213 /* This means that the bulk operation (cipeher/m2m) is terminated. */
1214 if (active_count > 1) {
1215 /* Use zero length EOP descriptor. */
1216 struct cryptocop_dma_desc *ed = alloc_cdesc(alloc_flag);
1217 struct strcop_meta_out ed_mo = {0};
1218 if (!ed) {
1219 DEBUG_API(printk("cryptocop_setup_dma_list: alloc EOP descriptor for cipher\n"));
1220 failed = -ENOMEM;
1221 goto error_cleanup;
1224 assert(cipher_ctx.active && cipher_ctx.done);
1226 if (cipher_ctx.unit_no == src_dma){
1227 /* mem2mem */
1228 ed_mo.ciphsel = src_none;
1229 } else {
1230 ed_mo.ciphsel = cipher_ctx.current_src;
1232 ed_mo.ciphconf = cipher_ctx.ciph_conf;
1233 ed_mo.cbcmode = cipher_ctx.cbcmode;
1234 ed_mo.decrypt = cipher_ctx.decrypt;
1236 ed->free_buf = NULL;
1237 ed->dma_descr->wait = 1;
1238 ed->dma_descr->out_eop = 1;
1240 ed->dma_descr->buf = (char*)virt_to_phys(&ed); /* Use any valid physical address for zero length descriptor. */
1241 ed->dma_descr->after = ed->dma_descr->buf;
1242 ed->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_out, ed_mo);
1243 current_out_cdesc->next = ed;
1244 current_out_cdesc = ed;
1245 } else {
1246 /* Set EOP in the current out descriptor since the only active module is
1247 * the one needing the EOP. */
1249 current_out_cdesc->dma_descr->out_eop = 1;
1253 if (cipher_ctx.done && cipher_ctx.active) cipher_ctx.active = 0;
1254 if (digest_ctx.done && digest_ctx.active) digest_ctx.active = 0;
1255 if (csum_ctx.done && csum_ctx.active) csum_ctx.active = 0;
1256 indata_ix += odsc->length;
1257 odsc = odsc->next;
1258 } /* while (odsc) */ /* Process descriptors. */
1259 DEBUG(printk("cryptocop_setup_dma_list: done parsing operation descriptors\n"));
1260 if (cipher_ctx.tcfg && (cipher_ctx.active || !cipher_ctx.done)){
1261 DEBUG_API(printk("cryptocop_setup_dma_list: cipher operation not terminated.\n"));
1262 failed = -EINVAL;
1263 goto error_cleanup;
1265 if (digest_ctx.tcfg && (digest_ctx.active || !digest_ctx.done)){
1266 DEBUG_API(printk("cryptocop_setup_dma_list: digest operation not terminated.\n"));
1267 failed = -EINVAL;
1268 goto error_cleanup;
1270 if (csum_ctx.tcfg && (csum_ctx.active || !csum_ctx.done)){
1271 DEBUG_API(printk("cryptocop_setup_dma_list: csum operation not terminated.\n"));
1272 failed = -EINVAL;
1273 goto error_cleanup;
1276 failed = append_input_descriptors(operation, &current_in_cdesc, &current_out_cdesc, &cipher_ctx, alloc_flag);
1277 if (failed){
1278 DEBUG_API(printk("cryptocop_setup_dma_list: append_input_descriptors cipher_ctx %d\n", failed));
1279 goto error_cleanup;
1281 failed = append_input_descriptors(operation, &current_in_cdesc, &current_out_cdesc, &digest_ctx, alloc_flag);
1282 if (failed){
1283 DEBUG_API(printk("cryptocop_setup_dma_list: append_input_descriptors cipher_ctx %d\n", failed));
1284 goto error_cleanup;
1286 failed = append_input_descriptors(operation, &current_in_cdesc, &current_out_cdesc, &csum_ctx, alloc_flag);
1287 if (failed){
1288 DEBUG_API(printk("cryptocop_setup_dma_list: append_input_descriptors cipher_ctx %d\n", failed));
1289 goto error_cleanup;
1292 DEBUG(printk("cryptocop_setup_dma_list: int_op=0x%p, *int_op=0x%p\n", int_op, *int_op));
1293 (*int_op)->cdesc_out = out_cdesc_head.next;
1294 (*int_op)->cdesc_in = in_cdesc_head.next;
1295 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));
1297 setup_descr_chain(out_cdesc_head.next);
1298 setup_descr_chain(in_cdesc_head.next);
1300 /* Last but not least: mark the last DMA in descriptor for a INTR and EOL and the the
1301 * last DMA out descriptor for EOL.
1303 current_in_cdesc->dma_descr->intr = 1;
1304 current_in_cdesc->dma_descr->eol = 1;
1305 current_out_cdesc->dma_descr->eol = 1;
1307 /* Setup DMA contexts. */
1308 (*int_op)->ctx_out.next = NULL;
1309 (*int_op)->ctx_out.eol = 1;
1310 (*int_op)->ctx_out.intr = 0;
1311 (*int_op)->ctx_out.store_mode = 0;
1312 (*int_op)->ctx_out.en = 0;
1313 (*int_op)->ctx_out.dis = 0;
1314 (*int_op)->ctx_out.md0 = 0;
1315 (*int_op)->ctx_out.md1 = 0;
1316 (*int_op)->ctx_out.md2 = 0;
1317 (*int_op)->ctx_out.md3 = 0;
1318 (*int_op)->ctx_out.md4 = 0;
1319 (*int_op)->ctx_out.saved_data = (dma_descr_data*)virt_to_phys((*int_op)->cdesc_out->dma_descr);
1320 (*int_op)->ctx_out.saved_data_buf = (*int_op)->cdesc_out->dma_descr->buf; /* Already physical address. */
1322 (*int_op)->ctx_in.next = NULL;
1323 (*int_op)->ctx_in.eol = 1;
1324 (*int_op)->ctx_in.intr = 0;
1325 (*int_op)->ctx_in.store_mode = 0;
1326 (*int_op)->ctx_in.en = 0;
1327 (*int_op)->ctx_in.dis = 0;
1328 (*int_op)->ctx_in.md0 = 0;
1329 (*int_op)->ctx_in.md1 = 0;
1330 (*int_op)->ctx_in.md2 = 0;
1331 (*int_op)->ctx_in.md3 = 0;
1332 (*int_op)->ctx_in.md4 = 0;
1334 (*int_op)->ctx_in.saved_data = (dma_descr_data*)virt_to_phys((*int_op)->cdesc_in->dma_descr);
1335 (*int_op)->ctx_in.saved_data_buf = (*int_op)->cdesc_in->dma_descr->buf; /* Already physical address. */
1337 DEBUG(printk("cryptocop_setup_dma_list: done\n"));
1338 return 0;
1340 error_cleanup:
1342 /* Free all allocated resources. */
1343 struct cryptocop_dma_desc *tmp_cdesc;
1344 while (digest_ctx.pad_descs){
1345 tmp_cdesc = digest_ctx.pad_descs->next;
1346 free_cdesc(digest_ctx.pad_descs);
1347 digest_ctx.pad_descs = tmp_cdesc;
1349 while (csum_ctx.pad_descs){
1350 tmp_cdesc = csum_ctx.pad_descs->next;
1351 free_cdesc(csum_ctx.pad_descs);
1352 csum_ctx.pad_descs = tmp_cdesc;
1354 assert(cipher_ctx.pad_descs == NULL); /* The ciphers are never padded. */
1356 if (*int_op != NULL) delete_internal_operation(*int_op);
1358 DEBUG_API(printk("cryptocop_setup_dma_list: done with error %d\n", failed));
1359 return failed;
1363 static void delete_internal_operation(struct cryptocop_int_operation *iop)
1365 void *ptr = iop->alloc_ptr;
1366 struct cryptocop_dma_desc *cd = iop->cdesc_out;
1367 struct cryptocop_dma_desc *next;
1369 DEBUG(printk("delete_internal_operation: iop=0x%p, alloc_ptr=0x%p\n", iop, ptr));
1371 while (cd) {
1372 next = cd->next;
1373 free_cdesc(cd);
1374 cd = next;
1376 cd = iop->cdesc_in;
1377 while (cd) {
1378 next = cd->next;
1379 free_cdesc(cd);
1380 cd = next;
1382 kfree(ptr);
1385 #define MD5_MIN_PAD_LENGTH (9)
1386 #define MD5_PAD_LENGTH_FIELD_LENGTH (8)
1388 static int create_md5_pad(int alloc_flag, unsigned long long hashed_length, char **pad, size_t *pad_length)
1390 size_t padlen = MD5_BLOCK_LENGTH - (hashed_length % MD5_BLOCK_LENGTH);
1391 unsigned char *p;
1392 int i;
1393 unsigned long long int bit_length = hashed_length << 3;
1395 if (padlen < MD5_MIN_PAD_LENGTH) padlen += MD5_BLOCK_LENGTH;
1397 p = kzalloc(padlen, alloc_flag);
1398 if (!p) return -ENOMEM;
1400 *p = 0x80;
1402 DEBUG(printk("create_md5_pad: hashed_length=%lld bits == %lld bytes\n", bit_length, hashed_length));
1404 i = padlen - MD5_PAD_LENGTH_FIELD_LENGTH;
1405 while (bit_length != 0){
1406 p[i++] = bit_length % 0x100;
1407 bit_length >>= 8;
1410 *pad = (char*)p;
1411 *pad_length = padlen;
1413 return 0;
1416 #define SHA1_MIN_PAD_LENGTH (9)
1417 #define SHA1_PAD_LENGTH_FIELD_LENGTH (8)
1419 static int create_sha1_pad(int alloc_flag, unsigned long long hashed_length, char **pad, size_t *pad_length)
1421 size_t padlen = SHA1_BLOCK_LENGTH - (hashed_length % SHA1_BLOCK_LENGTH);
1422 unsigned char *p;
1423 int i;
1424 unsigned long long int bit_length = hashed_length << 3;
1426 if (padlen < SHA1_MIN_PAD_LENGTH) padlen += SHA1_BLOCK_LENGTH;
1428 p = kzalloc(padlen, alloc_flag);
1429 if (!p) return -ENOMEM;
1431 *p = 0x80;
1433 DEBUG(printk("create_sha1_pad: hashed_length=%lld bits == %lld bytes\n", bit_length, hashed_length));
1435 i = padlen - 1;
1436 while (bit_length != 0){
1437 p[i--] = bit_length % 0x100;
1438 bit_length >>= 8;
1441 *pad = (char*)p;
1442 *pad_length = padlen;
1444 return 0;
1448 static int transform_ok(struct cryptocop_transform_init *tinit)
1450 switch (tinit->alg){
1451 case cryptocop_alg_csum:
1452 switch (tinit->csum_mode){
1453 case cryptocop_csum_le:
1454 case cryptocop_csum_be:
1455 break;
1456 default:
1457 DEBUG_API(printk("transform_ok: Bad mode set for csum transform\n"));
1458 return -EINVAL;
1460 case cryptocop_alg_mem2mem:
1461 case cryptocop_alg_md5:
1462 case cryptocop_alg_sha1:
1463 if (tinit->keylen != 0) {
1464 DEBUG_API(printk("transform_ok: non-zero keylength, %d, for a digest/csum algorithm\n", tinit->keylen));
1465 return -EINVAL; /* This check is a bit strict. */
1467 break;
1468 case cryptocop_alg_des:
1469 if (tinit->keylen != 64) {
1470 DEBUG_API(printk("transform_ok: keylen %d invalid for DES\n", tinit->keylen));
1471 return -EINVAL;
1473 break;
1474 case cryptocop_alg_3des:
1475 if (tinit->keylen != 192) {
1476 DEBUG_API(printk("transform_ok: keylen %d invalid for 3DES\n", tinit->keylen));
1477 return -EINVAL;
1479 break;
1480 case cryptocop_alg_aes:
1481 if (tinit->keylen != 128 && tinit->keylen != 192 && tinit->keylen != 256) {
1482 DEBUG_API(printk("transform_ok: keylen %d invalid for AES\n", tinit->keylen));
1483 return -EINVAL;
1485 break;
1486 case cryptocop_no_alg:
1487 default:
1488 DEBUG_API(printk("transform_ok: no such algorithm %d\n", tinit->alg));
1489 return -EINVAL;
1492 switch (tinit->alg){
1493 case cryptocop_alg_des:
1494 case cryptocop_alg_3des:
1495 case cryptocop_alg_aes:
1496 if (tinit->cipher_mode != cryptocop_cipher_mode_ecb && tinit->cipher_mode != cryptocop_cipher_mode_cbc) return -EINVAL;
1497 default:
1498 break;
1500 return 0;
1504 int cryptocop_new_session(cryptocop_session_id *sid, struct cryptocop_transform_init *tinit, int alloc_flag)
1506 struct cryptocop_session *sess;
1507 struct cryptocop_transform_init *tfrm_in = tinit;
1508 struct cryptocop_transform_init *tmp_in;
1509 int no_tfrms = 0;
1510 int i;
1511 unsigned long int flags;
1513 init_stream_coprocessor(); /* For safety if we are called early */
1515 while (tfrm_in){
1516 int err;
1517 ++no_tfrms;
1518 if ((err = transform_ok(tfrm_in))) {
1519 DEBUG_API(printk("cryptocop_new_session, bad transform\n"));
1520 return err;
1522 tfrm_in = tfrm_in->next;
1524 if (0 == no_tfrms) {
1525 DEBUG_API(printk("cryptocop_new_session, no transforms specified\n"));
1526 return -EINVAL;
1529 sess = kmalloc(sizeof(struct cryptocop_session), alloc_flag);
1530 if (!sess){
1531 DEBUG_API(printk("cryptocop_new_session, kmalloc cryptocop_session\n"));
1532 return -ENOMEM;
1535 sess->tfrm_ctx = kmalloc(no_tfrms * sizeof(struct cryptocop_transform_ctx), alloc_flag);
1536 if (!sess->tfrm_ctx) {
1537 DEBUG_API(printk("cryptocop_new_session, kmalloc cryptocop_transform_ctx\n"));
1538 kfree(sess);
1539 return -ENOMEM;
1542 tfrm_in = tinit;
1543 for (i = 0; i < no_tfrms; i++){
1544 tmp_in = tfrm_in->next;
1545 while (tmp_in){
1546 if (tmp_in->tid == tfrm_in->tid) {
1547 DEBUG_API(printk("cryptocop_new_session, duplicate transform ids\n"));
1548 kfree(sess->tfrm_ctx);
1549 kfree(sess);
1550 return -EINVAL;
1552 tmp_in = tmp_in->next;
1554 memcpy(&sess->tfrm_ctx[i].init, tfrm_in, sizeof(struct cryptocop_transform_init));
1555 sess->tfrm_ctx[i].dec_key_set = 0;
1556 sess->tfrm_ctx[i].next = &sess->tfrm_ctx[i] + 1;
1558 tfrm_in = tfrm_in->next;
1560 sess->tfrm_ctx[i-1].next = NULL;
1562 spin_lock_irqsave(&cryptocop_sessions_lock, flags);
1563 sess->sid = next_sid;
1564 next_sid++;
1565 /* TODO If we are really paranoid we should do duplicate check to handle sid wraparound.
1566 * OTOH 2^64 is a really large number of session. */
1567 if (next_sid == 0) next_sid = 1;
1569 /* Prepend to session list. */
1570 sess->next = cryptocop_sessions;
1571 cryptocop_sessions = sess;
1572 spin_unlock_irqrestore(&cryptocop_sessions_lock, flags);
1573 *sid = sess->sid;
1574 return 0;
1578 int cryptocop_free_session(cryptocop_session_id sid)
1580 struct cryptocop_transform_ctx *tc;
1581 struct cryptocop_session *sess = NULL;
1582 struct cryptocop_session *psess = NULL;
1583 unsigned long int flags;
1584 int i;
1585 LIST_HEAD(remove_list);
1586 struct list_head *node, *tmp;
1587 struct cryptocop_prio_job *pj;
1589 DEBUG(printk("cryptocop_free_session: sid=%lld\n", sid));
1591 spin_lock_irqsave(&cryptocop_sessions_lock, flags);
1592 sess = cryptocop_sessions;
1593 while (sess && sess->sid != sid){
1594 psess = sess;
1595 sess = sess->next;
1597 if (sess){
1598 if (psess){
1599 psess->next = sess->next;
1600 } else {
1601 cryptocop_sessions = sess->next;
1604 spin_unlock_irqrestore(&cryptocop_sessions_lock, flags);
1606 if (!sess) return -EINVAL;
1608 /* Remove queued jobs. */
1609 spin_lock_irqsave(&cryptocop_job_queue_lock, flags);
1611 for (i = 0; i < cryptocop_prio_no_prios; i++){
1612 if (!list_empty(&(cryptocop_job_queues[i].jobs))){
1613 list_for_each_safe(node, tmp, &(cryptocop_job_queues[i].jobs)) {
1614 pj = list_entry(node, struct cryptocop_prio_job, node);
1615 if (pj->oper->sid == sid) {
1616 list_move_tail(node, &remove_list);
1621 spin_unlock_irqrestore(&cryptocop_job_queue_lock, flags);
1623 list_for_each_safe(node, tmp, &remove_list) {
1624 list_del(node);
1625 pj = list_entry(node, struct cryptocop_prio_job, node);
1626 pj->oper->operation_status = -EAGAIN; /* EAGAIN is not ideal for job/session terminated but it's the best choice I know of. */
1627 DEBUG(printk("cryptocop_free_session: pj=0x%p, pj->oper=0x%p, pj->iop=0x%p\n", pj, pj->oper, pj->iop));
1628 pj->oper->cb(pj->oper, pj->oper->cb_data);
1629 delete_internal_operation(pj->iop);
1630 kfree(pj);
1633 tc = sess->tfrm_ctx;
1634 /* Erase keying data. */
1635 while (tc){
1636 DEBUG(printk("cryptocop_free_session: memset keys, tfrm id=%d\n", tc->init.tid));
1637 memset(tc->init.key, 0xff, CRYPTOCOP_MAX_KEY_LENGTH);
1638 memset(tc->dec_key, 0xff, CRYPTOCOP_MAX_KEY_LENGTH);
1639 tc = tc->next;
1641 kfree(sess->tfrm_ctx);
1642 kfree(sess);
1644 return 0;
1647 static struct cryptocop_session *get_session(cryptocop_session_id sid)
1649 struct cryptocop_session *sess;
1650 unsigned long int flags;
1652 spin_lock_irqsave(&cryptocop_sessions_lock, flags);
1653 sess = cryptocop_sessions;
1654 while (sess && (sess->sid != sid)){
1655 sess = sess->next;
1657 spin_unlock_irqrestore(&cryptocop_sessions_lock, flags);
1659 return sess;
1662 static struct cryptocop_transform_ctx *get_transform_ctx(struct cryptocop_session *sess, cryptocop_tfrm_id tid)
1664 struct cryptocop_transform_ctx *tc = sess->tfrm_ctx;
1666 DEBUG(printk("get_transform_ctx, sess=0x%p, tid=%d\n", sess, tid));
1667 assert(sess != NULL);
1668 while (tc && tc->init.tid != tid){
1669 DEBUG(printk("tc=0x%p, tc->next=0x%p\n", tc, tc->next));
1670 tc = tc->next;
1672 DEBUG(printk("get_transform_ctx, returning tc=0x%p\n", tc));
1673 return tc;
1678 /* The AES s-transform matrix (s-box). */
1679 static const u8 aes_sbox[256] = {
1680 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
1681 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
1682 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
1683 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
1684 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
1685 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
1686 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
1687 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
1688 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
1689 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
1690 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
1691 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
1692 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
1693 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
1694 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
1695 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22
1698 /* AES has a 32 bit word round constants for each round in the
1699 * key schedule. round_constant[i] is really Rcon[i+1] in FIPS187.
1701 static u32 round_constant[11] = {
1702 0x01000000, 0x02000000, 0x04000000, 0x08000000,
1703 0x10000000, 0x20000000, 0x40000000, 0x80000000,
1704 0x1B000000, 0x36000000, 0x6C000000
1707 /* Apply the s-box to each of the four occtets in w. */
1708 static u32 aes_ks_subword(const u32 w)
1710 u8 bytes[4];
1712 *(u32*)(&bytes[0]) = w;
1713 bytes[0] = aes_sbox[bytes[0]];
1714 bytes[1] = aes_sbox[bytes[1]];
1715 bytes[2] = aes_sbox[bytes[2]];
1716 bytes[3] = aes_sbox[bytes[3]];
1717 return *(u32*)(&bytes[0]);
1720 /* The encrypt (forward) Rijndael key schedule algorithm pseudo code:
1721 * (Note that AES words are 32 bit long)
1723 * KeyExpansion(byte key[4*Nk], word w[Nb*(Nr+1)], Nk){
1724 * word temp
1725 * i = 0
1726 * while (i < Nk) {
1727 * w[i] = word(key[4*i, 4*i + 1, 4*i + 2, 4*i + 3])
1728 * i = i + 1
1730 * i = Nk
1732 * while (i < (Nb * (Nr + 1))) {
1733 * temp = w[i - 1]
1734 * if ((i mod Nk) == 0) {
1735 * temp = SubWord(RotWord(temp)) xor Rcon[i/Nk]
1737 * else if ((Nk > 6) && ((i mod Nk) == 4)) {
1738 * temp = SubWord(temp)
1740 * w[i] = w[i - Nk] xor temp
1742 * RotWord(t) does a 8 bit cyclic shift left on a 32 bit word.
1743 * SubWord(t) applies the AES s-box individually to each octet
1744 * in a 32 bit word.
1746 * For AES Nk can have the values 4, 6, and 8 (corresponding to
1747 * values for Nr of 10, 12, and 14). Nb is always 4.
1749 * To construct w[i], w[i - 1] and w[i - Nk] must be
1750 * available. Consequently we must keep a state of the last Nk words
1751 * to be able to create the last round keys.
1753 static void get_aes_decrypt_key(unsigned char *dec_key, const unsigned char *key, unsigned int keylength)
1755 u32 temp;
1756 u32 w_ring[8]; /* nk is max 8, use elements 0..(nk - 1) as a ringbuffer */
1757 u8 w_last_ix;
1758 int i;
1759 u8 nr, nk;
1761 switch (keylength){
1762 case 128:
1763 nk = 4;
1764 nr = 10;
1765 break;
1766 case 192:
1767 nk = 6;
1768 nr = 12;
1769 break;
1770 case 256:
1771 nk = 8;
1772 nr = 14;
1773 break;
1774 default:
1775 panic("stream co-processor: bad aes key length in get_aes_decrypt_key\n");
1778 /* Need to do host byte order correction here since key is byte oriented and the
1779 * kx algorithm is word (u32) oriented. */
1780 for (i = 0; i < nk; i+=1) {
1781 w_ring[i] = be32_to_cpu(*(u32*)&key[4*i]);
1784 i = (int)nk;
1785 w_last_ix = i - 1;
1786 while (i < (4 * (nr + 2))) {
1787 temp = w_ring[w_last_ix];
1788 if (!(i % nk)) {
1789 /* RotWord(temp) */
1790 temp = (temp << 8) | (temp >> 24);
1791 temp = aes_ks_subword(temp);
1792 temp ^= round_constant[i/nk - 1];
1793 } else if ((nk > 6) && ((i % nk) == 4)) {
1794 temp = aes_ks_subword(temp);
1796 w_last_ix = (w_last_ix + 1) % nk; /* This is the same as (i-Nk) mod Nk */
1797 temp ^= w_ring[w_last_ix];
1798 w_ring[w_last_ix] = temp;
1800 /* We need the round keys for round Nr+1 and Nr+2 (round key
1801 * Nr+2 is the round key beyond the last one used when
1802 * encrypting). Rounds are numbered starting from 0, Nr=10
1803 * implies 11 rounds are used in encryption/decryption.
1805 if (i >= (4 * nr)) {
1806 /* Need to do host byte order correction here, the key
1807 * is byte oriented. */
1808 *(u32*)dec_key = cpu_to_be32(temp);
1809 dec_key += 4;
1811 ++i;
1816 /**** Job/operation management. ****/
1818 int cryptocop_job_queue_insert_csum(struct cryptocop_operation *operation)
1820 return cryptocop_job_queue_insert(cryptocop_prio_kernel_csum, operation);
1823 int cryptocop_job_queue_insert_crypto(struct cryptocop_operation *operation)
1825 return cryptocop_job_queue_insert(cryptocop_prio_kernel, operation);
1828 int cryptocop_job_queue_insert_user_job(struct cryptocop_operation *operation)
1830 return cryptocop_job_queue_insert(cryptocop_prio_user, operation);
1833 static int cryptocop_job_queue_insert(cryptocop_queue_priority prio, struct cryptocop_operation *operation)
1835 int ret;
1836 struct cryptocop_prio_job *pj = NULL;
1837 unsigned long int flags;
1839 DEBUG(printk("cryptocop_job_queue_insert(%d, 0x%p)\n", prio, operation));
1841 if (!operation || !operation->cb){
1842 DEBUG_API(printk("cryptocop_job_queue_insert oper=0x%p, NULL operation or callback\n", operation));
1843 return -EINVAL;
1846 if ((ret = cryptocop_job_setup(&pj, operation)) != 0){
1847 DEBUG_API(printk("cryptocop_job_queue_insert: job setup failed\n"));
1848 return ret;
1850 assert(pj != NULL);
1852 spin_lock_irqsave(&cryptocop_job_queue_lock, flags);
1853 list_add_tail(&pj->node, &cryptocop_job_queues[prio].jobs);
1854 spin_unlock_irqrestore(&cryptocop_job_queue_lock, flags);
1856 /* Make sure a job is running */
1857 cryptocop_start_job();
1858 return 0;
1861 static void cryptocop_do_tasklet(unsigned long unused);
1862 DECLARE_TASKLET (cryptocop_tasklet, cryptocop_do_tasklet, 0);
1864 static void cryptocop_do_tasklet(unsigned long unused)
1866 struct list_head *node;
1867 struct cryptocop_prio_job *pj = NULL;
1868 unsigned long flags;
1870 DEBUG(printk("cryptocop_do_tasklet: entering\n"));
1872 do {
1873 spin_lock_irqsave(&cryptocop_completed_jobs_lock, flags);
1874 if (!list_empty(&cryptocop_completed_jobs)){
1875 node = cryptocop_completed_jobs.next;
1876 list_del(node);
1877 pj = list_entry(node, struct cryptocop_prio_job, node);
1878 } else {
1879 pj = NULL;
1881 spin_unlock_irqrestore(&cryptocop_completed_jobs_lock, flags);
1882 if (pj) {
1883 assert(pj->oper != NULL);
1885 /* Notify consumer of operation completeness. */
1886 DEBUG(printk("cryptocop_do_tasklet: callback 0x%p, data 0x%p\n", pj->oper->cb, pj->oper->cb_data));
1888 pj->oper->operation_status = 0; /* Job is completed. */
1889 pj->oper->cb(pj->oper, pj->oper->cb_data);
1890 delete_internal_operation(pj->iop);
1891 kfree(pj);
1893 } while (pj != NULL);
1895 DEBUG(printk("cryptocop_do_tasklet: exiting\n"));
1898 static irqreturn_t
1899 dma_done_interrupt(int irq, void *dev_id)
1901 struct cryptocop_prio_job *done_job;
1902 reg_dma_rw_ack_intr ack_intr = {
1903 .data = 1,
1906 REG_WR(dma, IN_DMA_INST, rw_ack_intr, ack_intr);
1908 DEBUG(printk("cryptocop DMA done\n"));
1910 spin_lock(&running_job_lock);
1911 if (cryptocop_running_job == NULL){
1912 printk("stream co-processor got interrupt when not busy\n");
1913 spin_unlock(&running_job_lock);
1914 return IRQ_HANDLED;
1916 done_job = cryptocop_running_job;
1917 cryptocop_running_job = NULL;
1918 spin_unlock(&running_job_lock);
1920 /* Start processing a job. */
1921 if (!spin_trylock(&cryptocop_process_lock)){
1922 DEBUG(printk("cryptocop irq handler, not starting a job\n"));
1923 } else {
1924 cryptocop_start_job();
1925 spin_unlock(&cryptocop_process_lock);
1928 done_job->oper->operation_status = 0; /* Job is completed. */
1929 if (done_job->oper->fast_callback){
1930 /* This operation wants callback from interrupt. */
1931 done_job->oper->cb(done_job->oper, done_job->oper->cb_data);
1932 delete_internal_operation(done_job->iop);
1933 kfree(done_job);
1934 } else {
1935 spin_lock(&cryptocop_completed_jobs_lock);
1936 list_add_tail(&(done_job->node), &cryptocop_completed_jobs);
1937 spin_unlock(&cryptocop_completed_jobs_lock);
1938 tasklet_schedule(&cryptocop_tasklet);
1941 DEBUG(printk("cryptocop leave irq handler\n"));
1942 return IRQ_HANDLED;
1946 /* Setup interrupts and DMA channels. */
1947 static int init_cryptocop(void)
1949 unsigned long flags;
1950 reg_dma_rw_cfg dma_cfg = {.en = 1};
1951 reg_dma_rw_intr_mask intr_mask_in = {.data = regk_dma_yes}; /* Only want descriptor interrupts from the DMA in channel. */
1952 reg_dma_rw_ack_intr ack_intr = {.data = 1,.in_eop = 1 };
1953 reg_strcop_rw_cfg strcop_cfg = {
1954 .ipend = regk_strcop_little,
1955 .td1 = regk_strcop_e,
1956 .td2 = regk_strcop_d,
1957 .td3 = regk_strcop_e,
1958 .ignore_sync = 0,
1959 .en = 1
1962 if (request_irq(DMA_IRQ, dma_done_interrupt, 0,
1963 "stream co-processor DMA", NULL))
1964 panic("request_irq stream co-processor irq dma9");
1966 (void)crisv32_request_dma(OUT_DMA, "strcop", DMA_PANIC_ON_ERROR,
1967 0, dma_strp);
1968 (void)crisv32_request_dma(IN_DMA, "strcop", DMA_PANIC_ON_ERROR,
1969 0, dma_strp);
1971 local_irq_save(flags);
1973 /* Reset and enable the cryptocop. */
1974 strcop_cfg.en = 0;
1975 REG_WR(strcop, regi_strcop, rw_cfg, strcop_cfg);
1976 strcop_cfg.en = 1;
1977 REG_WR(strcop, regi_strcop, rw_cfg, strcop_cfg);
1979 /* Enable DMAs. */
1980 REG_WR(dma, IN_DMA_INST, rw_cfg, dma_cfg); /* input DMA */
1981 REG_WR(dma, OUT_DMA_INST, rw_cfg, dma_cfg); /* output DMA */
1983 /* Set up wordsize = 4 for DMAs. */
1984 DMA_WR_CMD(OUT_DMA_INST, regk_dma_set_w_size4);
1985 DMA_WR_CMD(IN_DMA_INST, regk_dma_set_w_size4);
1987 /* Enable interrupts. */
1988 REG_WR(dma, IN_DMA_INST, rw_intr_mask, intr_mask_in);
1990 /* Clear intr ack. */
1991 REG_WR(dma, IN_DMA_INST, rw_ack_intr, ack_intr);
1993 local_irq_restore(flags);
1995 return 0;
1998 /* Free used cryptocop hw resources (interrupt and DMA channels). */
1999 static void release_cryptocop(void)
2001 unsigned long flags;
2002 reg_dma_rw_cfg dma_cfg = {.en = 0};
2003 reg_dma_rw_intr_mask intr_mask_in = {0};
2004 reg_dma_rw_ack_intr ack_intr = {.data = 1,.in_eop = 1 };
2006 local_irq_save(flags);
2008 /* Clear intr ack. */
2009 REG_WR(dma, IN_DMA_INST, rw_ack_intr, ack_intr);
2011 /* Disable DMAs. */
2012 REG_WR(dma, IN_DMA_INST, rw_cfg, dma_cfg); /* input DMA */
2013 REG_WR(dma, OUT_DMA_INST, rw_cfg, dma_cfg); /* output DMA */
2015 /* Disable interrupts. */
2016 REG_WR(dma, IN_DMA_INST, rw_intr_mask, intr_mask_in);
2018 local_irq_restore(flags);
2020 free_irq(DMA_IRQ, NULL);
2022 (void)crisv32_free_dma(OUT_DMA);
2023 (void)crisv32_free_dma(IN_DMA);
2027 /* Init job queue. */
2028 static int cryptocop_job_queue_init(void)
2030 int i;
2032 INIT_LIST_HEAD(&cryptocop_completed_jobs);
2034 for (i = 0; i < cryptocop_prio_no_prios; i++){
2035 cryptocop_job_queues[i].prio = (cryptocop_queue_priority)i;
2036 INIT_LIST_HEAD(&cryptocop_job_queues[i].jobs);
2038 return 0;
2042 static void cryptocop_job_queue_close(void)
2044 struct list_head *node, *tmp;
2045 struct cryptocop_prio_job *pj = NULL;
2046 unsigned long int process_flags, flags;
2047 int i;
2049 /* FIXME: This is as yet untested code. */
2051 /* Stop strcop from getting an operation to process while we are closing the
2052 module. */
2053 spin_lock_irqsave(&cryptocop_process_lock, process_flags);
2055 /* Empty the job queue. */
2056 for (i = 0; i < cryptocop_prio_no_prios; i++){
2057 if (!list_empty(&(cryptocop_job_queues[i].jobs))){
2058 list_for_each_safe(node, tmp, &(cryptocop_job_queues[i].jobs)) {
2059 pj = list_entry(node, struct cryptocop_prio_job, node);
2060 list_del(node);
2062 /* Call callback to notify consumer of job removal. */
2063 DEBUG(printk("cryptocop_job_queue_close: callback 0x%p, data 0x%p\n", pj->oper->cb, pj->oper->cb_data));
2064 pj->oper->operation_status = -EINTR; /* Job is terminated without completion. */
2065 pj->oper->cb(pj->oper, pj->oper->cb_data);
2067 delete_internal_operation(pj->iop);
2068 kfree(pj);
2072 spin_unlock_irqrestore(&cryptocop_process_lock, process_flags);
2074 /* Remove the running job, if any. */
2075 spin_lock_irqsave(&running_job_lock, flags);
2076 if (cryptocop_running_job){
2077 reg_strcop_rw_cfg rw_cfg;
2078 reg_dma_rw_cfg dma_out_cfg, dma_in_cfg;
2080 /* Stop DMA. */
2081 dma_out_cfg = REG_RD(dma, OUT_DMA_INST, rw_cfg);
2082 dma_out_cfg.en = regk_dma_no;
2083 REG_WR(dma, OUT_DMA_INST, rw_cfg, dma_out_cfg);
2085 dma_in_cfg = REG_RD(dma, IN_DMA_INST, rw_cfg);
2086 dma_in_cfg.en = regk_dma_no;
2087 REG_WR(dma, IN_DMA_INST, rw_cfg, dma_in_cfg);
2089 /* Disble the cryptocop. */
2090 rw_cfg = REG_RD(strcop, regi_strcop, rw_cfg);
2091 rw_cfg.en = 0;
2092 REG_WR(strcop, regi_strcop, rw_cfg, rw_cfg);
2094 pj = cryptocop_running_job;
2095 cryptocop_running_job = NULL;
2097 /* Call callback to notify consumer of job removal. */
2098 DEBUG(printk("cryptocop_job_queue_close: callback 0x%p, data 0x%p\n", pj->oper->cb, pj->oper->cb_data));
2099 pj->oper->operation_status = -EINTR; /* Job is terminated without completion. */
2100 pj->oper->cb(pj->oper, pj->oper->cb_data);
2102 delete_internal_operation(pj->iop);
2103 kfree(pj);
2105 spin_unlock_irqrestore(&running_job_lock, flags);
2107 /* Remove completed jobs, if any. */
2108 spin_lock_irqsave(&cryptocop_completed_jobs_lock, flags);
2110 list_for_each_safe(node, tmp, &cryptocop_completed_jobs) {
2111 pj = list_entry(node, struct cryptocop_prio_job, node);
2112 list_del(node);
2113 /* Call callback to notify consumer of job removal. */
2114 DEBUG(printk("cryptocop_job_queue_close: callback 0x%p, data 0x%p\n", pj->oper->cb, pj->oper->cb_data));
2115 pj->oper->operation_status = -EINTR; /* Job is terminated without completion. */
2116 pj->oper->cb(pj->oper, pj->oper->cb_data);
2118 delete_internal_operation(pj->iop);
2119 kfree(pj);
2121 spin_unlock_irqrestore(&cryptocop_completed_jobs_lock, flags);
2125 static void cryptocop_start_job(void)
2127 int i;
2128 struct cryptocop_prio_job *pj;
2129 unsigned long int flags;
2130 unsigned long int running_job_flags;
2131 reg_strcop_rw_cfg rw_cfg = {.en = 1, .ignore_sync = 0};
2133 DEBUG(printk("cryptocop_start_job: entering\n"));
2135 spin_lock_irqsave(&running_job_lock, running_job_flags);
2136 if (cryptocop_running_job != NULL){
2137 /* Already running. */
2138 DEBUG(printk("cryptocop_start_job: already running, exit\n"));
2139 spin_unlock_irqrestore(&running_job_lock, running_job_flags);
2140 return;
2142 spin_lock_irqsave(&cryptocop_job_queue_lock, flags);
2144 /* Check the queues in priority order. */
2145 for (i = cryptocop_prio_kernel_csum; (i < cryptocop_prio_no_prios) && list_empty(&cryptocop_job_queues[i].jobs); i++);
2146 if (i == cryptocop_prio_no_prios) {
2147 spin_unlock_irqrestore(&cryptocop_job_queue_lock, flags);
2148 spin_unlock_irqrestore(&running_job_lock, running_job_flags);
2149 DEBUG(printk("cryptocop_start_job: no jobs to run\n"));
2150 return; /* No jobs to run */
2152 DEBUG(printk("starting job for prio %d\n", i));
2154 /* TODO: Do not starve lower priority jobs. Let in a lower
2155 * prio job for every N-th processed higher prio job or some
2156 * other scheduling policy. This could reasonably be
2157 * tweakable since the optimal balance would depend on the
2158 * type of load on the system. */
2160 /* Pull the DMA lists from the job and start the DMA client. */
2161 pj = list_entry(cryptocop_job_queues[i].jobs.next, struct cryptocop_prio_job, node);
2162 list_del(&pj->node);
2163 spin_unlock_irqrestore(&cryptocop_job_queue_lock, flags);
2164 cryptocop_running_job = pj;
2166 /* Set config register (3DES and CSUM modes). */
2167 switch (pj->iop->tdes_mode){
2168 case cryptocop_3des_eee:
2169 rw_cfg.td1 = regk_strcop_e;
2170 rw_cfg.td2 = regk_strcop_e;
2171 rw_cfg.td3 = regk_strcop_e;
2172 break;
2173 case cryptocop_3des_eed:
2174 rw_cfg.td1 = regk_strcop_e;
2175 rw_cfg.td2 = regk_strcop_e;
2176 rw_cfg.td3 = regk_strcop_d;
2177 break;
2178 case cryptocop_3des_ede:
2179 rw_cfg.td1 = regk_strcop_e;
2180 rw_cfg.td2 = regk_strcop_d;
2181 rw_cfg.td3 = regk_strcop_e;
2182 break;
2183 case cryptocop_3des_edd:
2184 rw_cfg.td1 = regk_strcop_e;
2185 rw_cfg.td2 = regk_strcop_d;
2186 rw_cfg.td3 = regk_strcop_d;
2187 break;
2188 case cryptocop_3des_dee:
2189 rw_cfg.td1 = regk_strcop_d;
2190 rw_cfg.td2 = regk_strcop_e;
2191 rw_cfg.td3 = regk_strcop_e;
2192 break;
2193 case cryptocop_3des_ded:
2194 rw_cfg.td1 = regk_strcop_d;
2195 rw_cfg.td2 = regk_strcop_e;
2196 rw_cfg.td3 = regk_strcop_d;
2197 break;
2198 case cryptocop_3des_dde:
2199 rw_cfg.td1 = regk_strcop_d;
2200 rw_cfg.td2 = regk_strcop_d;
2201 rw_cfg.td3 = regk_strcop_e;
2202 break;
2203 case cryptocop_3des_ddd:
2204 rw_cfg.td1 = regk_strcop_d;
2205 rw_cfg.td2 = regk_strcop_d;
2206 rw_cfg.td3 = regk_strcop_d;
2207 break;
2208 default:
2209 DEBUG(printk("cryptocop_setup_dma_list: bad 3DES mode\n"));
2211 switch (pj->iop->csum_mode){
2212 case cryptocop_csum_le:
2213 rw_cfg.ipend = regk_strcop_little;
2214 break;
2215 case cryptocop_csum_be:
2216 rw_cfg.ipend = regk_strcop_big;
2217 break;
2218 default:
2219 DEBUG(printk("cryptocop_setup_dma_list: bad checksum mode\n"));
2221 REG_WR(strcop, regi_strcop, rw_cfg, rw_cfg);
2223 DEBUG(printk("cryptocop_start_job: starting DMA, new cryptocop_running_job=0x%p\n"
2224 "ctx_in: 0x%p, phys: 0x%p\n"
2225 "ctx_out: 0x%p, phys: 0x%p\n",
2227 &pj->iop->ctx_in, (char*)virt_to_phys(&pj->iop->ctx_in),
2228 &pj->iop->ctx_out, (char*)virt_to_phys(&pj->iop->ctx_out)));
2230 /* Start input DMA. */
2231 flush_dma_context(&pj->iop->ctx_in);
2232 DMA_START_CONTEXT(IN_DMA_INST, virt_to_phys(&pj->iop->ctx_in));
2234 /* Start output DMA. */
2235 DMA_START_CONTEXT(OUT_DMA_INST, virt_to_phys(&pj->iop->ctx_out));
2237 spin_unlock_irqrestore(&running_job_lock, running_job_flags);
2238 DEBUG(printk("cryptocop_start_job: exiting\n"));
2242 static int cryptocop_job_setup(struct cryptocop_prio_job **pj, struct cryptocop_operation *operation)
2244 int err;
2245 int alloc_flag = operation->in_interrupt ? GFP_ATOMIC : GFP_KERNEL;
2246 void *iop_alloc_ptr = NULL;
2248 *pj = kmalloc(sizeof (struct cryptocop_prio_job), alloc_flag);
2249 if (!*pj) return -ENOMEM;
2251 DEBUG(printk("cryptocop_job_setup: operation=0x%p\n", operation));
2253 (*pj)->oper = operation;
2254 DEBUG(printk("cryptocop_job_setup, cb=0x%p cb_data=0x%p\n", (*pj)->oper->cb, (*pj)->oper->cb_data));
2256 if (operation->use_dmalists) {
2257 DEBUG(print_user_dma_lists(&operation->list_op));
2258 if (!operation->list_op.inlist || !operation->list_op.outlist || !operation->list_op.out_data_buf || !operation->list_op.in_data_buf){
2259 DEBUG_API(printk("cryptocop_job_setup: bad indata (use_dmalists)\n"));
2260 kfree(*pj);
2261 return -EINVAL;
2263 iop_alloc_ptr = kmalloc(DESCR_ALLOC_PAD + sizeof(struct cryptocop_int_operation), alloc_flag);
2264 if (!iop_alloc_ptr) {
2265 DEBUG_API(printk("cryptocop_job_setup: kmalloc cryptocop_int_operation\n"));
2266 kfree(*pj);
2267 return -ENOMEM;
2269 (*pj)->iop = (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));
2270 DEBUG(memset((*pj)->iop, 0xff, sizeof(struct cryptocop_int_operation)));
2271 (*pj)->iop->alloc_ptr = iop_alloc_ptr;
2272 (*pj)->iop->sid = operation->sid;
2273 (*pj)->iop->cdesc_out = NULL;
2274 (*pj)->iop->cdesc_in = NULL;
2275 (*pj)->iop->tdes_mode = operation->list_op.tdes_mode;
2276 (*pj)->iop->csum_mode = operation->list_op.csum_mode;
2277 (*pj)->iop->ddesc_out = operation->list_op.outlist;
2278 (*pj)->iop->ddesc_in = operation->list_op.inlist;
2280 /* Setup DMA contexts. */
2281 (*pj)->iop->ctx_out.next = NULL;
2282 (*pj)->iop->ctx_out.eol = 1;
2283 (*pj)->iop->ctx_out.saved_data = operation->list_op.outlist;
2284 (*pj)->iop->ctx_out.saved_data_buf = operation->list_op.out_data_buf;
2286 (*pj)->iop->ctx_in.next = NULL;
2287 (*pj)->iop->ctx_in.eol = 1;
2288 (*pj)->iop->ctx_in.saved_data = operation->list_op.inlist;
2289 (*pj)->iop->ctx_in.saved_data_buf = operation->list_op.in_data_buf;
2290 } else {
2291 if ((err = cryptocop_setup_dma_list(operation, &(*pj)->iop, alloc_flag))) {
2292 DEBUG_API(printk("cryptocop_job_setup: cryptocop_setup_dma_list failed %d\n", err));
2293 kfree(*pj);
2294 return err;
2297 DEBUG(print_dma_descriptors((*pj)->iop));
2299 DEBUG(printk("cryptocop_job_setup, DMA list setup successful\n"));
2301 return 0;
2304 static int cryptocop_open(struct inode *inode, struct file *filp)
2306 int p = iminor(inode);
2308 if (p != CRYPTOCOP_MINOR) return -EINVAL;
2310 filp->private_data = NULL;
2311 return 0;
2315 static int cryptocop_release(struct inode *inode, struct file *filp)
2317 struct cryptocop_private *dev = filp->private_data;
2318 struct cryptocop_private *dev_next;
2320 while (dev){
2321 dev_next = dev->next;
2322 if (dev->sid != CRYPTOCOP_SESSION_ID_NONE) {
2323 (void)cryptocop_free_session(dev->sid);
2325 kfree(dev);
2326 dev = dev_next;
2329 return 0;
2333 static int cryptocop_ioctl_close_session(struct inode *inode, struct file *filp,
2334 unsigned int cmd, unsigned long arg)
2336 struct cryptocop_private *dev = filp->private_data;
2337 struct cryptocop_private *prev_dev = NULL;
2338 struct strcop_session_op *sess_op = (struct strcop_session_op *)arg;
2339 struct strcop_session_op sop;
2340 int err;
2342 DEBUG(printk("cryptocop_ioctl_close_session\n"));
2344 if (!access_ok(VERIFY_READ, sess_op, sizeof(struct strcop_session_op)))
2345 return -EFAULT;
2346 err = copy_from_user(&sop, sess_op, sizeof(struct strcop_session_op));
2347 if (err) return -EFAULT;
2349 while (dev && (dev->sid != sop.ses_id)) {
2350 prev_dev = dev;
2351 dev = dev->next;
2353 if (dev){
2354 if (prev_dev){
2355 prev_dev->next = dev->next;
2356 } else {
2357 filp->private_data = dev->next;
2359 err = cryptocop_free_session(dev->sid);
2360 if (err) return -EFAULT;
2361 } else {
2362 DEBUG_API(printk("cryptocop_ioctl_close_session: session %lld not found\n", sop.ses_id));
2363 return -EINVAL;
2365 return 0;
2369 static void ioctl_process_job_callback(struct cryptocop_operation *op, void*cb_data)
2371 struct ioctl_job_cb_ctx *jc = (struct ioctl_job_cb_ctx *)cb_data;
2373 DEBUG(printk("ioctl_process_job_callback: op=0x%p, cb_data=0x%p\n", op, cb_data));
2375 jc->processed = 1;
2376 wake_up(&cryptocop_ioc_process_wq);
2380 #define CRYPTOCOP_IOCTL_CIPHER_TID (1)
2381 #define CRYPTOCOP_IOCTL_DIGEST_TID (2)
2382 #define CRYPTOCOP_IOCTL_CSUM_TID (3)
2384 static size_t first_cfg_change_ix(struct strcop_crypto_op *crp_op)
2386 size_t ch_ix = 0;
2388 if (crp_op->do_cipher) ch_ix = crp_op->cipher_start;
2389 if (crp_op->do_digest && (crp_op->digest_start < ch_ix)) ch_ix = crp_op->digest_start;
2390 if (crp_op->do_csum && (crp_op->csum_start < ch_ix)) ch_ix = crp_op->csum_start;
2392 DEBUG(printk("first_cfg_change_ix: ix=%d\n", ch_ix));
2393 return ch_ix;
2397 static size_t next_cfg_change_ix(struct strcop_crypto_op *crp_op, size_t ix)
2399 size_t ch_ix = INT_MAX;
2400 size_t tmp_ix = 0;
2402 if (crp_op->do_cipher && ((crp_op->cipher_start + crp_op->cipher_len) > ix)){
2403 if (crp_op->cipher_start > ix) {
2404 ch_ix = crp_op->cipher_start;
2405 } else {
2406 ch_ix = crp_op->cipher_start + crp_op->cipher_len;
2409 if (crp_op->do_digest && ((crp_op->digest_start + crp_op->digest_len) > ix)){
2410 if (crp_op->digest_start > ix) {
2411 tmp_ix = crp_op->digest_start;
2412 } else {
2413 tmp_ix = crp_op->digest_start + crp_op->digest_len;
2415 if (tmp_ix < ch_ix) ch_ix = tmp_ix;
2417 if (crp_op->do_csum && ((crp_op->csum_start + crp_op->csum_len) > ix)){
2418 if (crp_op->csum_start > ix) {
2419 tmp_ix = crp_op->csum_start;
2420 } else {
2421 tmp_ix = crp_op->csum_start + crp_op->csum_len;
2423 if (tmp_ix < ch_ix) ch_ix = tmp_ix;
2425 if (ch_ix == INT_MAX) ch_ix = ix;
2426 DEBUG(printk("next_cfg_change_ix prev ix=%d, next ix=%d\n", ix, ch_ix));
2427 return ch_ix;
2431 /* Map map_length bytes from the pages starting on *pageix and *pageoffset to iovecs starting on *iovix.
2432 * Return -1 for ok, 0 for fail. */
2433 static int map_pages_to_iovec(struct iovec *iov, int iovlen, int *iovix, struct page **pages, int nopages, int *pageix, int *pageoffset, int map_length )
2435 int tmplen;
2437 assert(iov != NULL);
2438 assert(iovix != NULL);
2439 assert(pages != NULL);
2440 assert(pageix != NULL);
2441 assert(pageoffset != NULL);
2443 DEBUG(printk("map_pages_to_iovec, map_length=%d, iovlen=%d, *iovix=%d, nopages=%d, *pageix=%d, *pageoffset=%d\n", map_length, iovlen, *iovix, nopages, *pageix, *pageoffset));
2445 while (map_length > 0){
2446 DEBUG(printk("map_pages_to_iovec, map_length=%d, iovlen=%d, *iovix=%d, nopages=%d, *pageix=%d, *pageoffset=%d\n", map_length, iovlen, *iovix, nopages, *pageix, *pageoffset));
2447 if (*iovix >= iovlen){
2448 DEBUG_API(printk("map_page_to_iovec: *iovix=%d >= iovlen=%d\n", *iovix, iovlen));
2449 return 0;
2451 if (*pageix >= nopages){
2452 DEBUG_API(printk("map_page_to_iovec: *pageix=%d >= nopages=%d\n", *pageix, nopages));
2453 return 0;
2455 iov[*iovix].iov_base = (unsigned char*)page_address(pages[*pageix]) + *pageoffset;
2456 tmplen = PAGE_SIZE - *pageoffset;
2457 if (tmplen < map_length){
2458 (*pageoffset) = 0;
2459 (*pageix)++;
2460 } else {
2461 tmplen = map_length;
2462 (*pageoffset) += map_length;
2464 DEBUG(printk("mapping %d bytes from page %d (or %d) to iovec %d\n", tmplen, *pageix, *pageix-1, *iovix));
2465 iov[*iovix].iov_len = tmplen;
2466 map_length -= tmplen;
2467 (*iovix)++;
2469 DEBUG(printk("map_page_to_iovec, exit, *iovix=%d\n", *iovix));
2470 return -1;
2475 static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
2477 int i;
2478 struct cryptocop_private *dev = filp->private_data;
2479 struct strcop_crypto_op *crp_oper = (struct strcop_crypto_op *)arg;
2480 struct strcop_crypto_op oper = {0};
2481 int err = 0;
2482 struct cryptocop_operation *cop = NULL;
2484 struct ioctl_job_cb_ctx *jc = NULL;
2486 struct page **inpages = NULL;
2487 struct page **outpages = NULL;
2488 int noinpages = 0;
2489 int nooutpages = 0;
2491 struct cryptocop_desc descs[5]; /* Max 5 descriptors are needed, there are three transforms that
2492 * can get connected/disconnected on different places in the indata. */
2493 struct cryptocop_desc_cfg dcfgs[5*3];
2494 int desc_ix = 0;
2495 int dcfg_ix = 0;
2496 struct cryptocop_tfrm_cfg ciph_tcfg = {0};
2497 struct cryptocop_tfrm_cfg digest_tcfg = {0};
2498 struct cryptocop_tfrm_cfg csum_tcfg = {0};
2500 unsigned char *digest_result = NULL;
2501 int digest_length = 0;
2502 int cblocklen = 0;
2503 unsigned char csum_result[CSUM_BLOCK_LENGTH];
2504 struct cryptocop_session *sess;
2506 int iovlen = 0;
2507 int iovix = 0;
2508 int pageix = 0;
2509 int pageoffset = 0;
2511 size_t prev_ix = 0;
2512 size_t next_ix;
2514 int cipher_active, digest_active, csum_active;
2515 int end_digest, end_csum;
2516 int digest_done = 0;
2517 int cipher_done = 0;
2518 int csum_done = 0;
2520 DEBUG(printk("cryptocop_ioctl_process\n"));
2522 if (!access_ok(VERIFY_WRITE, crp_oper, sizeof(struct strcop_crypto_op))){
2523 DEBUG_API(printk("cryptocop_ioctl_process: !access_ok crp_oper!\n"));
2524 return -EFAULT;
2526 if (copy_from_user(&oper, crp_oper, sizeof(struct strcop_crypto_op))) {
2527 DEBUG_API(printk("cryptocop_ioctl_process: copy_from_user\n"));
2528 return -EFAULT;
2530 DEBUG(print_strcop_crypto_op(&oper));
2532 while (dev && dev->sid != oper.ses_id) dev = dev->next;
2533 if (!dev){
2534 DEBUG_API(printk("cryptocop_ioctl_process: session %lld not found\n", oper.ses_id));
2535 return -EINVAL;
2538 /* Check buffers. */
2539 if (((oper.indata + oper.inlen) < oper.indata) || ((oper.cipher_outdata + oper.cipher_outlen) < oper.cipher_outdata)){
2540 DEBUG_API(printk("cryptocop_ioctl_process: user buffers wrapped around, bad user!\n"));
2541 return -EINVAL;
2544 if (!access_ok(VERIFY_WRITE, oper.cipher_outdata, oper.cipher_outlen)){
2545 DEBUG_API(printk("cryptocop_ioctl_process: !access_ok out data!\n"));
2546 return -EFAULT;
2548 if (!access_ok(VERIFY_READ, oper.indata, oper.inlen)){
2549 DEBUG_API(printk("cryptocop_ioctl_process: !access_ok in data!\n"));
2550 return -EFAULT;
2553 cop = kmalloc(sizeof(struct cryptocop_operation), GFP_KERNEL);
2554 if (!cop) {
2555 DEBUG_API(printk("cryptocop_ioctl_process: kmalloc\n"));
2556 return -ENOMEM;
2558 jc = kmalloc(sizeof(struct ioctl_job_cb_ctx), GFP_KERNEL);
2559 if (!jc) {
2560 DEBUG_API(printk("cryptocop_ioctl_process: kmalloc\n"));
2561 err = -ENOMEM;
2562 goto error_cleanup;
2564 jc->processed = 0;
2566 cop->cb_data = jc;
2567 cop->cb = ioctl_process_job_callback;
2568 cop->operation_status = 0;
2569 cop->use_dmalists = 0;
2570 cop->in_interrupt = 0;
2571 cop->fast_callback = 0;
2572 cop->tfrm_op.tfrm_cfg = NULL;
2573 cop->tfrm_op.desc = NULL;
2574 cop->tfrm_op.indata = NULL;
2575 cop->tfrm_op.incount = 0;
2576 cop->tfrm_op.inlen = 0;
2577 cop->tfrm_op.outdata = NULL;
2578 cop->tfrm_op.outcount = 0;
2579 cop->tfrm_op.outlen = 0;
2581 sess = get_session(oper.ses_id);
2582 if (!sess){
2583 DEBUG_API(printk("cryptocop_ioctl_process: bad session id.\n"));
2584 kfree(cop);
2585 kfree(jc);
2586 return -EINVAL;
2589 if (oper.do_cipher) {
2590 unsigned int cipher_outlen = 0;
2591 struct cryptocop_transform_ctx *tc = get_transform_ctx(sess, CRYPTOCOP_IOCTL_CIPHER_TID);
2592 if (!tc) {
2593 DEBUG_API(printk("cryptocop_ioctl_process: no cipher transform in session.\n"));
2594 err = -EINVAL;
2595 goto error_cleanup;
2597 ciph_tcfg.tid = CRYPTOCOP_IOCTL_CIPHER_TID;
2598 ciph_tcfg.inject_ix = 0;
2599 ciph_tcfg.flags = 0;
2600 if ((oper.cipher_start < 0) || (oper.cipher_len <= 0) || (oper.cipher_start > oper.inlen) || ((oper.cipher_start + oper.cipher_len) > oper.inlen)){
2601 DEBUG_API(printk("cryptocop_ioctl_process: bad cipher length\n"));
2602 kfree(cop);
2603 kfree(jc);
2604 return -EINVAL;
2606 cblocklen = tc->init.alg == cryptocop_alg_aes ? AES_BLOCK_LENGTH : DES_BLOCK_LENGTH;
2607 if (oper.cipher_len % cblocklen) {
2608 kfree(cop);
2609 kfree(jc);
2610 DEBUG_API(printk("cryptocop_ioctl_process: cipher inlength not multiple of block length.\n"));
2611 return -EINVAL;
2613 cipher_outlen = oper.cipher_len;
2614 if (tc->init.cipher_mode == cryptocop_cipher_mode_cbc){
2615 if (oper.cipher_explicit) {
2616 ciph_tcfg.flags |= CRYPTOCOP_EXPLICIT_IV;
2617 memcpy(ciph_tcfg.iv, oper.cipher_iv, cblocklen);
2618 } else {
2619 cipher_outlen = oper.cipher_len - cblocklen;
2621 } else {
2622 if (oper.cipher_explicit){
2623 kfree(cop);
2624 kfree(jc);
2625 DEBUG_API(printk("cryptocop_ioctl_process: explicit_iv when not CBC mode\n"));
2626 return -EINVAL;
2629 if (oper.cipher_outlen != cipher_outlen) {
2630 kfree(cop);
2631 kfree(jc);
2632 DEBUG_API(printk("cryptocop_ioctl_process: cipher_outlen incorrect, should be %d not %d.\n", cipher_outlen, oper.cipher_outlen));
2633 return -EINVAL;
2636 if (oper.decrypt){
2637 ciph_tcfg.flags |= CRYPTOCOP_DECRYPT;
2638 } else {
2639 ciph_tcfg.flags |= CRYPTOCOP_ENCRYPT;
2641 ciph_tcfg.next = cop->tfrm_op.tfrm_cfg;
2642 cop->tfrm_op.tfrm_cfg = &ciph_tcfg;
2644 if (oper.do_digest){
2645 struct cryptocop_transform_ctx *tc = get_transform_ctx(sess, CRYPTOCOP_IOCTL_DIGEST_TID);
2646 if (!tc) {
2647 DEBUG_API(printk("cryptocop_ioctl_process: no digest transform in session.\n"));
2648 err = -EINVAL;
2649 goto error_cleanup;
2651 digest_length = tc->init.alg == cryptocop_alg_md5 ? 16 : 20;
2652 digest_result = kmalloc(digest_length, GFP_KERNEL);
2653 if (!digest_result) {
2654 DEBUG_API(printk("cryptocop_ioctl_process: kmalloc digest_result\n"));
2655 err = -EINVAL;
2656 goto error_cleanup;
2658 DEBUG(memset(digest_result, 0xff, digest_length));
2660 digest_tcfg.tid = CRYPTOCOP_IOCTL_DIGEST_TID;
2661 digest_tcfg.inject_ix = 0;
2662 ciph_tcfg.inject_ix += digest_length;
2663 if ((oper.digest_start < 0) || (oper.digest_len <= 0) || (oper.digest_start > oper.inlen) || ((oper.digest_start + oper.digest_len) > oper.inlen)){
2664 DEBUG_API(printk("cryptocop_ioctl_process: bad digest length\n"));
2665 err = -EINVAL;
2666 goto error_cleanup;
2669 digest_tcfg.next = cop->tfrm_op.tfrm_cfg;
2670 cop->tfrm_op.tfrm_cfg = &digest_tcfg;
2672 if (oper.do_csum){
2673 csum_tcfg.tid = CRYPTOCOP_IOCTL_CSUM_TID;
2674 csum_tcfg.inject_ix = digest_length;
2675 ciph_tcfg.inject_ix += 2;
2677 if ((oper.csum_start < 0) || (oper.csum_len <= 0) || (oper.csum_start > oper.inlen) || ((oper.csum_start + oper.csum_len) > oper.inlen)){
2678 DEBUG_API(printk("cryptocop_ioctl_process: bad csum length\n"));
2679 kfree(cop);
2680 kfree(jc);
2681 return -EINVAL;
2684 csum_tcfg.next = cop->tfrm_op.tfrm_cfg;
2685 cop->tfrm_op.tfrm_cfg = &csum_tcfg;
2688 prev_ix = first_cfg_change_ix(&oper);
2689 if (prev_ix > oper.inlen) {
2690 DEBUG_API(printk("cryptocop_ioctl_process: length mismatch\n"));
2691 nooutpages = noinpages = 0;
2692 err = -EINVAL;
2693 goto error_cleanup;
2695 DEBUG(printk("cryptocop_ioctl_process: inlen=%d, cipher_outlen=%d\n", oper.inlen, oper.cipher_outlen));
2697 /* Map user pages for in and out data of the operation. */
2698 noinpages = (((unsigned long int)(oper.indata + prev_ix) & ~PAGE_MASK) + oper.inlen - 1 - prev_ix + ~PAGE_MASK) >> PAGE_SHIFT;
2699 DEBUG(printk("cryptocop_ioctl_process: noinpages=%d\n", noinpages));
2700 inpages = kmalloc(noinpages * sizeof(struct page*), GFP_KERNEL);
2701 if (!inpages){
2702 DEBUG_API(printk("cryptocop_ioctl_process: kmalloc inpages\n"));
2703 nooutpages = noinpages = 0;
2704 err = -ENOMEM;
2705 goto error_cleanup;
2707 if (oper.do_cipher){
2708 nooutpages = (((unsigned long int)oper.cipher_outdata & ~PAGE_MASK) + oper.cipher_outlen - 1 + ~PAGE_MASK) >> PAGE_SHIFT;
2709 DEBUG(printk("cryptocop_ioctl_process: nooutpages=%d\n", nooutpages));
2710 outpages = kmalloc(nooutpages * sizeof(struct page*), GFP_KERNEL);
2711 if (!outpages){
2712 DEBUG_API(printk("cryptocop_ioctl_process: kmalloc outpages\n"));
2713 nooutpages = noinpages = 0;
2714 err = -ENOMEM;
2715 goto error_cleanup;
2719 /* Acquire the mm page semaphore. */
2720 down_read(&current->mm->mmap_sem);
2722 err = get_user_pages((unsigned long int)(oper.indata + prev_ix),
2723 noinpages,
2724 0, /* read access only for in data */
2725 0, /* no force */
2726 inpages,
2727 NULL);
2729 if (err < 0) {
2730 up_read(&current->mm->mmap_sem);
2731 nooutpages = noinpages = 0;
2732 DEBUG_API(printk("cryptocop_ioctl_process: get_user_pages indata\n"));
2733 goto error_cleanup;
2735 noinpages = err;
2736 if (oper.do_cipher){
2737 err = get_user_pages((unsigned long int)oper.cipher_outdata,
2738 nooutpages,
2739 1, /* write access for out data */
2740 0, /* no force */
2741 outpages,
2742 NULL);
2743 up_read(&current->mm->mmap_sem);
2744 if (err < 0) {
2745 nooutpages = 0;
2746 DEBUG_API(printk("cryptocop_ioctl_process: get_user_pages outdata\n"));
2747 goto error_cleanup;
2749 nooutpages = err;
2750 } else {
2751 up_read(&current->mm->mmap_sem);
2754 /* Add 6 to nooutpages to make room for possibly inserted buffers for storing digest and
2755 * csum output and splits when units are (dis-)connected. */
2756 cop->tfrm_op.indata = kmalloc((noinpages) * sizeof(struct iovec), GFP_KERNEL);
2757 cop->tfrm_op.outdata = kmalloc((6 + nooutpages) * sizeof(struct iovec), GFP_KERNEL);
2758 if (!cop->tfrm_op.indata || !cop->tfrm_op.outdata) {
2759 DEBUG_API(printk("cryptocop_ioctl_process: kmalloc iovecs\n"));
2760 err = -ENOMEM;
2761 goto error_cleanup;
2764 cop->tfrm_op.inlen = oper.inlen - prev_ix;
2765 cop->tfrm_op.outlen = 0;
2766 if (oper.do_cipher) cop->tfrm_op.outlen += oper.cipher_outlen;
2767 if (oper.do_digest) cop->tfrm_op.outlen += digest_length;
2768 if (oper.do_csum) cop->tfrm_op.outlen += 2;
2770 /* Setup the in iovecs. */
2771 cop->tfrm_op.incount = noinpages;
2772 if (noinpages > 1){
2773 size_t tmplen = cop->tfrm_op.inlen;
2775 cop->tfrm_op.indata[0].iov_len = PAGE_SIZE - ((unsigned long int)(oper.indata + prev_ix) & ~PAGE_MASK);
2776 cop->tfrm_op.indata[0].iov_base = (unsigned char*)page_address(inpages[0]) + ((unsigned long int)(oper.indata + prev_ix) & ~PAGE_MASK);
2777 tmplen -= cop->tfrm_op.indata[0].iov_len;
2778 for (i = 1; i<noinpages; i++){
2779 cop->tfrm_op.indata[i].iov_len = tmplen < PAGE_SIZE ? tmplen : PAGE_SIZE;
2780 cop->tfrm_op.indata[i].iov_base = (unsigned char*)page_address(inpages[i]);
2781 tmplen -= PAGE_SIZE;
2783 } else {
2784 cop->tfrm_op.indata[0].iov_len = oper.inlen - prev_ix;
2785 cop->tfrm_op.indata[0].iov_base = (unsigned char*)page_address(inpages[0]) + ((unsigned long int)(oper.indata + prev_ix) & ~PAGE_MASK);
2788 iovlen = nooutpages + 6;
2789 pageoffset = oper.do_cipher ? ((unsigned long int)oper.cipher_outdata & ~PAGE_MASK) : 0;
2791 next_ix = next_cfg_change_ix(&oper, prev_ix);
2792 if (prev_ix == next_ix){
2793 DEBUG_API(printk("cryptocop_ioctl_process: length configuration broken.\n"));
2794 err = -EINVAL; /* This should be impossible barring bugs. */
2795 goto error_cleanup;
2797 while (prev_ix != next_ix){
2798 end_digest = end_csum = cipher_active = digest_active = csum_active = 0;
2799 descs[desc_ix].cfg = NULL;
2800 descs[desc_ix].length = next_ix - prev_ix;
2802 if (oper.do_cipher && (oper.cipher_start < next_ix) && (prev_ix < (oper.cipher_start + oper.cipher_len))) {
2803 dcfgs[dcfg_ix].tid = CRYPTOCOP_IOCTL_CIPHER_TID;
2804 dcfgs[dcfg_ix].src = cryptocop_source_dma;
2805 cipher_active = 1;
2807 if (next_ix == (oper.cipher_start + oper.cipher_len)){
2808 cipher_done = 1;
2809 dcfgs[dcfg_ix].last = 1;
2810 } else {
2811 dcfgs[dcfg_ix].last = 0;
2813 dcfgs[dcfg_ix].next = descs[desc_ix].cfg;
2814 descs[desc_ix].cfg = &dcfgs[dcfg_ix];
2815 ++dcfg_ix;
2817 if (oper.do_digest && (oper.digest_start < next_ix) && (prev_ix < (oper.digest_start + oper.digest_len))) {
2818 digest_active = 1;
2819 dcfgs[dcfg_ix].tid = CRYPTOCOP_IOCTL_DIGEST_TID;
2820 dcfgs[dcfg_ix].src = cryptocop_source_dma;
2821 if (next_ix == (oper.digest_start + oper.digest_len)){
2822 assert(!digest_done);
2823 digest_done = 1;
2824 dcfgs[dcfg_ix].last = 1;
2825 } else {
2826 dcfgs[dcfg_ix].last = 0;
2828 dcfgs[dcfg_ix].next = descs[desc_ix].cfg;
2829 descs[desc_ix].cfg = &dcfgs[dcfg_ix];
2830 ++dcfg_ix;
2832 if (oper.do_csum && (oper.csum_start < next_ix) && (prev_ix < (oper.csum_start + oper.csum_len))){
2833 csum_active = 1;
2834 dcfgs[dcfg_ix].tid = CRYPTOCOP_IOCTL_CSUM_TID;
2835 dcfgs[dcfg_ix].src = cryptocop_source_dma;
2836 if (next_ix == (oper.csum_start + oper.csum_len)){
2837 csum_done = 1;
2838 dcfgs[dcfg_ix].last = 1;
2839 } else {
2840 dcfgs[dcfg_ix].last = 0;
2842 dcfgs[dcfg_ix].next = descs[desc_ix].cfg;
2843 descs[desc_ix].cfg = &dcfgs[dcfg_ix];
2844 ++dcfg_ix;
2846 if (!descs[desc_ix].cfg){
2847 DEBUG_API(printk("cryptocop_ioctl_process: data segment %d (%d to %d) had no active transforms\n", desc_ix, prev_ix, next_ix));
2848 err = -EINVAL;
2849 goto error_cleanup;
2851 descs[desc_ix].next = &(descs[desc_ix]) + 1;
2852 ++desc_ix;
2853 prev_ix = next_ix;
2854 next_ix = next_cfg_change_ix(&oper, prev_ix);
2856 if (desc_ix > 0){
2857 descs[desc_ix-1].next = NULL;
2858 } else {
2859 descs[0].next = NULL;
2861 if (oper.do_digest) {
2862 DEBUG(printk("cryptocop_ioctl_process: mapping %d byte digest output to iovec %d\n", digest_length, iovix));
2863 /* Add outdata iovec, length == <length of type of digest> */
2864 cop->tfrm_op.outdata[iovix].iov_base = digest_result;
2865 cop->tfrm_op.outdata[iovix].iov_len = digest_length;
2866 ++iovix;
2868 if (oper.do_csum) {
2869 /* Add outdata iovec, length == 2, the length of csum. */
2870 DEBUG(printk("cryptocop_ioctl_process: mapping 2 byte csum output to iovec %d\n", iovix));
2871 /* Add outdata iovec, length == <length of type of digest> */
2872 cop->tfrm_op.outdata[iovix].iov_base = csum_result;
2873 cop->tfrm_op.outdata[iovix].iov_len = 2;
2874 ++iovix;
2876 if (oper.do_cipher) {
2877 if (!map_pages_to_iovec(cop->tfrm_op.outdata, iovlen, &iovix, outpages, nooutpages, &pageix, &pageoffset, oper.cipher_outlen)){
2878 DEBUG_API(printk("cryptocop_ioctl_process: failed to map pages to iovec.\n"));
2879 err = -ENOSYS; /* This should be impossible barring bugs. */
2880 goto error_cleanup;
2883 DEBUG(printk("cryptocop_ioctl_process: setting cop->tfrm_op.outcount %d\n", iovix));
2884 cop->tfrm_op.outcount = iovix;
2885 assert(iovix <= (nooutpages + 6));
2887 cop->sid = oper.ses_id;
2888 cop->tfrm_op.desc = &descs[0];
2890 DEBUG(printk("cryptocop_ioctl_process: inserting job, cb_data=0x%p\n", cop->cb_data));
2892 if ((err = cryptocop_job_queue_insert_user_job(cop)) != 0) {
2893 DEBUG_API(printk("cryptocop_ioctl_process: insert job %d\n", err));
2894 err = -EINVAL;
2895 goto error_cleanup;
2898 DEBUG(printk("cryptocop_ioctl_process: begin wait for result\n"));
2900 wait_event(cryptocop_ioc_process_wq, (jc->processed != 0));
2901 DEBUG(printk("cryptocop_ioctl_process: end wait for result\n"));
2902 if (!jc->processed){
2903 printk(KERN_WARNING "cryptocop_ioctl_process: job not processed at completion\n");
2904 err = -EIO;
2905 goto error_cleanup;
2908 /* Job process done. Cipher output should already be correct in job so no post processing of outdata. */
2909 DEBUG(printk("cryptocop_ioctl_process: operation_status = %d\n", cop->operation_status));
2910 if (cop->operation_status == 0){
2911 if (oper.do_digest){
2912 DEBUG(printk("cryptocop_ioctl_process: copy %d bytes digest to user\n", digest_length));
2913 err = copy_to_user((unsigned char*)crp_oper + offsetof(struct strcop_crypto_op, digest), digest_result, digest_length);
2914 if (0 != err){
2915 DEBUG_API(printk("cryptocop_ioctl_process: copy_to_user, digest length %d, err %d\n", digest_length, err));
2916 err = -EFAULT;
2917 goto error_cleanup;
2920 if (oper.do_csum){
2921 DEBUG(printk("cryptocop_ioctl_process: copy 2 bytes checksum to user\n"));
2922 err = copy_to_user((unsigned char*)crp_oper + offsetof(struct strcop_crypto_op, csum), csum_result, 2);
2923 if (0 != err){
2924 DEBUG_API(printk("cryptocop_ioctl_process: copy_to_user, csum, err %d\n", err));
2925 err = -EFAULT;
2926 goto error_cleanup;
2929 err = 0;
2930 } else {
2931 DEBUG(printk("cryptocop_ioctl_process: returning err = operation_status = %d\n", cop->operation_status));
2932 err = cop->operation_status;
2935 error_cleanup:
2936 /* Release page caches. */
2937 for (i = 0; i < noinpages; i++){
2938 put_page(inpages[i]);
2940 for (i = 0; i < nooutpages; i++){
2941 int spdl_err;
2942 /* Mark output pages dirty. */
2943 spdl_err = set_page_dirty_lock(outpages[i]);
2944 DEBUG(if (spdl_err < 0)printk("cryptocop_ioctl_process: set_page_dirty_lock returned %d\n", spdl_err));
2946 for (i = 0; i < nooutpages; i++){
2947 put_page(outpages[i]);
2950 kfree(digest_result);
2951 kfree(inpages);
2952 kfree(outpages);
2953 if (cop){
2954 kfree(cop->tfrm_op.indata);
2955 kfree(cop->tfrm_op.outdata);
2956 kfree(cop);
2958 kfree(jc);
2960 DEBUG(print_lock_status());
2962 return err;
2966 static int cryptocop_ioctl_create_session(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
2968 cryptocop_session_id sid;
2969 int err;
2970 struct cryptocop_private *dev;
2971 struct strcop_session_op *sess_op = (struct strcop_session_op *)arg;
2972 struct strcop_session_op sop;
2973 struct cryptocop_transform_init *tis = NULL;
2974 struct cryptocop_transform_init ti_cipher = {0};
2975 struct cryptocop_transform_init ti_digest = {0};
2976 struct cryptocop_transform_init ti_csum = {0};
2978 if (!access_ok(VERIFY_WRITE, sess_op, sizeof(struct strcop_session_op)))
2979 return -EFAULT;
2980 err = copy_from_user(&sop, sess_op, sizeof(struct strcop_session_op));
2981 if (err) return -EFAULT;
2982 if (sop.cipher != cryptocop_cipher_none) {
2983 if (!access_ok(VERIFY_READ, sop.key, sop.keylen)) return -EFAULT;
2985 DEBUG(printk("cryptocop_ioctl_create_session, sess_op:\n"));
2987 DEBUG(printk("\tcipher:%d\n"
2988 "\tcipher_mode:%d\n"
2989 "\tdigest:%d\n"
2990 "\tcsum:%d\n",
2991 (int)sop.cipher,
2992 (int)sop.cmode,
2993 (int)sop.digest,
2994 (int)sop.csum));
2996 if (sop.cipher != cryptocop_cipher_none){
2997 /* Init the cipher. */
2998 switch (sop.cipher){
2999 case cryptocop_cipher_des:
3000 ti_cipher.alg = cryptocop_alg_des;
3001 break;
3002 case cryptocop_cipher_3des:
3003 ti_cipher.alg = cryptocop_alg_3des;
3004 break;
3005 case cryptocop_cipher_aes:
3006 ti_cipher.alg = cryptocop_alg_aes;
3007 break;
3008 default:
3009 DEBUG_API(printk("create session, bad cipher algorithm %d\n", sop.cipher));
3010 return -EINVAL;
3012 DEBUG(printk("setting cipher transform %d\n", ti_cipher.alg));
3013 copy_from_user(ti_cipher.key, sop.key, sop.keylen/8);
3014 ti_cipher.keylen = sop.keylen;
3015 switch (sop.cmode){
3016 case cryptocop_cipher_mode_cbc:
3017 case cryptocop_cipher_mode_ecb:
3018 ti_cipher.cipher_mode = sop.cmode;
3019 break;
3020 default:
3021 DEBUG_API(printk("create session, bad cipher mode %d\n", sop.cmode));
3022 return -EINVAL;
3024 DEBUG(printk("cryptocop_ioctl_create_session: setting CBC mode %d\n", ti_cipher.cipher_mode));
3025 switch (sop.des3_mode){
3026 case cryptocop_3des_eee:
3027 case cryptocop_3des_eed:
3028 case cryptocop_3des_ede:
3029 case cryptocop_3des_edd:
3030 case cryptocop_3des_dee:
3031 case cryptocop_3des_ded:
3032 case cryptocop_3des_dde:
3033 case cryptocop_3des_ddd:
3034 ti_cipher.tdes_mode = sop.des3_mode;
3035 break;
3036 default:
3037 DEBUG_API(printk("create session, bad 3DES mode %d\n", sop.des3_mode));
3038 return -EINVAL;
3040 ti_cipher.tid = CRYPTOCOP_IOCTL_CIPHER_TID;
3041 ti_cipher.next = tis;
3042 tis = &ti_cipher;
3043 } /* if (sop.cipher != cryptocop_cipher_none) */
3044 if (sop.digest != cryptocop_digest_none){
3045 DEBUG(printk("setting digest transform\n"));
3046 switch (sop.digest){
3047 case cryptocop_digest_md5:
3048 ti_digest.alg = cryptocop_alg_md5;
3049 break;
3050 case cryptocop_digest_sha1:
3051 ti_digest.alg = cryptocop_alg_sha1;
3052 break;
3053 default:
3054 DEBUG_API(printk("create session, bad digest algorithm %d\n", sop.digest));
3055 return -EINVAL;
3057 ti_digest.tid = CRYPTOCOP_IOCTL_DIGEST_TID;
3058 ti_digest.next = tis;
3059 tis = &ti_digest;
3060 } /* if (sop.digest != cryptocop_digest_none) */
3061 if (sop.csum != cryptocop_csum_none){
3062 DEBUG(printk("setting csum transform\n"));
3063 switch (sop.csum){
3064 case cryptocop_csum_le:
3065 case cryptocop_csum_be:
3066 ti_csum.csum_mode = sop.csum;
3067 break;
3068 default:
3069 DEBUG_API(printk("create session, bad checksum algorithm %d\n", sop.csum));
3070 return -EINVAL;
3072 ti_csum.alg = cryptocop_alg_csum;
3073 ti_csum.tid = CRYPTOCOP_IOCTL_CSUM_TID;
3074 ti_csum.next = tis;
3075 tis = &ti_csum;
3076 } /* (sop.csum != cryptocop_csum_none) */
3077 dev = kmalloc(sizeof(struct cryptocop_private), GFP_KERNEL);
3078 if (!dev){
3079 DEBUG_API(printk("create session, alloc dev\n"));
3080 return -ENOMEM;
3083 err = cryptocop_new_session(&sid, tis, GFP_KERNEL);
3084 DEBUG({ if (err) printk("create session, cryptocop_new_session %d\n", err);});
3086 if (err) {
3087 kfree(dev);
3088 return err;
3090 sess_op->ses_id = sid;
3091 dev->sid = sid;
3092 dev->next = filp->private_data;
3093 filp->private_data = dev;
3095 return 0;
3098 static long cryptocop_ioctl_unlocked(struct inode *inode,
3099 struct file *filp, unsigned int cmd, unsigned long arg)
3101 int err = 0;
3102 if (_IOC_TYPE(cmd) != ETRAXCRYPTOCOP_IOCTYPE) {
3103 DEBUG_API(printk("cryptocop_ioctl: wrong type\n"));
3104 return -ENOTTY;
3106 if (_IOC_NR(cmd) > CRYPTOCOP_IO_MAXNR){
3107 return -ENOTTY;
3109 /* Access check of the argument. Some commands, e.g. create session and process op,
3110 needs additional checks. Those are handled in the command handling functions. */
3111 if (_IOC_DIR(cmd) & _IOC_READ)
3112 err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
3113 else if (_IOC_DIR(cmd) & _IOC_WRITE)
3114 err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
3115 if (err) return -EFAULT;
3117 switch (cmd) {
3118 case CRYPTOCOP_IO_CREATE_SESSION:
3119 return cryptocop_ioctl_create_session(inode, filp, cmd, arg);
3120 case CRYPTOCOP_IO_CLOSE_SESSION:
3121 return cryptocop_ioctl_close_session(inode, filp, cmd, arg);
3122 case CRYPTOCOP_IO_PROCESS_OP:
3123 return cryptocop_ioctl_process(inode, filp, cmd, arg);
3124 default:
3125 DEBUG_API(printk("cryptocop_ioctl: unknown command\n"));
3126 return -ENOTTY;
3128 return 0;
3131 static long
3132 cryptocop_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
3134 long ret;
3136 mutex_lock(&cryptocop_mutex);
3137 ret = cryptocop_ioctl_unlocked(file_inode(filp), filp, cmd, arg);
3138 mutex_unlock(&cryptocop_mutex);
3140 return ret;
3144 #ifdef LDEBUG
3145 static void print_dma_descriptors(struct cryptocop_int_operation *iop)
3147 struct cryptocop_dma_desc *cdesc_out = iop->cdesc_out;
3148 struct cryptocop_dma_desc *cdesc_in = iop->cdesc_in;
3149 int i;
3151 printk("print_dma_descriptors start\n");
3153 printk("iop:\n");
3154 printk("\tsid: 0x%lld\n", iop->sid);
3156 printk("\tcdesc_out: 0x%p\n", iop->cdesc_out);
3157 printk("\tcdesc_in: 0x%p\n", iop->cdesc_in);
3158 printk("\tddesc_out: 0x%p\n", iop->ddesc_out);
3159 printk("\tddesc_in: 0x%p\n", iop->ddesc_in);
3161 printk("\niop->ctx_out: 0x%p phys: 0x%p\n", &iop->ctx_out, (char*)virt_to_phys(&iop->ctx_out));
3162 printk("\tnext: 0x%p\n"
3163 "\tsaved_data: 0x%p\n"
3164 "\tsaved_data_buf: 0x%p\n",
3165 iop->ctx_out.next,
3166 iop->ctx_out.saved_data,
3167 iop->ctx_out.saved_data_buf);
3169 printk("\niop->ctx_in: 0x%p phys: 0x%p\n", &iop->ctx_in, (char*)virt_to_phys(&iop->ctx_in));
3170 printk("\tnext: 0x%p\n"
3171 "\tsaved_data: 0x%p\n"
3172 "\tsaved_data_buf: 0x%p\n",
3173 iop->ctx_in.next,
3174 iop->ctx_in.saved_data,
3175 iop->ctx_in.saved_data_buf);
3177 i = 0;
3178 while (cdesc_out) {
3179 dma_descr_data *td;
3180 printk("cdesc_out %d, desc=0x%p\n", i, cdesc_out->dma_descr);
3181 printk("\n\tvirt_to_phys(desc): 0x%p\n", (char*)virt_to_phys(cdesc_out->dma_descr));
3182 td = cdesc_out->dma_descr;
3183 printk("\n\tbuf: 0x%p\n"
3184 "\tafter: 0x%p\n"
3185 "\tmd: 0x%04x\n"
3186 "\tnext: 0x%p\n",
3187 td->buf,
3188 td->after,
3189 td->md,
3190 td->next);
3191 printk("flags:\n"
3192 "\twait:\t%d\n"
3193 "\teol:\t%d\n"
3194 "\touteop:\t%d\n"
3195 "\tineop:\t%d\n"
3196 "\tintr:\t%d\n",
3197 td->wait,
3198 td->eol,
3199 td->out_eop,
3200 td->in_eop,
3201 td->intr);
3202 cdesc_out = cdesc_out->next;
3203 i++;
3205 i = 0;
3206 while (cdesc_in) {
3207 dma_descr_data *td;
3208 printk("cdesc_in %d, desc=0x%p\n", i, cdesc_in->dma_descr);
3209 printk("\n\tvirt_to_phys(desc): 0x%p\n", (char*)virt_to_phys(cdesc_in->dma_descr));
3210 td = cdesc_in->dma_descr;
3211 printk("\n\tbuf: 0x%p\n"
3212 "\tafter: 0x%p\n"
3213 "\tmd: 0x%04x\n"
3214 "\tnext: 0x%p\n",
3215 td->buf,
3216 td->after,
3217 td->md,
3218 td->next);
3219 printk("flags:\n"
3220 "\twait:\t%d\n"
3221 "\teol:\t%d\n"
3222 "\touteop:\t%d\n"
3223 "\tineop:\t%d\n"
3224 "\tintr:\t%d\n",
3225 td->wait,
3226 td->eol,
3227 td->out_eop,
3228 td->in_eop,
3229 td->intr);
3230 cdesc_in = cdesc_in->next;
3231 i++;
3234 printk("print_dma_descriptors end\n");
3238 static void print_strcop_crypto_op(struct strcop_crypto_op *cop)
3240 printk("print_strcop_crypto_op, 0x%p\n", cop);
3242 /* Indata. */
3243 printk("indata=0x%p\n"
3244 "inlen=%d\n"
3245 "do_cipher=%d\n"
3246 "decrypt=%d\n"
3247 "cipher_explicit=%d\n"
3248 "cipher_start=%d\n"
3249 "cipher_len=%d\n"
3250 "outdata=0x%p\n"
3251 "outlen=%d\n",
3252 cop->indata,
3253 cop->inlen,
3254 cop->do_cipher,
3255 cop->decrypt,
3256 cop->cipher_explicit,
3257 cop->cipher_start,
3258 cop->cipher_len,
3259 cop->cipher_outdata,
3260 cop->cipher_outlen);
3262 printk("do_digest=%d\n"
3263 "digest_start=%d\n"
3264 "digest_len=%d\n",
3265 cop->do_digest,
3266 cop->digest_start,
3267 cop->digest_len);
3269 printk("do_csum=%d\n"
3270 "csum_start=%d\n"
3271 "csum_len=%d\n",
3272 cop->do_csum,
3273 cop->csum_start,
3274 cop->csum_len);
3277 static void print_cryptocop_operation(struct cryptocop_operation *cop)
3279 struct cryptocop_desc *d;
3280 struct cryptocop_tfrm_cfg *tc;
3281 struct cryptocop_desc_cfg *dc;
3282 int i;
3284 printk("print_cryptocop_operation, cop=0x%p\n\n", cop);
3285 printk("sid: %lld\n", cop->sid);
3286 printk("operation_status=%d\n"
3287 "use_dmalists=%d\n"
3288 "in_interrupt=%d\n"
3289 "fast_callback=%d\n",
3290 cop->operation_status,
3291 cop->use_dmalists,
3292 cop->in_interrupt,
3293 cop->fast_callback);
3295 if (cop->use_dmalists){
3296 print_user_dma_lists(&cop->list_op);
3297 } else {
3298 printk("cop->tfrm_op\n"
3299 "tfrm_cfg=0x%p\n"
3300 "desc=0x%p\n"
3301 "indata=0x%p\n"
3302 "incount=%d\n"
3303 "inlen=%d\n"
3304 "outdata=0x%p\n"
3305 "outcount=%d\n"
3306 "outlen=%d\n\n",
3307 cop->tfrm_op.tfrm_cfg,
3308 cop->tfrm_op.desc,
3309 cop->tfrm_op.indata,
3310 cop->tfrm_op.incount,
3311 cop->tfrm_op.inlen,
3312 cop->tfrm_op.outdata,
3313 cop->tfrm_op.outcount,
3314 cop->tfrm_op.outlen);
3316 tc = cop->tfrm_op.tfrm_cfg;
3317 while (tc){
3318 printk("tfrm_cfg, 0x%p\n"
3319 "tid=%d\n"
3320 "flags=%d\n"
3321 "inject_ix=%d\n"
3322 "next=0x%p\n",
3324 tc->tid,
3325 tc->flags,
3326 tc->inject_ix,
3327 tc->next);
3328 tc = tc->next;
3330 d = cop->tfrm_op.desc;
3331 while (d){
3332 printk("\n======================desc, 0x%p\n"
3333 "length=%d\n"
3334 "cfg=0x%p\n"
3335 "next=0x%p\n",
3337 d->length,
3338 d->cfg,
3339 d->next);
3340 dc = d->cfg;
3341 while (dc){
3342 printk("=========desc_cfg, 0x%p\n"
3343 "tid=%d\n"
3344 "src=%d\n"
3345 "last=%d\n"
3346 "next=0x%p\n",
3348 dc->tid,
3349 dc->src,
3350 dc->last,
3351 dc->next);
3352 dc = dc->next;
3354 d = d->next;
3356 printk("\n====iniov\n");
3357 for (i = 0; i < cop->tfrm_op.incount; i++){
3358 printk("indata[%d]\n"
3359 "base=0x%p\n"
3360 "len=%d\n",
3362 cop->tfrm_op.indata[i].iov_base,
3363 cop->tfrm_op.indata[i].iov_len);
3365 printk("\n====outiov\n");
3366 for (i = 0; i < cop->tfrm_op.outcount; i++){
3367 printk("outdata[%d]\n"
3368 "base=0x%p\n"
3369 "len=%d\n",
3371 cop->tfrm_op.outdata[i].iov_base,
3372 cop->tfrm_op.outdata[i].iov_len);
3375 printk("------------end print_cryptocop_operation\n");
3379 static void print_user_dma_lists(struct cryptocop_dma_list_operation *dma_op)
3381 dma_descr_data *dd;
3382 int i;
3384 printk("print_user_dma_lists, dma_op=0x%p\n", dma_op);
3386 printk("out_data_buf = 0x%p, phys_to_virt(out_data_buf) = 0x%p\n", dma_op->out_data_buf, phys_to_virt((unsigned long int)dma_op->out_data_buf));
3387 printk("in_data_buf = 0x%p, phys_to_virt(in_data_buf) = 0x%p\n", dma_op->in_data_buf, phys_to_virt((unsigned long int)dma_op->in_data_buf));
3389 printk("##############outlist\n");
3390 dd = phys_to_virt((unsigned long int)dma_op->outlist);
3391 i = 0;
3392 while (dd != NULL) {
3393 printk("#%d phys_to_virt(desc) 0x%p\n", i, dd);
3394 printk("\n\tbuf: 0x%p\n"
3395 "\tafter: 0x%p\n"
3396 "\tmd: 0x%04x\n"
3397 "\tnext: 0x%p\n",
3398 dd->buf,
3399 dd->after,
3400 dd->md,
3401 dd->next);
3402 printk("flags:\n"
3403 "\twait:\t%d\n"
3404 "\teol:\t%d\n"
3405 "\touteop:\t%d\n"
3406 "\tineop:\t%d\n"
3407 "\tintr:\t%d\n",
3408 dd->wait,
3409 dd->eol,
3410 dd->out_eop,
3411 dd->in_eop,
3412 dd->intr);
3413 if (dd->eol)
3414 dd = NULL;
3415 else
3416 dd = phys_to_virt((unsigned long int)dd->next);
3417 ++i;
3420 printk("##############inlist\n");
3421 dd = phys_to_virt((unsigned long int)dma_op->inlist);
3422 i = 0;
3423 while (dd != NULL) {
3424 printk("#%d phys_to_virt(desc) 0x%p\n", i, dd);
3425 printk("\n\tbuf: 0x%p\n"
3426 "\tafter: 0x%p\n"
3427 "\tmd: 0x%04x\n"
3428 "\tnext: 0x%p\n",
3429 dd->buf,
3430 dd->after,
3431 dd->md,
3432 dd->next);
3433 printk("flags:\n"
3434 "\twait:\t%d\n"
3435 "\teol:\t%d\n"
3436 "\touteop:\t%d\n"
3437 "\tineop:\t%d\n"
3438 "\tintr:\t%d\n",
3439 dd->wait,
3440 dd->eol,
3441 dd->out_eop,
3442 dd->in_eop,
3443 dd->intr);
3444 if (dd->eol)
3445 dd = NULL;
3446 else
3447 dd = phys_to_virt((unsigned long int)dd->next);
3448 ++i;
3453 static void print_lock_status(void)
3455 printk("**********************print_lock_status\n");
3456 printk("cryptocop_completed_jobs_lock %d\n", spin_is_locked(&cryptocop_completed_jobs_lock));
3457 printk("cryptocop_job_queue_lock %d\n", spin_is_locked(&cryptocop_job_queue_lock));
3458 printk("descr_pool_lock %d\n", spin_is_locked(&descr_pool_lock));
3459 printk("cryptocop_sessions_lock %d\n", spin_is_locked(cryptocop_sessions_lock));
3460 printk("running_job_lock %d\n", spin_is_locked(running_job_lock));
3461 printk("cryptocop_process_lock %d\n", spin_is_locked(cryptocop_process_lock));
3463 #endif /* LDEBUG */
3466 static const char cryptocop_name[] = "ETRAX FS stream co-processor";
3468 static int init_stream_coprocessor(void)
3470 int err;
3471 int i;
3472 static int initialized = 0;
3474 if (initialized)
3475 return 0;
3477 initialized = 1;
3479 printk("ETRAX FS stream co-processor driver v0.01, (c) 2003 Axis Communications AB\n");
3481 err = register_chrdev(CRYPTOCOP_MAJOR, cryptocop_name, &cryptocop_fops);
3482 if (err < 0) {
3483 printk(KERN_ERR "stream co-processor: could not get major number.\n");
3484 return err;
3487 err = init_cryptocop();
3488 if (err) {
3489 (void)unregister_chrdev(CRYPTOCOP_MAJOR, cryptocop_name);
3490 return err;
3492 err = cryptocop_job_queue_init();
3493 if (err) {
3494 release_cryptocop();
3495 (void)unregister_chrdev(CRYPTOCOP_MAJOR, cryptocop_name);
3496 return err;
3498 /* Init the descriptor pool. */
3499 for (i = 0; i < CRYPTOCOP_DESCRIPTOR_POOL_SIZE - 1; i++) {
3500 descr_pool[i].from_pool = 1;
3501 descr_pool[i].next = &descr_pool[i + 1];
3503 descr_pool[i].from_pool = 1;
3504 descr_pool[i].next = NULL;
3505 descr_pool_free_list = &descr_pool[0];
3506 descr_pool_no_free = CRYPTOCOP_DESCRIPTOR_POOL_SIZE;
3508 spin_lock_init(&cryptocop_completed_jobs_lock);
3509 spin_lock_init(&cryptocop_job_queue_lock);
3510 spin_lock_init(&descr_pool_lock);
3511 spin_lock_init(&cryptocop_sessions_lock);
3512 spin_lock_init(&running_job_lock);
3513 spin_lock_init(&cryptocop_process_lock);
3515 cryptocop_sessions = NULL;
3516 next_sid = 1;
3518 cryptocop_running_job = NULL;
3520 printk("stream co-processor: init done.\n");
3521 return 0;
3524 static void __exit exit_stream_coprocessor(void)
3526 release_cryptocop();
3527 cryptocop_job_queue_close();
3530 module_init(init_stream_coprocessor);
3531 module_exit(exit_stream_coprocessor);