1
2
3
4
5
6
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>
16
17#include <asm/uaccess.h>
18#include <asm/io.h>
19#include <linux/atomic.h>
20
21#include <linux/list.h>
22#include <linux/interrupt.h>
23
24#include <asm/signal.h>
25#include <asm/irq.h>
26
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>
32
33#include <hwregs/strcop.h>
34#include <hwregs/strcop_defs.h>
35#include <cryptocop.h>
36
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
50
51#define DESCR_ALLOC_PAD (31)
52
53struct cryptocop_dma_desc {
54 char *free_buf;
55 dma_descr_data *dma_descr;
56
57 unsigned char dma_descr_buf[sizeof(dma_descr_data) + DESCR_ALLOC_PAD];
58
59 unsigned int from_pool:1;
60 struct cryptocop_dma_desc *next;
61};
62
63
64struct cryptocop_int_operation{
65 void *alloc_ptr;
66 cryptocop_session_id sid;
67
68 dma_descr_context ctx_out;
69 dma_descr_context ctx_in;
70
71
72 struct cryptocop_dma_desc *cdesc_out;
73 struct cryptocop_dma_desc *cdesc_in;
74
75
76 cryptocop_3des_mode tdes_mode;
77 cryptocop_csum_type csum_mode;
78
79
80 dma_descr_data *ddesc_out;
81 dma_descr_data *ddesc_in;
82};
83
84
85struct cryptocop_tfrm_ctx {
86 cryptocop_tfrm_id tid;
87 unsigned int blocklength;
88
89 unsigned int start_ix;
90
91 struct cryptocop_tfrm_cfg *tcfg;
92 struct cryptocop_transform_ctx *tctx;
93
94 unsigned char previous_src;
95 unsigned char current_src;
96
97
98 unsigned char hash_conf;
99 unsigned char hash_mode;
100 unsigned char ciph_conf;
101 unsigned char cbcmode;
102 unsigned char decrypt;
103
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;
110
111
112
113 struct cryptocop_dma_desc *pad_descs;
114
115 struct cryptocop_tfrm_ctx *prev_src;
116 struct cryptocop_tfrm_ctx *curr_src;
117
118
119 unsigned char unit_no;
120};
121
122
123struct cryptocop_private{
124 cryptocop_session_id sid;
125 struct cryptocop_private *next;
126};
127
128
129
130struct 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;
134
135 struct cryptocop_transform_ctx *next;
136};
137
138
139struct cryptocop_session{
140 cryptocop_session_id sid;
141
142 struct cryptocop_transform_ctx *tfrm_ctx;
143
144 struct cryptocop_session *next;
145};
146
147
148
149
150typedef 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;
156
157struct cryptocop_prio_queue{
158 struct list_head jobs;
159 cryptocop_queue_priority prio;
160};
161
162struct cryptocop_prio_job{
163 struct list_head node;
164 cryptocop_queue_priority prio;
165
166 struct cryptocop_operation *oper;
167 struct cryptocop_int_operation *iop;
168};
169
170struct ioctl_job_cb_ctx {
171 unsigned int processed:1;
172};
173
174
175static struct cryptocop_session *cryptocop_sessions = NULL;
176spinlock_t cryptocop_sessions_lock;
177
178
179static cryptocop_session_id next_sid = 1;
180
181
182static const char csum_zero_pad[1] = {0x00};
183
184
185#define MEM2MEM_DISCARD_BUF_LENGTH (512)
186static unsigned char mem2mem_discard_buf[MEM2MEM_DISCARD_BUF_LENGTH];
187
188
189
190#define CRYPTOCOP_DESCRIPTOR_POOL_SIZE (100)
191static struct cryptocop_dma_desc descr_pool[CRYPTOCOP_DESCRIPTOR_POOL_SIZE];
192static struct cryptocop_dma_desc *descr_pool_free_list;
193static int descr_pool_no_free;
194static spinlock_t descr_pool_lock;
195
196
197
198spinlock_t cryptocop_process_lock;
199
200static struct cryptocop_prio_queue cryptocop_job_queues[cryptocop_prio_no_prios];
201static spinlock_t cryptocop_job_queue_lock;
202static struct cryptocop_prio_job *cryptocop_running_job = NULL;
203static spinlock_t running_job_lock;
204
205
206
207static struct list_head cryptocop_completed_jobs;
208static spinlock_t cryptocop_completed_jobs_lock;
209
210DECLARE_WAIT_QUEUE_HEAD(cryptocop_ioc_process_wq);
211
212
213
214
215static int cryptocop_open(struct inode *, struct file *);
216
217static int cryptocop_release(struct inode *, struct file *);
218
219static long cryptocop_ioctl(struct file *file,
220 unsigned int cmd, unsigned long arg);
221
222static void cryptocop_start_job(void);
223
224static int cryptocop_job_queue_insert(cryptocop_queue_priority prio, struct cryptocop_operation *operation);
225static int cryptocop_job_setup(struct cryptocop_prio_job **pj, struct cryptocop_operation *operation);
226
227static int cryptocop_job_queue_init(void);
228static void cryptocop_job_queue_close(void);
229
230static int create_md5_pad(int alloc_flag, unsigned long long hashed_length, char **pad, size_t *pad_length);
231
232static int create_sha1_pad(int alloc_flag, unsigned long long hashed_length, char **pad, size_t *pad_length);
233
234static int transform_ok(struct cryptocop_transform_init *tinit);
235
236static struct cryptocop_session *get_session(cryptocop_session_id sid);
237
238static struct cryptocop_transform_ctx *get_transform_ctx(struct cryptocop_session *sess, cryptocop_tfrm_id tid);
239
240static void delete_internal_operation(struct cryptocop_int_operation *iop);
241
242static void get_aes_decrypt_key(unsigned char *dec_key, const unsigned char *key, unsigned int keylength);
243
244static int init_stream_coprocessor(void);
245
246static void __exit exit_stream_coprocessor(void);
247
248
249#ifdef LDEBUG
250#define DEBUG(s) s
251#define DEBUG_API(s) s
252static void print_cryptocop_operation(struct cryptocop_operation *cop);
253static void print_dma_descriptors(struct cryptocop_int_operation *iop);
254static void print_strcop_crypto_op(struct strcop_crypto_op *cop);
255static void print_lock_status(void);
256static 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
263
264
265
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)
273
274
275#define CRYPTOCOP_MAJOR (254)
276#define CRYPTOCOP_MINOR (0)
277
278
279
280const 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,
286};
287
288
289static void free_cdesc(struct cryptocop_dma_desc *cdesc)
290{
291 DEBUG(printk("free_cdesc: cdesc 0x%p, from_pool=%d\n", cdesc, cdesc->from_pool));
292 kfree(cdesc->free_buf);
293
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);
303 }
304}
305
306
307static struct cryptocop_dma_desc *alloc_cdesc(int alloc_flag)
308{
309 int use_pool = (alloc_flag & GFP_ATOMIC) ? 1 : 0;
310 struct cryptocop_dma_desc *cdesc;
311
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;
319 }
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;
330 }
331 cdesc->from_pool = 0;
332 }
333 cdesc->dma_descr = (dma_descr_data*)(((unsigned long int)cdesc + offsetof(struct cryptocop_dma_desc, dma_descr_buf) + DESCR_ALLOC_PAD) & ~0x0000001F);
334
335 cdesc->next = NULL;
336
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;
345
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;
348}
349
350
351static void setup_descr_chain(struct cryptocop_dma_desc *cd)
352{
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;
359 }
360 cd = cd->next;
361 }
362 DEBUG(printk("setup_descr_chain: exit\n"));
363}
364
365
366
367
368static int create_pad_descriptor(struct cryptocop_tfrm_ctx *tc, struct cryptocop_dma_desc **pad_desc, int alloc_flag)
369{
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
376 };
377 char *pad;
378 size_t plen;
379
380 DEBUG(printk("create_pad_descriptor: start.\n"));
381
382
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;
388 }
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;
395 }
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;
406 }
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;
418 plen = 0;
419 }
420 mo.csumsel = src_dma;
421 break;
422 }
423 cdesc->dma_descr->wait = 1;
424 cdesc->dma_descr->out_eop = 1;
425 cdesc->dma_descr->buf = (char*)virt_to_phys((char*)pad);
426 cdesc->dma_descr->after = cdesc->dma_descr->buf + plen;
427
428 cdesc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_out, mo);
429 *pad_desc = cdesc;
430
431 return 0;
432
433 error_cleanup:
434 if (cdesc) free_cdesc(cdesc);
435 return -1;
436}
437
438
439static int setup_key_dl_desc(struct cryptocop_tfrm_ctx *tc, struct cryptocop_dma_desc **kd, int alloc_flag)
440{
441 struct cryptocop_dma_desc *key_desc = alloc_cdesc(alloc_flag);
442 struct strcop_meta_out mo = {0};
443
444 DEBUG(printk("setup_key_dl_desc\n"));
445
446 if (!key_desc) {
447 DEBUG_API(printk("setup_key_dl_desc: failed descriptor allocation.\n"));
448 return -ENOMEM;
449 }
450
451
452 if ((tc->tctx->init.alg == cryptocop_alg_aes) && (tc->tcfg->flags & CRYPTOCOP_DECRYPT)) {
453
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;
457 }
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;
463 }
464
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;
485 }
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);
488
489 key_desc->dma_descr->out_eop = 1;
490 key_desc->dma_descr->wait = 1;
491 key_desc->dma_descr->intr = 0;
492
493 *kd = key_desc;
494 return 0;
495}
496
497static int setup_cipher_iv_desc(struct cryptocop_tfrm_ctx *tc, struct cryptocop_dma_desc **id, int alloc_flag)
498{
499 struct cryptocop_dma_desc *iv_desc = alloc_cdesc(alloc_flag);
500 struct strcop_meta_out mo = {0};
501
502 DEBUG(printk("setup_cipher_iv_desc\n"));
503
504 if (!iv_desc) {
505 DEBUG_API(printk("setup_cipher_iv_desc: failed CBC IV descriptor allocation.\n"));
506 return -ENOMEM;
507 }
508
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;
511
512
513 mo.hashsel = mo.csumsel = src_none;
514 mo.ciphsel = src_dma;
515 mo.ciphconf = tc->ciph_conf;
516 mo.cbcmode = tc->cbcmode;
517
518 iv_desc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_out, mo);
519
520 iv_desc->dma_descr->out_eop = 0;
521 iv_desc->dma_descr->wait = 1;
522 iv_desc->dma_descr->intr = 0;
523
524 *id = iv_desc;
525 return 0;
526}
527
528
529static int create_input_descriptors(struct cryptocop_operation *operation, struct cryptocop_tfrm_ctx *tc, struct cryptocop_dma_desc **id, int alloc_flag)
530{
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};
538
539 size_t out_length = tc->produced;
540 int rem_length;
541 int dlength;
542
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;
547 }
548
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++;
552 }
553 if (outiov_ix >= operation->tfrm_op.outcount){
554 DEBUG_API(printk("create_input_descriptors: operation outdata too small\n"));
555 return -EINVAL;
556 }
557 iov_offset = tc->tcfg->inject_ix - out_ix;
558 mi.dmasel = tc->unit_no;
559
560
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;
567 }
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;
571
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));
577
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);
581
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;
587 }
588 }
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;
593 }
594
595 mi.sync = 1;
596 outdesc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_in, mi);
597
598 *id = head.next;
599 return 0;
600
601 error_cleanup:
602 while (head.next) {
603 outdesc = head.next->next;
604 free_cdesc(head.next);
605 head.next = outdesc;
606 }
607 return err;
608}
609
610
611static 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)
612{
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;
617
618 cdesc = alloc_cdesc(alloc_flag);
619 if (!cdesc) {
620 DEBUG_API(printk("create_output_descriptors: alloc_cdesc\n"));
621 return -ENOMEM;
622 }
623 (*current_out_cdesc)->next = cdesc;
624 (*current_out_cdesc) = cdesc;
625
626 cdesc->free_buf = NULL;
627
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;
630
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;
640 }
641 }
642 cdesc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_out, (*meta_out));
643 }
644
645 (*current_out_cdesc)->dma_descr->wait = 1;
646
647 return 0;
648}
649
650
651static 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)
652{
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;
665 }
666 }
667
668
669 if (tc->unit_no == src_dma){
670
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;
679 }
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;
685 }
686 mi.sync = 1;
687 (*current_in_cdesc)->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_in, mi);
688 }
689
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;
694 }
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;
701 }
702 }
703 return 0;
704}
705
706
707
708static int cryptocop_setup_dma_list(struct cryptocop_operation *operation, struct cryptocop_int_operation **int_op, int alloc_flag)
709{
710 struct cryptocop_session *sess;
711 struct cryptocop_transform_ctx *tctx;
712
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;
773
774 unsigned int indata_ix = 0;
775
776
777 int iniov_ix = 0;
778 int iniov_offset = 0;
779
780
781 struct cryptocop_desc *odsc;
782
783 int failed = 0;
784
785 struct cryptocop_dma_desc out_cdesc_head = {0};
786 struct cryptocop_dma_desc in_cdesc_head = {0};
787
788 struct cryptocop_dma_desc *current_out_cdesc = &out_cdesc_head;
789 struct cryptocop_dma_desc *current_in_cdesc = &in_cdesc_head;
790
791 struct cryptocop_tfrm_ctx *output_tc = NULL;
792 void *iop_alloc_ptr;
793
794 assert(operation != NULL);
795 assert(int_op != NULL);
796
797 DEBUG(printk("cryptocop_setup_dma_list: start\n"));
798 DEBUG(print_cryptocop_operation(operation));
799
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;
805 }
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;
811 }
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));
816
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;
824
825
826 if (!tcfg) {
827 DEBUG_API(printk("cryptocop_setup_dma_list: no configured transforms in operation.\n"));
828 failed = -EINVAL;
829 goto error_cleanup;
830 }
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;
837 }
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;
842 }
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;
849 }
850
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
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;
867 }
868 cipher_ctx.tcfg = tcfg;
869 cipher_ctx.tctx = tctx;
870 if (cipher_ctx.tcfg->flags & CRYPTOCOP_DECRYPT){
871 cipher_ctx.decrypt = 1;
872 }
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;
884 }
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);
904 }
905 (*int_op)->tdes_mode = tctx->init.tdes_mode;
906 break;
907 case cryptocop_alg_md5:
908 case cryptocop_alg_sha1:
909
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;
914 }
915 digest_ctx.tcfg = tcfg;
916 digest_ctx.tctx = tctx;
917 digest_ctx.hash_mode = 0;
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;
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;
928 break;
929 default:
930 panic("cryptocop_setup_dma_list: impossible digest algorithm\n");
931 }
932 break;
933 case cryptocop_alg_csum:
934
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;
939 }
940 (*int_op)->csum_mode = tctx->init.csum_mode;
941 csum_ctx.tcfg = tcfg;
942 csum_ctx.tctx = tctx;
943 break;
944 default:
945
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;
949 }
950 tcfg = tcfg->next;
951 }
952
953 if (cipher_ctx.tcfg && (cipher_ctx.tctx->init.alg != cryptocop_alg_mem2mem)){
954 struct cryptocop_dma_desc *key_desc = NULL;
955
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;
960 }
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);
964
965
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;
968
969 DEBUG(printk("cryptocop_setup_dma_list: setup cipher CBC IV descriptor.\n"));
970
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;
975 }
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);
979 }
980 }
981
982
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;
989
990 output_tc = NULL;
991
992 DEBUG(printk("cryptocop_setup_dma_list: parsing an operation descriptor\n"));
993
994 while (dcfg) {
995 struct cryptocop_tfrm_ctx *tc = NULL;
996
997 DEBUG(printk("cryptocop_setup_dma_list: parsing an operation descriptor configuration.\n"));
998
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;
1005 }
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;
1010 }
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;
1015 }
1016 if (!tc->active) {
1017 tc->start_ix = indata_ix;
1018 tc->active = 1;
1019 }
1020
1021 tc->previous_src = tc->current_src;
1022 tc->prev_src = tc->curr_src;
1023
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
1043
1044 DEBUG_API(printk("cryptocop_setup_dma_list: bad unit source configured %d.\n", dcfg->src));
1045 failed = -EINVAL;
1046 goto error_cleanup;
1047 }
1048 if (tc->current_src != src_dma) {
1049
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;
1056 }
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;
1061 }
1062 } else {
1063 tc->curr_src = NULL;
1064 }
1065
1066
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
1070
1071
1072
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)))
1075 {
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;
1079 }
1080 }
1081
1082 if (dcfg->last) {
1083
1084 tc->done = 1;
1085 }
1086 dcfg = dcfg->next;
1087 }
1088 DEBUG(printk("cryptocop_setup_dma_list: parsing operation descriptor configuration complete.\n"));
1089
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;
1094 }
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;
1099 }
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;
1104 }
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115 DEBUG(printk("cryptocop_setup_dma_list: desc->length=%d, desc_len=%d.\n", odsc->length, desc_len));
1116
1117 if (csum_ctx.active) {
1118 csum_ctx.consumed += desc_len;
1119 if (csum_ctx.done) {
1120 csum_ctx.produced = 2;
1121 }
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));
1123 }
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;
1131 }
1132 }
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));
1134 }
1135 if (cipher_ctx.active) {
1136
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;
1142 }
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));
1144 }
1145
1146
1147
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
1154 meta_out.ciphsel = src_none;
1155 } else {
1156 meta_out.ciphsel = cipher_ctx.current_src;
1157 }
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;
1165 }
1166
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;
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;
1179 }
1180 }
1181 } else {
1182 meta_out.hashsel = src_none;
1183 }
1184
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;
1194 }
1195 }
1196 } else {
1197 meta_out.csumsel = src_none;
1198 }
1199 DEBUG(printk("cryptocop_setup_dma_list: %d eop needed, %d active units\n", eop_needed_count, active_count));
1200
1201 failed = create_output_descriptors(operation, &iniov_ix, &iniov_offset, desc_len, ¤t_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;
1205 }
1206
1207
1208
1209
1210 assert(active_count >= eop_needed_count);
1211 assert((eop_needed_count == 0) || (eop_needed_count == 1));
1212 if (eop_needed_count) {
1213
1214 if (active_count > 1) {
1215
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;
1222 }
1223
1224 assert(cipher_ctx.active && cipher_ctx.done);
1225
1226 if (cipher_ctx.unit_no == src_dma){
1227
1228 ed_mo.ciphsel = src_none;
1229 } else {
1230 ed_mo.ciphsel = cipher_ctx.current_src;
1231 }
1232 ed_mo.ciphconf = cipher_ctx.ciph_conf;
1233 ed_mo.cbcmode = cipher_ctx.cbcmode;
1234 ed_mo.decrypt = cipher_ctx.decrypt;
1235
1236 ed->free_buf = NULL;
1237 ed->dma_descr->wait = 1;
1238 ed->dma_descr->out_eop = 1;
1239
1240 ed->dma_descr->buf = (char*)virt_to_phys(&ed);
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
1247
1248
1249 current_out_cdesc->dma_descr->out_eop = 1;
1250 }
1251 }
1252
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 }
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;
1264 }
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;
1269 }
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;
1274 }
1275
1276 failed = append_input_descriptors(operation, ¤t_in_cdesc, ¤t_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;
1280 }
1281 failed = append_input_descriptors(operation, ¤t_in_cdesc, ¤t_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;
1285 }
1286 failed = append_input_descriptors(operation, ¤t_in_cdesc, ¤t_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;
1290 }
1291
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));
1296
1297 setup_descr_chain(out_cdesc_head.next);
1298 setup_descr_chain(in_cdesc_head.next);
1299
1300
1301
1302
1303 current_in_cdesc->dma_descr->intr = 1;
1304 current_in_cdesc->dma_descr->eol = 1;
1305 current_out_cdesc->dma_descr->eol = 1;
1306
1307
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;
1321
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;
1333
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;
1336
1337 DEBUG(printk("cryptocop_setup_dma_list: done\n"));
1338 return 0;
1339
1340error_cleanup:
1341 {
1342
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;
1348 }
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;
1353 }
1354 assert(cipher_ctx.pad_descs == NULL);
1355
1356 if (*int_op != NULL) delete_internal_operation(*int_op);
1357 }
1358 DEBUG_API(printk("cryptocop_setup_dma_list: done with error %d\n", failed));
1359 return failed;
1360}
1361
1362
1363static void delete_internal_operation(struct cryptocop_int_operation *iop)
1364{
1365 void *ptr = iop->alloc_ptr;
1366 struct cryptocop_dma_desc *cd = iop->cdesc_out;
1367 struct cryptocop_dma_desc *next;
1368
1369 DEBUG(printk("delete_internal_operation: iop=0x%p, alloc_ptr=0x%p\n", iop, ptr));
1370
1371 while (cd) {
1372 next = cd->next;
1373 free_cdesc(cd);
1374 cd = next;
1375 }
1376 cd = iop->cdesc_in;
1377 while (cd) {
1378 next = cd->next;
1379 free_cdesc(cd);
1380 cd = next;
1381 }
1382 kfree(ptr);
1383}
1384
1385#define MD5_MIN_PAD_LENGTH (9)
1386#define MD5_PAD_LENGTH_FIELD_LENGTH (8)
1387
1388static int create_md5_pad(int alloc_flag, unsigned long long hashed_length, char **pad, size_t *pad_length)
1389{
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;
1394
1395 if (padlen < MD5_MIN_PAD_LENGTH) padlen += MD5_BLOCK_LENGTH;
1396
1397 p = kzalloc(padlen, alloc_flag);
1398 if (!p) return -ENOMEM;
1399
1400 *p = 0x80;
1401
1402 DEBUG(printk("create_md5_pad: hashed_length=%lld bits == %lld bytes\n", bit_length, hashed_length));
1403
1404 i = padlen - MD5_PAD_LENGTH_FIELD_LENGTH;
1405 while (bit_length != 0){
1406 p[i++] = bit_length % 0x100;
1407 bit_length >>= 8;
1408 }
1409
1410 *pad = (char*)p;
1411 *pad_length = padlen;
1412
1413 return 0;
1414}
1415
1416#define SHA1_MIN_PAD_LENGTH (9)
1417#define SHA1_PAD_LENGTH_FIELD_LENGTH (8)
1418
1419static int create_sha1_pad(int alloc_flag, unsigned long long hashed_length, char **pad, size_t *pad_length)
1420{
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;
1425
1426 if (padlen < SHA1_MIN_PAD_LENGTH) padlen += SHA1_BLOCK_LENGTH;
1427
1428 p = kzalloc(padlen, alloc_flag);
1429 if (!p) return -ENOMEM;
1430
1431 *p = 0x80;
1432
1433 DEBUG(printk("create_sha1_pad: hashed_length=%lld bits == %lld bytes\n", bit_length, hashed_length));
1434
1435 i = padlen - 1;
1436 while (bit_length != 0){
1437 p[i--] = bit_length % 0x100;
1438 bit_length >>= 8;
1439 }
1440
1441 *pad = (char*)p;
1442 *pad_length = padlen;
1443
1444 return 0;
1445}
1446
1447
1448static int transform_ok(struct cryptocop_transform_init *tinit)
1449{
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;
1459 }
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;
1466 }
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;
1472 }
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;
1478 }
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;
1484 }
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;
1490 }
1491
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;
1499 }
1500 return 0;
1501}
1502
1503
1504int cryptocop_new_session(cryptocop_session_id *sid, struct cryptocop_transform_init *tinit, int alloc_flag)
1505{
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;
1512
1513 init_stream_coprocessor();
1514
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;
1521 }
1522 tfrm_in = tfrm_in->next;
1523 }
1524 if (0 == no_tfrms) {
1525 DEBUG_API(printk("cryptocop_new_session, no transforms specified\n"));
1526 return -EINVAL;
1527 }
1528
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;
1533 }
1534
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;
1540 }
1541
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;
1551 }
1552 tmp_in = tmp_in->next;
1553 }
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;
1557
1558 tfrm_in = tfrm_in->next;
1559 }
1560 sess->tfrm_ctx[i-1].next = NULL;
1561
1562 spin_lock_irqsave(&cryptocop_sessions_lock, flags);
1563 sess->sid = next_sid;
1564 next_sid++;
1565
1566
1567 if (next_sid == 0) next_sid = 1;
1568
1569
1570 sess->next = cryptocop_sessions;
1571 cryptocop_sessions = sess;
1572 spin_unlock_irqrestore(&cryptocop_sessions_lock, flags);
1573 *sid = sess->sid;
1574 return 0;
1575}
1576
1577
1578int cryptocop_free_session(cryptocop_session_id sid)
1579{
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;
1588
1589 DEBUG(printk("cryptocop_free_session: sid=%lld\n", sid));
1590
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;
1596 }
1597 if (sess){
1598 if (psess){
1599 psess->next = sess->next;
1600 } else {
1601 cryptocop_sessions = sess->next;
1602 }
1603 }
1604 spin_unlock_irqrestore(&cryptocop_sessions_lock, flags);
1605
1606 if (!sess) return -EINVAL;
1607
1608
1609 spin_lock_irqsave(&cryptocop_job_queue_lock, flags);
1610
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);
1617 }
1618 }
1619 }
1620 }
1621 spin_unlock_irqrestore(&cryptocop_job_queue_lock, flags);
1622
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;
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);
1631 }
1632
1633 tc = sess->tfrm_ctx;
1634
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;
1640 }
1641 kfree(sess->tfrm_ctx);
1642 kfree(sess);
1643
1644 return 0;
1645}
1646
1647static struct cryptocop_session *get_session(cryptocop_session_id sid)
1648{
1649 struct cryptocop_session *sess;
1650 unsigned long int flags;
1651
1652 spin_lock_irqsave(&cryptocop_sessions_lock, flags);
1653 sess = cryptocop_sessions;
1654 while (sess && (sess->sid != sid)){
1655 sess = sess->next;
1656 }
1657 spin_unlock_irqrestore(&cryptocop_sessions_lock, flags);
1658
1659 return sess;
1660}
1661
1662static struct cryptocop_transform_ctx *get_transform_ctx(struct cryptocop_session *sess, cryptocop_tfrm_id tid)
1663{
1664 struct cryptocop_transform_ctx *tc = sess->tfrm_ctx;
1665
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;
1671 }
1672 DEBUG(printk("get_transform_ctx, returning tc=0x%p\n", tc));
1673 return tc;
1674}
1675
1676
1677
1678
1679static 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
1696};
1697
1698
1699
1700
1701static u32 round_constant[11] = {
1702 0x01000000, 0x02000000, 0x04000000, 0x08000000,
1703 0x10000000, 0x20000000, 0x40000000, 0x80000000,
1704 0x1B000000, 0x36000000, 0x6C000000
1705};
1706
1707
1708static u32 aes_ks_subword(const u32 w)
1709{
1710 u8 bytes[4];
1711
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]);
1718}
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753static void get_aes_decrypt_key(unsigned char *dec_key, const unsigned char *key, unsigned int keylength)
1754{
1755 u32 temp;
1756 u32 w_ring[8];
1757 u8 w_last_ix;
1758 int i;
1759 u8 nr, nk;
1760
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");
1776 };
1777
1778
1779
1780 for (i = 0; i < nk; i+=1) {
1781 w_ring[i] = be32_to_cpu(*(u32*)&key[4*i]);
1782 }
1783
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
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);
1795 }
1796 w_last_ix = (w_last_ix + 1) % nk;
1797 temp ^= w_ring[w_last_ix];
1798 w_ring[w_last_ix] = temp;
1799
1800
1801
1802
1803
1804
1805 if (i >= (4 * nr)) {
1806
1807
1808 *(u32*)dec_key = cpu_to_be32(temp);
1809 dec_key += 4;
1810 }
1811 ++i;
1812 }
1813}
1814
1815
1816
1817
1818int cryptocop_job_queue_insert_csum(struct cryptocop_operation *operation)
1819{
1820 return cryptocop_job_queue_insert(cryptocop_prio_kernel_csum, operation);
1821}
1822
1823int cryptocop_job_queue_insert_crypto(struct cryptocop_operation *operation)
1824{
1825 return cryptocop_job_queue_insert(cryptocop_prio_kernel, operation);
1826}
1827
1828int cryptocop_job_queue_insert_user_job(struct cryptocop_operation *operation)
1829{
1830 return cryptocop_job_queue_insert(cryptocop_prio_user, operation);
1831}
1832
1833static int cryptocop_job_queue_insert(cryptocop_queue_priority prio, struct cryptocop_operation *operation)
1834{
1835 int ret;
1836 struct cryptocop_prio_job *pj = NULL;
1837 unsigned long int flags;
1838
1839 DEBUG(printk("cryptocop_job_queue_insert(%d, 0x%p)\n", prio, operation));
1840
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;
1844 }
1845
1846 if ((ret = cryptocop_job_setup(&pj, operation)) != 0){
1847 DEBUG_API(printk("cryptocop_job_queue_insert: job setup failed\n"));
1848 return ret;
1849 }
1850 assert(pj != NULL);
1851
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);
1855
1856
1857 cryptocop_start_job();
1858 return 0;
1859}
1860
1861static void cryptocop_do_tasklet(unsigned long unused);
1862DECLARE_TASKLET (cryptocop_tasklet, cryptocop_do_tasklet, 0);
1863
1864static void cryptocop_do_tasklet(unsigned long unused)
1865{
1866 struct list_head *node;
1867 struct cryptocop_prio_job *pj = NULL;
1868 unsigned long flags;
1869
1870 DEBUG(printk("cryptocop_do_tasklet: entering\n"));
1871
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;
1880 }
1881 spin_unlock_irqrestore(&cryptocop_completed_jobs_lock, flags);
1882 if (pj) {
1883 assert(pj->oper != NULL);
1884
1885
1886 DEBUG(printk("cryptocop_do_tasklet: callback 0x%p, data 0x%p\n", pj->oper->cb, pj->oper->cb_data));
1887
1888 pj->oper->operation_status = 0;
1889 pj->oper->cb(pj->oper, pj->oper->cb_data);
1890 delete_internal_operation(pj->iop);
1891 kfree(pj);
1892 }
1893 } while (pj != NULL);
1894
1895 DEBUG(printk("cryptocop_do_tasklet: exiting\n"));
1896}
1897
1898static irqreturn_t
1899dma_done_interrupt(int irq, void *dev_id)
1900{
1901 struct cryptocop_prio_job *done_job;
1902 reg_dma_rw_ack_intr ack_intr = {
1903 .data = 1,
1904 };
1905
1906 REG_WR(dma, IN_DMA_INST, rw_ack_intr, ack_intr);
1907
1908 DEBUG(printk("cryptocop DMA done\n"));
1909
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;
1915 }
1916 done_job = cryptocop_running_job;
1917 cryptocop_running_job = NULL;
1918 spin_unlock(&running_job_lock);
1919
1920
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);
1926 }
1927
1928 done_job->oper->operation_status = 0;
1929 if (done_job->oper->fast_callback){
1930
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);
1939 }
1940
1941 DEBUG(printk("cryptocop leave irq handler\n"));
1942 return IRQ_HANDLED;
1943}
1944
1945
1946
1947static int init_cryptocop(void)
1948{
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};
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
1960 };
1961
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");
1965
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);
1970
1971 local_irq_save(flags);
1972
1973
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);
1978
1979
1980 REG_WR(dma, IN_DMA_INST, rw_cfg, dma_cfg);
1981 REG_WR(dma, OUT_DMA_INST, rw_cfg, dma_cfg);
1982
1983
1984 DMA_WR_CMD(OUT_DMA_INST, regk_dma_set_w_size4);
1985 DMA_WR_CMD(IN_DMA_INST, regk_dma_set_w_size4);
1986
1987
1988 REG_WR(dma, IN_DMA_INST, rw_intr_mask, intr_mask_in);
1989
1990
1991 REG_WR(dma, IN_DMA_INST, rw_ack_intr, ack_intr);
1992
1993 local_irq_restore(flags);
1994
1995 return 0;
1996}
1997
1998
1999static void release_cryptocop(void)
2000{
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 };
2005
2006 local_irq_save(flags);
2007
2008
2009 REG_WR(dma, IN_DMA_INST, rw_ack_intr, ack_intr);
2010
2011
2012 REG_WR(dma, IN_DMA_INST, rw_cfg, dma_cfg);
2013 REG_WR(dma, OUT_DMA_INST, rw_cfg, dma_cfg);
2014
2015
2016 REG_WR(dma, IN_DMA_INST, rw_intr_mask, intr_mask_in);
2017
2018 local_irq_restore(flags);
2019
2020 free_irq(DMA_IRQ, NULL);
2021
2022 (void)crisv32_free_dma(OUT_DMA);
2023 (void)crisv32_free_dma(IN_DMA);
2024}
2025
2026
2027
2028static int cryptocop_job_queue_init(void)
2029{
2030 int i;
2031
2032 INIT_LIST_HEAD(&cryptocop_completed_jobs);
2033
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);
2037 }
2038 return 0;
2039}
2040
2041
2042static void cryptocop_job_queue_close(void)
2043{
2044 struct list_head *node, *tmp;
2045 struct cryptocop_prio_job *pj = NULL;
2046 unsigned long int process_flags, flags;
2047 int i;
2048
2049
2050
2051
2052
2053 spin_lock_irqsave(&cryptocop_process_lock, process_flags);
2054
2055
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);
2061
2062
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;
2065 pj->oper->cb(pj->oper, pj->oper->cb_data);
2066
2067 delete_internal_operation(pj->iop);
2068 kfree(pj);
2069 }
2070 }
2071 }
2072 spin_unlock_irqrestore(&cryptocop_process_lock, process_flags);
2073
2074
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;
2079
2080
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);
2084
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);
2088
2089
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);
2093
2094 pj = cryptocop_running_job;
2095 cryptocop_running_job = NULL;
2096
2097
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;
2100 pj->oper->cb(pj->oper, pj->oper->cb_data);
2101
2102 delete_internal_operation(pj->iop);
2103 kfree(pj);
2104 }
2105 spin_unlock_irqrestore(&running_job_lock, flags);
2106
2107
2108 spin_lock_irqsave(&cryptocop_completed_jobs_lock, flags);
2109
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
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;
2116 pj->oper->cb(pj->oper, pj->oper->cb_data);
2117
2118 delete_internal_operation(pj->iop);
2119 kfree(pj);
2120 }
2121 spin_unlock_irqrestore(&cryptocop_completed_jobs_lock, flags);
2122}
2123
2124
2125static void cryptocop_start_job(void)
2126{
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};
2132
2133 DEBUG(printk("cryptocop_start_job: entering\n"));
2134
2135 spin_lock_irqsave(&running_job_lock, running_job_flags);
2136 if (cryptocop_running_job != NULL){
2137
2138 DEBUG(printk("cryptocop_start_job: already running, exit\n"));
2139 spin_unlock_irqrestore(&running_job_lock, running_job_flags);
2140 return;
2141 }
2142 spin_lock_irqsave(&cryptocop_job_queue_lock, flags);
2143
2144
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;
2151 }
2152 DEBUG(printk("starting job for prio %d\n", i));
2153
2154
2155
2156
2157
2158
2159
2160
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;
2165
2166
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"));
2210 }
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"));
2220 }
2221 REG_WR(strcop, regi_strcop, rw_cfg, rw_cfg);
2222
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",
2226 pj,
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)));
2229
2230
2231 flush_dma_context(&pj->iop->ctx_in);
2232 DMA_START_CONTEXT(IN_DMA_INST, virt_to_phys(&pj->iop->ctx_in));
2233
2234
2235 DMA_START_CONTEXT(OUT_DMA_INST, virt_to_phys(&pj->iop->ctx_out));
2236
2237 spin_unlock_irqrestore(&running_job_lock, running_job_flags);
2238 DEBUG(printk("cryptocop_start_job: exiting\n"));
2239}
2240
2241
2242static int cryptocop_job_setup(struct cryptocop_prio_job **pj, struct cryptocop_operation *operation)
2243{
2244 int err;
2245 int alloc_flag = operation->in_interrupt ? GFP_ATOMIC : GFP_KERNEL;
2246 void *iop_alloc_ptr = NULL;
2247
2248 *pj = kmalloc(sizeof (struct cryptocop_prio_job), alloc_flag);
2249 if (!*pj) return -ENOMEM;
2250
2251 DEBUG(printk("cryptocop_job_setup: operation=0x%p\n", operation));
2252
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));
2255
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;
2262 }
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;
2268 }
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;
2279
2280
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;
2285
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;
2295 }
2296 }
2297 DEBUG(print_dma_descriptors((*pj)->iop));
2298
2299 DEBUG(printk("cryptocop_job_setup, DMA list setup successful\n"));
2300
2301 return 0;
2302}
2303
2304static int cryptocop_open(struct inode *inode, struct file *filp)
2305{
2306 int p = iminor(inode);
2307
2308 if (p != CRYPTOCOP_MINOR) return -EINVAL;
2309
2310 filp->private_data = NULL;
2311 return 0;
2312}
2313
2314
2315static int cryptocop_release(struct inode *inode, struct file *filp)
2316{
2317 struct cryptocop_private *dev = filp->private_data;
2318 struct cryptocop_private *dev_next;
2319
2320 while (dev){
2321 dev_next = dev->next;
2322 if (dev->sid != CRYPTOCOP_SESSION_ID_NONE) {
2323 (void)cryptocop_free_session(dev->sid);
2324 }
2325 kfree(dev);
2326 dev = dev_next;
2327 }
2328
2329 return 0;
2330}
2331
2332
2333static int cryptocop_ioctl_close_session(struct inode *inode, struct file *filp,
2334 unsigned int cmd, unsigned long arg)
2335{
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;
2341
2342 DEBUG(printk("cryptocop_ioctl_close_session\n"));
2343
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;
2348
2349 while (dev && (dev->sid != sop.ses_id)) {
2350 prev_dev = dev;
2351 dev = dev->next;
2352 }
2353 if (dev){
2354 if (prev_dev){
2355 prev_dev->next = dev->next;
2356 } else {
2357 filp->private_data = dev->next;
2358 }
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;
2364 }
2365 return 0;
2366}
2367
2368
2369static void ioctl_process_job_callback(struct cryptocop_operation *op, void*cb_data)
2370{
2371 struct ioctl_job_cb_ctx *jc = (struct ioctl_job_cb_ctx *)cb_data;
2372
2373 DEBUG(printk("ioctl_process_job_callback: op=0x%p, cb_data=0x%p\n", op, cb_data));
2374
2375 jc->processed = 1;
2376 wake_up(&cryptocop_ioc_process_wq);
2377}
2378
2379
2380#define CRYPTOCOP_IOCTL_CIPHER_TID (1)
2381#define CRYPTOCOP_IOCTL_DIGEST_TID (2)
2382#define CRYPTOCOP_IOCTL_CSUM_TID (3)
2383
2384static size_t first_cfg_change_ix(struct strcop_crypto_op *crp_op)
2385{
2386 size_t ch_ix = 0;
2387
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;
2391
2392 DEBUG(printk("first_cfg_change_ix: ix=%d\n", ch_ix));
2393 return ch_ix;
2394}
2395
2396
2397static size_t next_cfg_change_ix(struct strcop_crypto_op *crp_op, size_t ix)
2398{
2399 size_t ch_ix = INT_MAX;
2400 size_t tmp_ix = 0;
2401
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;
2407 }
2408 }
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;
2414 }
2415 if (tmp_ix < ch_ix) ch_ix = tmp_ix;
2416 }
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;
2422 }
2423 if (tmp_ix < ch_ix) ch_ix = tmp_ix;
2424 }
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;
2428}
2429
2430
2431
2432
2433static int map_pages_to_iovec(struct iovec *iov, int iovlen, int *iovix, struct page **pages, int nopages, int *pageix, int *pageoffset, int map_length )
2434{
2435 int tmplen;
2436
2437 assert(iov != NULL);
2438 assert(iovix != NULL);
2439 assert(pages != NULL);
2440 assert(pageix != NULL);
2441 assert(pageoffset != NULL);
2442
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));
2444
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;
2450 }
2451 if (*pageix >= nopages){
2452 DEBUG_API(printk("map_page_to_iovec: *pageix=%d >= nopages=%d\n", *pageix, nopages));
2453 return 0;
2454 }
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;
2463 }
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)++;
2468 }
2469 DEBUG(printk("map_page_to_iovec, exit, *iovix=%d\n", *iovix));
2470 return -1;
2471}
2472
2473
2474
2475static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
2476{
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;
2483
2484 struct ioctl_job_cb_ctx *jc = NULL;
2485
2486 struct page **inpages = NULL;
2487 struct page **outpages = NULL;
2488 int noinpages = 0;
2489 int nooutpages = 0;
2490
2491 struct cryptocop_desc descs[5];
2492
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};
2499
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;
2505
2506 int iovlen = 0;
2507 int iovix = 0;
2508 int pageix = 0;
2509 int pageoffset = 0;
2510
2511 size_t prev_ix = 0;
2512 size_t next_ix;
2513
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;
2519
2520 DEBUG(printk("cryptocop_ioctl_process\n"));
2521
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;
2525 }
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;
2529 }
2530 DEBUG(print_strcop_crypto_op(&oper));
2531
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;
2536 }
2537
2538
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;
2542 }
2543
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;
2547 }
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;
2551 }
2552
2553 cop = kmalloc(sizeof(struct cryptocop_operation), GFP_KERNEL);
2554 if (!cop) {
2555 DEBUG_API(printk("cryptocop_ioctl_process: kmalloc\n"));
2556 return -ENOMEM;
2557 }
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;
2563 }
2564 jc->processed = 0;
2565
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;
2580
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;
2587 }
2588
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;
2596 }
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;
2605 }
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;
2612 }
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;
2620 }
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;
2627 }
2628 }
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;
2634 }
2635
2636 if (oper.decrypt){
2637 ciph_tcfg.flags |= CRYPTOCOP_DECRYPT;
2638 } else {
2639 ciph_tcfg.flags |= CRYPTOCOP_ENCRYPT;
2640 }
2641 ciph_tcfg.next = cop->tfrm_op.tfrm_cfg;
2642 cop->tfrm_op.tfrm_cfg = &ciph_tcfg;
2643 }
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;
2650 }
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;
2657 }
2658 DEBUG(memset(digest_result, 0xff, digest_length));
2659
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;
2667 }
2668
2669 digest_tcfg.next = cop->tfrm_op.tfrm_cfg;
2670 cop->tfrm_op.tfrm_cfg = &digest_tcfg;
2671 }
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;
2676
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;
2682 }
2683
2684 csum_tcfg.next = cop->tfrm_op.tfrm_cfg;
2685 cop->tfrm_op.tfrm_cfg = &csum_tcfg;
2686 }
2687
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;
2694 }
2695 DEBUG(printk("cryptocop_ioctl_process: inlen=%d, cipher_outlen=%d\n", oper.inlen, oper.cipher_outlen));
2696
2697
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;
2706 }
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;
2716 }
2717 }
2718
2719
2720 down_read(¤t->mm->mmap_sem);
2721
2722 err = get_user_pages(current,
2723 current->mm,
2724 (unsigned long int)(oper.indata + prev_ix),
2725 noinpages,
2726 0,
2727 0,
2728 inpages,
2729 NULL);
2730
2731 if (err < 0) {
2732 up_read(¤t->mm->mmap_sem);
2733 nooutpages = noinpages = 0;
2734 DEBUG_API(printk("cryptocop_ioctl_process: get_user_pages indata\n"));
2735 goto error_cleanup;
2736 }
2737 noinpages = err;
2738 if (oper.do_cipher){
2739 err = get_user_pages(current,
2740 current->mm,
2741 (unsigned long int)oper.cipher_outdata,
2742 nooutpages,
2743 1,
2744 0,
2745 outpages,
2746 NULL);
2747 up_read(¤t->mm->mmap_sem);
2748 if (err < 0) {
2749 nooutpages = 0;
2750 DEBUG_API(printk("cryptocop_ioctl_process: get_user_pages outdata\n"));
2751 goto error_cleanup;
2752 }
2753 nooutpages = err;
2754 } else {
2755 up_read(¤t->mm->mmap_sem);
2756 }
2757
2758
2759
2760 cop->tfrm_op.indata = kmalloc((noinpages) * sizeof(struct iovec), GFP_KERNEL);
2761 cop->tfrm_op.outdata = kmalloc((6 + nooutpages) * sizeof(struct iovec), GFP_KERNEL);
2762 if (!cop->tfrm_op.indata || !cop->tfrm_op.outdata) {
2763 DEBUG_API(printk("cryptocop_ioctl_process: kmalloc iovecs\n"));
2764 err = -ENOMEM;
2765 goto error_cleanup;
2766 }
2767
2768 cop->tfrm_op.inlen = oper.inlen - prev_ix;
2769 cop->tfrm_op.outlen = 0;
2770 if (oper.do_cipher) cop->tfrm_op.outlen += oper.cipher_outlen;
2771 if (oper.do_digest) cop->tfrm_op.outlen += digest_length;
2772 if (oper.do_csum) cop->tfrm_op.outlen += 2;
2773
2774
2775 cop->tfrm_op.incount = noinpages;
2776 if (noinpages > 1){
2777 size_t tmplen = cop->tfrm_op.inlen;
2778
2779 cop->tfrm_op.indata[0].iov_len = PAGE_SIZE - ((unsigned long int)(oper.indata + prev_ix) & ~PAGE_MASK);
2780 cop->tfrm_op.indata[0].iov_base = (unsigned char*)page_address(inpages[0]) + ((unsigned long int)(oper.indata + prev_ix) & ~PAGE_MASK);
2781 tmplen -= cop->tfrm_op.indata[0].iov_len;
2782 for (i = 1; i<noinpages; i++){
2783 cop->tfrm_op.indata[i].iov_len = tmplen < PAGE_SIZE ? tmplen : PAGE_SIZE;
2784 cop->tfrm_op.indata[i].iov_base = (unsigned char*)page_address(inpages[i]);
2785 tmplen -= PAGE_SIZE;
2786 }
2787 } else {
2788 cop->tfrm_op.indata[0].iov_len = oper.inlen - prev_ix;
2789 cop->tfrm_op.indata[0].iov_base = (unsigned char*)page_address(inpages[0]) + ((unsigned long int)(oper.indata + prev_ix) & ~PAGE_MASK);
2790 }
2791
2792 iovlen = nooutpages + 6;
2793 pageoffset = oper.do_cipher ? ((unsigned long int)oper.cipher_outdata & ~PAGE_MASK) : 0;
2794
2795 next_ix = next_cfg_change_ix(&oper, prev_ix);
2796 if (prev_ix == next_ix){
2797 DEBUG_API(printk("cryptocop_ioctl_process: length configuration broken.\n"));
2798 err = -EINVAL;
2799 goto error_cleanup;
2800 }
2801 while (prev_ix != next_ix){
2802 end_digest = end_csum = cipher_active = digest_active = csum_active = 0;
2803 descs[desc_ix].cfg = NULL;
2804 descs[desc_ix].length = next_ix - prev_ix;
2805
2806 if (oper.do_cipher && (oper.cipher_start < next_ix) && (prev_ix < (oper.cipher_start + oper.cipher_len))) {
2807 dcfgs[dcfg_ix].tid = CRYPTOCOP_IOCTL_CIPHER_TID;
2808 dcfgs[dcfg_ix].src = cryptocop_source_dma;
2809 cipher_active = 1;
2810
2811 if (next_ix == (oper.cipher_start + oper.cipher_len)){
2812 cipher_done = 1;
2813 dcfgs[dcfg_ix].last = 1;
2814 } else {
2815 dcfgs[dcfg_ix].last = 0;
2816 }
2817 dcfgs[dcfg_ix].next = descs[desc_ix].cfg;
2818 descs[desc_ix].cfg = &dcfgs[dcfg_ix];
2819 ++dcfg_ix;
2820 }
2821 if (oper.do_digest && (oper.digest_start < next_ix) && (prev_ix < (oper.digest_start + oper.digest_len))) {
2822 digest_active = 1;
2823 dcfgs[dcfg_ix].tid = CRYPTOCOP_IOCTL_DIGEST_TID;
2824 dcfgs[dcfg_ix].src = cryptocop_source_dma;
2825 if (next_ix == (oper.digest_start + oper.digest_len)){
2826 assert(!digest_done);
2827 digest_done = 1;
2828 dcfgs[dcfg_ix].last = 1;
2829 } else {
2830 dcfgs[dcfg_ix].last = 0;
2831 }
2832 dcfgs[dcfg_ix].next = descs[desc_ix].cfg;
2833 descs[desc_ix].cfg = &dcfgs[dcfg_ix];
2834 ++dcfg_ix;
2835 }
2836 if (oper.do_csum && (oper.csum_start < next_ix) && (prev_ix < (oper.csum_start + oper.csum_len))){
2837 csum_active = 1;
2838 dcfgs[dcfg_ix].tid = CRYPTOCOP_IOCTL_CSUM_TID;
2839 dcfgs[dcfg_ix].src = cryptocop_source_dma;
2840 if (next_ix == (oper.csum_start + oper.csum_len)){
2841 csum_done = 1;
2842 dcfgs[dcfg_ix].last = 1;
2843 } else {
2844 dcfgs[dcfg_ix].last = 0;
2845 }
2846 dcfgs[dcfg_ix].next = descs[desc_ix].cfg;
2847 descs[desc_ix].cfg = &dcfgs[dcfg_ix];
2848 ++dcfg_ix;
2849 }
2850 if (!descs[desc_ix].cfg){
2851 DEBUG_API(printk("cryptocop_ioctl_process: data segment %d (%d to %d) had no active transforms\n", desc_ix, prev_ix, next_ix));
2852 err = -EINVAL;
2853 goto error_cleanup;
2854 }
2855 descs[desc_ix].next = &(descs[desc_ix]) + 1;
2856 ++desc_ix;
2857 prev_ix = next_ix;
2858 next_ix = next_cfg_change_ix(&oper, prev_ix);
2859 }
2860 if (desc_ix > 0){
2861 descs[desc_ix-1].next = NULL;
2862 } else {
2863 descs[0].next = NULL;
2864 }
2865 if (oper.do_digest) {
2866 DEBUG(printk("cryptocop_ioctl_process: mapping %d byte digest output to iovec %d\n", digest_length, iovix));
2867
2868 cop->tfrm_op.outdata[iovix].iov_base = digest_result;
2869 cop->tfrm_op.outdata[iovix].iov_len = digest_length;
2870 ++iovix;
2871 }
2872 if (oper.do_csum) {
2873
2874 DEBUG(printk("cryptocop_ioctl_process: mapping 2 byte csum output to iovec %d\n", iovix));
2875
2876 cop->tfrm_op.outdata[iovix].iov_base = csum_result;
2877 cop->tfrm_op.outdata[iovix].iov_len = 2;
2878 ++iovix;
2879 }
2880 if (oper.do_cipher) {
2881 if (!map_pages_to_iovec(cop->tfrm_op.outdata, iovlen, &iovix, outpages, nooutpages, &pageix, &pageoffset, oper.cipher_outlen)){
2882 DEBUG_API(printk("cryptocop_ioctl_process: failed to map pages to iovec.\n"));
2883 err = -ENOSYS;
2884 goto error_cleanup;
2885 }
2886 }
2887 DEBUG(printk("cryptocop_ioctl_process: setting cop->tfrm_op.outcount %d\n", iovix));
2888 cop->tfrm_op.outcount = iovix;
2889 assert(iovix <= (nooutpages + 6));
2890
2891 cop->sid = oper.ses_id;
2892 cop->tfrm_op.desc = &descs[0];
2893
2894 DEBUG(printk("cryptocop_ioctl_process: inserting job, cb_data=0x%p\n", cop->cb_data));
2895
2896 if ((err = cryptocop_job_queue_insert_user_job(cop)) != 0) {
2897 DEBUG_API(printk("cryptocop_ioctl_process: insert job %d\n", err));
2898 err = -EINVAL;
2899 goto error_cleanup;
2900 }
2901
2902 DEBUG(printk("cryptocop_ioctl_process: begin wait for result\n"));
2903
2904 wait_event(cryptocop_ioc_process_wq, (jc->processed != 0));
2905 DEBUG(printk("cryptocop_ioctl_process: end wait for result\n"));
2906 if (!jc->processed){
2907 printk(KERN_WARNING "cryptocop_ioctl_process: job not processed at completion\n");
2908 err = -EIO;
2909 goto error_cleanup;
2910 }
2911
2912
2913 DEBUG(printk("cryptocop_ioctl_process: operation_status = %d\n", cop->operation_status));
2914 if (cop->operation_status == 0){
2915 if (oper.do_digest){
2916 DEBUG(printk("cryptocop_ioctl_process: copy %d bytes digest to user\n", digest_length));
2917 err = copy_to_user((unsigned char*)crp_oper + offsetof(struct strcop_crypto_op, digest), digest_result, digest_length);
2918 if (0 != err){
2919 DEBUG_API(printk("cryptocop_ioctl_process: copy_to_user, digest length %d, err %d\n", digest_length, err));
2920 err = -EFAULT;
2921 goto error_cleanup;
2922 }
2923 }
2924 if (oper.do_csum){
2925 DEBUG(printk("cryptocop_ioctl_process: copy 2 bytes checksum to user\n"));
2926 err = copy_to_user((unsigned char*)crp_oper + offsetof(struct strcop_crypto_op, csum), csum_result, 2);
2927 if (0 != err){
2928 DEBUG_API(printk("cryptocop_ioctl_process: copy_to_user, csum, err %d\n", err));
2929 err = -EFAULT;
2930 goto error_cleanup;
2931 }
2932 }
2933 err = 0;
2934 } else {
2935 DEBUG(printk("cryptocop_ioctl_process: returning err = operation_status = %d\n", cop->operation_status));
2936 err = cop->operation_status;
2937 }
2938
2939 error_cleanup:
2940
2941 for (i = 0; i < noinpages; i++){
2942 put_page(inpages[i]);
2943 }
2944 for (i = 0; i < nooutpages; i++){
2945 int spdl_err;
2946
2947 spdl_err = set_page_dirty_lock(outpages[i]);
2948 DEBUG(if (spdl_err < 0)printk("cryptocop_ioctl_process: set_page_dirty_lock returned %d\n", spdl_err));
2949 }
2950 for (i = 0; i < nooutpages; i++){
2951 put_page(outpages[i]);
2952 }
2953
2954 kfree(digest_result);
2955 kfree(inpages);
2956 kfree(outpages);
2957 if (cop){
2958 kfree(cop->tfrm_op.indata);
2959 kfree(cop->tfrm_op.outdata);
2960 kfree(cop);
2961 }
2962 kfree(jc);
2963
2964 DEBUG(print_lock_status());
2965
2966 return err;
2967}
2968
2969
2970static int cryptocop_ioctl_create_session(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
2971{
2972 cryptocop_session_id sid;
2973 int err;
2974 struct cryptocop_private *dev;
2975 struct strcop_session_op *sess_op = (struct strcop_session_op *)arg;
2976 struct strcop_session_op sop;
2977 struct cryptocop_transform_init *tis = NULL;
2978 struct cryptocop_transform_init ti_cipher = {0};
2979 struct cryptocop_transform_init ti_digest = {0};
2980 struct cryptocop_transform_init ti_csum = {0};
2981
2982 if (!access_ok(VERIFY_WRITE, sess_op, sizeof(struct strcop_session_op)))
2983 return -EFAULT;
2984 err = copy_from_user(&sop, sess_op, sizeof(struct strcop_session_op));
2985 if (err) return -EFAULT;
2986 if (sop.cipher != cryptocop_cipher_none) {
2987 if (!access_ok(VERIFY_READ, sop.key, sop.keylen)) return -EFAULT;
2988 }
2989 DEBUG(printk("cryptocop_ioctl_create_session, sess_op:\n"));
2990
2991 DEBUG(printk("\tcipher:%d\n"
2992 "\tcipher_mode:%d\n"
2993 "\tdigest:%d\n"
2994 "\tcsum:%d\n",
2995 (int)sop.cipher,
2996 (int)sop.cmode,
2997 (int)sop.digest,
2998 (int)sop.csum));
2999
3000 if (sop.cipher != cryptocop_cipher_none){
3001
3002 switch (sop.cipher){
3003 case cryptocop_cipher_des:
3004 ti_cipher.alg = cryptocop_alg_des;
3005 break;
3006 case cryptocop_cipher_3des:
3007 ti_cipher.alg = cryptocop_alg_3des;
3008 break;
3009 case cryptocop_cipher_aes:
3010 ti_cipher.alg = cryptocop_alg_aes;
3011 break;
3012 default:
3013 DEBUG_API(printk("create session, bad cipher algorithm %d\n", sop.cipher));
3014 return -EINVAL;
3015 };
3016 DEBUG(printk("setting cipher transform %d\n", ti_cipher.alg));
3017 copy_from_user(ti_cipher.key, sop.key, sop.keylen/8);
3018 ti_cipher.keylen = sop.keylen;
3019 switch (sop.cmode){
3020 case cryptocop_cipher_mode_cbc:
3021 case cryptocop_cipher_mode_ecb:
3022 ti_cipher.cipher_mode = sop.cmode;
3023 break;
3024 default:
3025 DEBUG_API(printk("create session, bad cipher mode %d\n", sop.cmode));
3026 return -EINVAL;
3027 }
3028 DEBUG(printk("cryptocop_ioctl_create_session: setting CBC mode %d\n", ti_cipher.cipher_mode));
3029 switch (sop.des3_mode){
3030 case cryptocop_3des_eee:
3031 case cryptocop_3des_eed:
3032 case cryptocop_3des_ede:
3033 case cryptocop_3des_edd:
3034 case cryptocop_3des_dee:
3035 case cryptocop_3des_ded:
3036 case cryptocop_3des_dde:
3037 case cryptocop_3des_ddd:
3038 ti_cipher.tdes_mode = sop.des3_mode;
3039 break;
3040 default:
3041 DEBUG_API(printk("create session, bad 3DES mode %d\n", sop.des3_mode));
3042 return -EINVAL;
3043 }
3044 ti_cipher.tid = CRYPTOCOP_IOCTL_CIPHER_TID;
3045 ti_cipher.next = tis;
3046 tis = &ti_cipher;
3047 }
3048 if (sop.digest != cryptocop_digest_none){
3049 DEBUG(printk("setting digest transform\n"));
3050 switch (sop.digest){
3051 case cryptocop_digest_md5:
3052 ti_digest.alg = cryptocop_alg_md5;
3053 break;
3054 case cryptocop_digest_sha1:
3055 ti_digest.alg = cryptocop_alg_sha1;
3056 break;
3057 default:
3058 DEBUG_API(printk("create session, bad digest algorithm %d\n", sop.digest));
3059 return -EINVAL;
3060 }
3061 ti_digest.tid = CRYPTOCOP_IOCTL_DIGEST_TID;
3062 ti_digest.next = tis;
3063 tis = &ti_digest;
3064 }
3065 if (sop.csum != cryptocop_csum_none){
3066 DEBUG(printk("setting csum transform\n"));
3067 switch (sop.csum){
3068 case cryptocop_csum_le:
3069 case cryptocop_csum_be:
3070 ti_csum.csum_mode = sop.csum;
3071 break;
3072 default:
3073 DEBUG_API(printk("create session, bad checksum algorithm %d\n", sop.csum));
3074 return -EINVAL;
3075 }
3076 ti_csum.alg = cryptocop_alg_csum;
3077 ti_csum.tid = CRYPTOCOP_IOCTL_CSUM_TID;
3078 ti_csum.next = tis;
3079 tis = &ti_csum;
3080 }
3081 dev = kmalloc(sizeof(struct cryptocop_private), GFP_KERNEL);
3082 if (!dev){
3083 DEBUG_API(printk("create session, alloc dev\n"));
3084 return -ENOMEM;
3085 }
3086
3087 err = cryptocop_new_session(&sid, tis, GFP_KERNEL);
3088 DEBUG({ if (err) printk("create session, cryptocop_new_session %d\n", err);});
3089
3090 if (err) {
3091 kfree(dev);
3092 return err;
3093 }
3094 sess_op->ses_id = sid;
3095 dev->sid = sid;
3096 dev->next = filp->private_data;
3097 filp->private_data = dev;
3098
3099 return 0;
3100}
3101
3102static long cryptocop_ioctl_unlocked(struct inode *inode,
3103 struct file *filp, unsigned int cmd, unsigned long arg)
3104{
3105 int err = 0;
3106 if (_IOC_TYPE(cmd) != ETRAXCRYPTOCOP_IOCTYPE) {
3107 DEBUG_API(printk("cryptocop_ioctl: wrong type\n"));
3108 return -ENOTTY;
3109 }
3110 if (_IOC_NR(cmd) > CRYPTOCOP_IO_MAXNR){
3111 return -ENOTTY;
3112 }
3113
3114
3115 if (_IOC_DIR(cmd) & _IOC_READ)
3116 err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
3117 else if (_IOC_DIR(cmd) & _IOC_WRITE)
3118 err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
3119 if (err) return -EFAULT;
3120
3121 switch (cmd) {
3122 case CRYPTOCOP_IO_CREATE_SESSION:
3123 return cryptocop_ioctl_create_session(inode, filp, cmd, arg);
3124 case CRYPTOCOP_IO_CLOSE_SESSION:
3125 return cryptocop_ioctl_close_session(inode, filp, cmd, arg);
3126 case CRYPTOCOP_IO_PROCESS_OP:
3127 return cryptocop_ioctl_process(inode, filp, cmd, arg);
3128 default:
3129 DEBUG_API(printk("cryptocop_ioctl: unknown command\n"));
3130 return -ENOTTY;
3131 }
3132 return 0;
3133}
3134
3135static long
3136cryptocop_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
3137{
3138 long ret;
3139
3140 mutex_lock(&cryptocop_mutex);
3141 ret = cryptocop_ioctl_unlocked(file_inode(filp), filp, cmd, arg);
3142 mutex_unlock(&cryptocop_mutex);
3143
3144 return ret;
3145}
3146
3147
3148#ifdef LDEBUG
3149static void print_dma_descriptors(struct cryptocop_int_operation *iop)
3150{
3151 struct cryptocop_dma_desc *cdesc_out = iop->cdesc_out;
3152 struct cryptocop_dma_desc *cdesc_in = iop->cdesc_in;
3153 int i;
3154
3155 printk("print_dma_descriptors start\n");
3156
3157 printk("iop:\n");
3158 printk("\tsid: 0x%lld\n", iop->sid);
3159
3160 printk("\tcdesc_out: 0x%p\n", iop->cdesc_out);
3161 printk("\tcdesc_in: 0x%p\n", iop->cdesc_in);
3162 printk("\tddesc_out: 0x%p\n", iop->ddesc_out);
3163 printk("\tddesc_in: 0x%p\n", iop->ddesc_in);
3164
3165 printk("\niop->ctx_out: 0x%p phys: 0x%p\n", &iop->ctx_out, (char*)virt_to_phys(&iop->ctx_out));
3166 printk("\tnext: 0x%p\n"
3167 "\tsaved_data: 0x%p\n"
3168 "\tsaved_data_buf: 0x%p\n",
3169 iop->ctx_out.next,
3170 iop->ctx_out.saved_data,
3171 iop->ctx_out.saved_data_buf);
3172
3173 printk("\niop->ctx_in: 0x%p phys: 0x%p\n", &iop->ctx_in, (char*)virt_to_phys(&iop->ctx_in));
3174 printk("\tnext: 0x%p\n"
3175 "\tsaved_data: 0x%p\n"
3176 "\tsaved_data_buf: 0x%p\n",
3177 iop->ctx_in.next,
3178 iop->ctx_in.saved_data,
3179 iop->ctx_in.saved_data_buf);
3180
3181 i = 0;
3182 while (cdesc_out) {
3183 dma_descr_data *td;
3184 printk("cdesc_out %d, desc=0x%p\n", i, cdesc_out->dma_descr);
3185 printk("\n\tvirt_to_phys(desc): 0x%p\n", (char*)virt_to_phys(cdesc_out->dma_descr));
3186 td = cdesc_out->dma_descr;
3187 printk("\n\tbuf: 0x%p\n"
3188 "\tafter: 0x%p\n"
3189 "\tmd: 0x%04x\n"
3190 "\tnext: 0x%p\n",
3191 td->buf,
3192 td->after,
3193 td->md,
3194 td->next);
3195 printk("flags:\n"
3196 "\twait:\t%d\n"
3197 "\teol:\t%d\n"
3198 "\touteop:\t%d\n"
3199 "\tineop:\t%d\n"
3200 "\tintr:\t%d\n",
3201 td->wait,
3202 td->eol,
3203 td->out_eop,
3204 td->in_eop,
3205 td->intr);
3206 cdesc_out = cdesc_out->next;
3207 i++;
3208 }
3209 i = 0;
3210 while (cdesc_in) {
3211 dma_descr_data *td;
3212 printk("cdesc_in %d, desc=0x%p\n", i, cdesc_in->dma_descr);
3213 printk("\n\tvirt_to_phys(desc): 0x%p\n", (char*)virt_to_phys(cdesc_in->dma_descr));
3214 td = cdesc_in->dma_descr;
3215 printk("\n\tbuf: 0x%p\n"
3216 "\tafter: 0x%p\n"
3217 "\tmd: 0x%04x\n"
3218 "\tnext: 0x%p\n",
3219 td->buf,
3220 td->after,
3221 td->md,
3222 td->next);
3223 printk("flags:\n"
3224 "\twait:\t%d\n"
3225 "\teol:\t%d\n"
3226 "\touteop:\t%d\n"
3227 "\tineop:\t%d\n"
3228 "\tintr:\t%d\n",
3229 td->wait,
3230 td->eol,
3231 td->out_eop,
3232 td->in_eop,
3233 td->intr);
3234 cdesc_in = cdesc_in->next;
3235 i++;
3236 }
3237
3238 printk("print_dma_descriptors end\n");
3239}
3240
3241
3242static void print_strcop_crypto_op(struct strcop_crypto_op *cop)
3243{
3244 printk("print_strcop_crypto_op, 0x%p\n", cop);
3245
3246
3247 printk("indata=0x%p\n"
3248 "inlen=%d\n"
3249 "do_cipher=%d\n"
3250 "decrypt=%d\n"
3251 "cipher_explicit=%d\n"
3252 "cipher_start=%d\n"
3253 "cipher_len=%d\n"
3254 "outdata=0x%p\n"
3255 "outlen=%d\n",
3256 cop->indata,
3257 cop->inlen,
3258 cop->do_cipher,
3259 cop->decrypt,
3260 cop->cipher_explicit,
3261 cop->cipher_start,
3262 cop->cipher_len,
3263 cop->cipher_outdata,
3264 cop->cipher_outlen);
3265
3266 printk("do_digest=%d\n"
3267 "digest_start=%d\n"
3268 "digest_len=%d\n",
3269 cop->do_digest,
3270 cop->digest_start,
3271 cop->digest_len);
3272
3273 printk("do_csum=%d\n"
3274 "csum_start=%d\n"
3275 "csum_len=%d\n",
3276 cop->do_csum,
3277 cop->csum_start,
3278 cop->csum_len);
3279}
3280
3281static void print_cryptocop_operation(struct cryptocop_operation *cop)
3282{
3283 struct cryptocop_desc *d;
3284 struct cryptocop_tfrm_cfg *tc;
3285 struct cryptocop_desc_cfg *dc;
3286 int i;
3287
3288 printk("print_cryptocop_operation, cop=0x%p\n\n", cop);
3289 printk("sid: %lld\n", cop->sid);
3290 printk("operation_status=%d\n"
3291 "use_dmalists=%d\n"
3292 "in_interrupt=%d\n"
3293 "fast_callback=%d\n",
3294 cop->operation_status,
3295 cop->use_dmalists,
3296 cop->in_interrupt,
3297 cop->fast_callback);
3298
3299 if (cop->use_dmalists){
3300 print_user_dma_lists(&cop->list_op);
3301 } else {
3302 printk("cop->tfrm_op\n"
3303 "tfrm_cfg=0x%p\n"
3304 "desc=0x%p\n"
3305 "indata=0x%p\n"
3306 "incount=%d\n"
3307 "inlen=%d\n"
3308 "outdata=0x%p\n"
3309 "outcount=%d\n"
3310 "outlen=%d\n\n",
3311 cop->tfrm_op.tfrm_cfg,
3312 cop->tfrm_op.desc,
3313 cop->tfrm_op.indata,
3314 cop->tfrm_op.incount,
3315 cop->tfrm_op.inlen,
3316 cop->tfrm_op.outdata,
3317 cop->tfrm_op.outcount,
3318 cop->tfrm_op.outlen);
3319
3320 tc = cop->tfrm_op.tfrm_cfg;
3321 while (tc){
3322 printk("tfrm_cfg, 0x%p\n"
3323 "tid=%d\n"
3324 "flags=%d\n"
3325 "inject_ix=%d\n"
3326 "next=0x%p\n",
3327 tc,
3328 tc->tid,
3329 tc->flags,
3330 tc->inject_ix,
3331 tc->next);
3332 tc = tc->next;
3333 }
3334 d = cop->tfrm_op.desc;
3335 while (d){
3336 printk("\n======================desc, 0x%p\n"
3337 "length=%d\n"
3338 "cfg=0x%p\n"
3339 "next=0x%p\n",
3340 d,
3341 d->length,
3342 d->cfg,
3343 d->next);
3344 dc = d->cfg;
3345 while (dc){
3346 printk("=========desc_cfg, 0x%p\n"
3347 "tid=%d\n"
3348 "src=%d\n"
3349 "last=%d\n"
3350 "next=0x%p\n",
3351 dc,
3352 dc->tid,
3353 dc->src,
3354 dc->last,
3355 dc->next);
3356 dc = dc->next;
3357 }
3358 d = d->next;
3359 }
3360 printk("\n====iniov\n");
3361 for (i = 0; i < cop->tfrm_op.incount; i++){
3362 printk("indata[%d]\n"
3363 "base=0x%p\n"
3364 "len=%d\n",
3365 i,
3366 cop->tfrm_op.indata[i].iov_base,
3367 cop->tfrm_op.indata[i].iov_len);
3368 }
3369 printk("\n====outiov\n");
3370 for (i = 0; i < cop->tfrm_op.outcount; i++){
3371 printk("outdata[%d]\n"
3372 "base=0x%p\n"
3373 "len=%d\n",
3374 i,
3375 cop->tfrm_op.outdata[i].iov_base,
3376 cop->tfrm_op.outdata[i].iov_len);
3377 }
3378 }
3379 printk("------------end print_cryptocop_operation\n");
3380}
3381
3382
3383static void print_user_dma_lists(struct cryptocop_dma_list_operation *dma_op)
3384{
3385 dma_descr_data *dd;
3386 int i;
3387
3388 printk("print_user_dma_lists, dma_op=0x%p\n", dma_op);
3389
3390 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));
3391 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));
3392
3393 printk("##############outlist\n");
3394 dd = phys_to_virt((unsigned long int)dma_op->outlist);
3395 i = 0;
3396 while (dd != NULL) {
3397 printk("#%d phys_to_virt(desc) 0x%p\n", i, dd);
3398 printk("\n\tbuf: 0x%p\n"
3399 "\tafter: 0x%p\n"
3400 "\tmd: 0x%04x\n"
3401 "\tnext: 0x%p\n",
3402 dd->buf,
3403 dd->after,
3404 dd->md,
3405 dd->next);
3406 printk("flags:\n"
3407 "\twait:\t%d\n"
3408 "\teol:\t%d\n"
3409 "\touteop:\t%d\n"
3410 "\tineop:\t%d\n"
3411 "\tintr:\t%d\n",
3412 dd->wait,
3413 dd->eol,
3414 dd->out_eop,
3415 dd->in_eop,
3416 dd->intr);
3417 if (dd->eol)
3418 dd = NULL;
3419 else
3420 dd = phys_to_virt((unsigned long int)dd->next);
3421 ++i;
3422 }
3423
3424 printk("##############inlist\n");
3425 dd = phys_to_virt((unsigned long int)dma_op->inlist);
3426 i = 0;
3427 while (dd != NULL) {
3428 printk("#%d phys_to_virt(desc) 0x%p\n", i, dd);
3429 printk("\n\tbuf: 0x%p\n"
3430 "\tafter: 0x%p\n"
3431 "\tmd: 0x%04x\n"
3432 "\tnext: 0x%p\n",
3433 dd->buf,
3434 dd->after,
3435 dd->md,
3436 dd->next);
3437 printk("flags:\n"
3438 "\twait:\t%d\n"
3439 "\teol:\t%d\n"
3440 "\touteop:\t%d\n"
3441 "\tineop:\t%d\n"
3442 "\tintr:\t%d\n",
3443 dd->wait,
3444 dd->eol,
3445 dd->out_eop,
3446 dd->in_eop,
3447 dd->intr);
3448 if (dd->eol)
3449 dd = NULL;
3450 else
3451 dd = phys_to_virt((unsigned long int)dd->next);
3452 ++i;
3453 }
3454}
3455
3456
3457static void print_lock_status(void)
3458{
3459 printk("**********************print_lock_status\n");
3460 printk("cryptocop_completed_jobs_lock %d\n", spin_is_locked(&cryptocop_completed_jobs_lock));
3461 printk("cryptocop_job_queue_lock %d\n", spin_is_locked(&cryptocop_job_queue_lock));
3462 printk("descr_pool_lock %d\n", spin_is_locked(&descr_pool_lock));
3463 printk("cryptocop_sessions_lock %d\n", spin_is_locked(cryptocop_sessions_lock));
3464 printk("running_job_lock %d\n", spin_is_locked(running_job_lock));
3465 printk("cryptocop_process_lock %d\n", spin_is_locked(cryptocop_process_lock));
3466}
3467#endif
3468
3469
3470static const char cryptocop_name[] = "ETRAX FS stream co-processor";
3471
3472static int init_stream_coprocessor(void)
3473{
3474 int err;
3475 int i;
3476 static int initialized = 0;
3477
3478 if (initialized)
3479 return 0;
3480
3481 initialized = 1;
3482
3483 printk("ETRAX FS stream co-processor driver v0.01, (c) 2003 Axis Communications AB\n");
3484
3485 err = register_chrdev(CRYPTOCOP_MAJOR, cryptocop_name, &cryptocop_fops);
3486 if (err < 0) {
3487 printk(KERN_ERR "stream co-processor: could not get major number.\n");
3488 return err;
3489 }
3490
3491 err = init_cryptocop();
3492 if (err) {
3493 (void)unregister_chrdev(CRYPTOCOP_MAJOR, cryptocop_name);
3494 return err;
3495 }
3496 err = cryptocop_job_queue_init();
3497 if (err) {
3498 release_cryptocop();
3499 (void)unregister_chrdev(CRYPTOCOP_MAJOR, cryptocop_name);
3500 return err;
3501 }
3502
3503 for (i = 0; i < CRYPTOCOP_DESCRIPTOR_POOL_SIZE - 1; i++) {
3504 descr_pool[i].from_pool = 1;
3505 descr_pool[i].next = &descr_pool[i + 1];
3506 }
3507 descr_pool[i].from_pool = 1;
3508 descr_pool[i].next = NULL;
3509 descr_pool_free_list = &descr_pool[0];
3510 descr_pool_no_free = CRYPTOCOP_DESCRIPTOR_POOL_SIZE;
3511
3512 spin_lock_init(&cryptocop_completed_jobs_lock);
3513 spin_lock_init(&cryptocop_job_queue_lock);
3514 spin_lock_init(&descr_pool_lock);
3515 spin_lock_init(&cryptocop_sessions_lock);
3516 spin_lock_init(&running_job_lock);
3517 spin_lock_init(&cryptocop_process_lock);
3518
3519 cryptocop_sessions = NULL;
3520 next_sid = 1;
3521
3522 cryptocop_running_job = NULL;
3523
3524 printk("stream co-processor: init done.\n");
3525 return 0;
3526}
3527
3528static void __exit exit_stream_coprocessor(void)
3529{
3530 release_cryptocop();
3531 cryptocop_job_queue_close();
3532}
3533
3534module_init(init_stream_coprocessor);
3535module_exit(exit_stream_coprocessor);
3536
3537