1 /*
2 * Stream co-processor driver for the ETRAX FS
3 *
4 * Copyright (C) 2003-2007 Axis Communications AB
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/smp_lock.h>
15 #include <linux/spinlock.h>
16 #include <linux/stddef.h>
17
18 #include <asm/uaccess.h>
19 #include <asm/io.h>
20 #include <asm/atomic.h>
21
22 #include <linux/list.h>
23 #include <linux/interrupt.h>
24
25 #include <asm/signal.h>
26 #include <asm/irq.h>
27
28 #include <dma.h>
29 #include <hwregs/dma.h>
30 #include <hwregs/reg_map.h>
31 #include <hwregs/reg_rdwr.h>
32 #include <hwregs/intr_vect_defs.h>
33
34 #include <hwregs/strcop.h>
35 #include <hwregs/strcop_defs.h>
36 #include <cryptocop.h>
37
38 #ifdef CONFIG_ETRAXFS
39 #define IN_DMA 9
40 #define OUT_DMA 8
41 #define IN_DMA_INST regi_dma9
42 #define OUT_DMA_INST regi_dma8
43 #define DMA_IRQ DMA9_INTR_VECT
44 #else
45 #define IN_DMA 3
46 #define OUT_DMA 2
47 #define IN_DMA_INST regi_dma3
48 #define OUT_DMA_INST regi_dma2
49 #define DMA_IRQ DMA3_INTR_VECT
50 #endif
51
52 #define DESCR_ALLOC_PAD (31)
53
54 struct cryptocop_dma_desc {
55 char *free_buf; /* If non-null will be kfreed in free_cdesc() */
56 dma_descr_data *dma_descr;
57
58 unsigned char dma_descr_buf[sizeof(dma_descr_data) + DESCR_ALLOC_PAD];
59
60 unsigned int from_pool:1; /* If 1 'allocated' from the descriptor pool. */
61 struct cryptocop_dma_desc *next;
62 };
63
64
65 struct cryptocop_int_operation{
66 void *alloc_ptr;
67 cryptocop_session_id sid;
68
69 dma_descr_context ctx_out;
70 dma_descr_context ctx_in;
71
72 /* DMA descriptors allocated by driver. */
73 struct cryptocop_dma_desc *cdesc_out;
74 struct cryptocop_dma_desc *cdesc_in;
75
76 /* Strcop config to use. */
77 cryptocop_3des_mode tdes_mode;
78 cryptocop_csum_type csum_mode;
79
80 /* DMA descrs provided by consumer. */
81 dma_descr_data *ddesc_out;
82 dma_descr_data *ddesc_in;
83 };
84
85
86 struct cryptocop_tfrm_ctx {
87 cryptocop_tfrm_id tid;
88 unsigned int blocklength;
89
90 unsigned int start_ix;
91
92 struct cryptocop_tfrm_cfg *tcfg;
93 struct cryptocop_transform_ctx *tctx;
94
95 unsigned char previous_src;
96 unsigned char current_src;
97
98 /* Values to use in metadata out. */
99 unsigned char hash_conf;
100 unsigned char hash_mode;
101 unsigned char ciph_conf;
102 unsigned char cbcmode;
103 unsigned char decrypt;
104
105 unsigned int requires_padding:1;
106 unsigned int strict_block_length:1;
107 unsigned int active:1;
108 unsigned int done:1;
109 size_t consumed;
110 size_t produced;
111
112 /* Pad (input) descriptors to put in the DMA out list when the transform
113 * output is put on the DMA in list. */
114 struct cryptocop_dma_desc *pad_descs;
115
116 struct cryptocop_tfrm_ctx *prev_src;
117 struct cryptocop_tfrm_ctx *curr_src;
118
119 /* Mapping to HW. */
120 unsigned char unit_no;
121 };
122
123
124 struct cryptocop_private{
125 cryptocop_session_id sid;
126 struct cryptocop_private *next;
127 };
128
129 /* Session list. */
130
131 struct cryptocop_transform_ctx{
132 struct cryptocop_transform_init init;
133 unsigned char dec_key[CRYPTOCOP_MAX_KEY_LENGTH];
134 unsigned int dec_key_set:1;
135
136 struct cryptocop_transform_ctx *next;
137 };
138
139
140 struct cryptocop_session{
141 cryptocop_session_id sid;
142
143 struct cryptocop_transform_ctx *tfrm_ctx;
144
145 struct cryptocop_session *next;
146 };
147
148 /* Priority levels for jobs sent to the cryptocop. Checksum operations from
149 kernel have highest priority since TCPIP stack processing must not
150 be a bottleneck. */
151 typedef enum {
152 cryptocop_prio_kernel_csum = 0,
153 cryptocop_prio_kernel = 1,
154 cryptocop_prio_user = 2,
155 cryptocop_prio_no_prios = 3
156 } cryptocop_queue_priority;
157
158 struct cryptocop_prio_queue{
159 struct list_head jobs;
160 cryptocop_queue_priority prio;
161 };
162
163 struct cryptocop_prio_job{
164 struct list_head node;
165 cryptocop_queue_priority prio;
166
167 struct cryptocop_operation *oper;
168 struct cryptocop_int_operation *iop;
169 };
170
171 struct ioctl_job_cb_ctx {
172 unsigned int processed:1;
173 };
174
175
176 static struct cryptocop_session *cryptocop_sessions = NULL;
177 spinlock_t cryptocop_sessions_lock;
178
179 /* Next Session ID to assign. */
180 static cryptocop_session_id next_sid = 1;
181
182 /* Pad for checksum. */
183 static const char csum_zero_pad[1] = {0x00};
184
185 /* Trash buffer for mem2mem operations. */
186 #define MEM2MEM_DISCARD_BUF_LENGTH (512)
187 static unsigned char mem2mem_discard_buf[MEM2MEM_DISCARD_BUF_LENGTH];
188
189 /* Descriptor pool. */
190 /* FIXME Tweak this value. */
191 #define CRYPTOCOP_DESCRIPTOR_POOL_SIZE (100)
192 static struct cryptocop_dma_desc descr_pool[CRYPTOCOP_DESCRIPTOR_POOL_SIZE];
193 static struct cryptocop_dma_desc *descr_pool_free_list;
194 static int descr_pool_no_free;
195 static spinlock_t descr_pool_lock;
196
197 /* Lock to stop cryptocop to start processing of a new operation. The holder
198 of this lock MUST call cryptocop_start_job() after it is unlocked. */
199 spinlock_t cryptocop_process_lock;
200
201 static struct cryptocop_prio_queue cryptocop_job_queues[cryptocop_prio_no_prios];
202 static spinlock_t cryptocop_job_queue_lock;
203 static struct cryptocop_prio_job *cryptocop_running_job = NULL;
204 static spinlock_t running_job_lock;
205
206 /* The interrupt handler appends completed jobs to this list. The scehduled
207 * tasklet removes them upon sending the response to the crypto consumer. */
208 static struct list_head cryptocop_completed_jobs;
209 static spinlock_t cryptocop_completed_jobs_lock;
210
211 DECLARE_WAIT_QUEUE_HEAD(cryptocop_ioc_process_wq);
212
213
214 /** Local functions. **/
215
216 static int cryptocop_open(struct inode *, struct file *);
217
218 static int cryptocop_release(struct inode *, struct file *);
219
220 static int cryptocop_ioctl(struct inode *inode, struct file *file,
221 unsigned int cmd, unsigned long arg);
222
223 static void cryptocop_start_job(void);
224
225 static int cryptocop_job_queue_insert(cryptocop_queue_priority prio, struct cryptocop_operation *operation);
226 static int cryptocop_job_setup(struct cryptocop_prio_job **pj, struct cryptocop_operation *operation);
227
228 static int cryptocop_job_queue_init(void);
229 static void cryptocop_job_queue_close(void);
230
231 static int create_md5_pad(int alloc_flag, unsigned long long hashed_length, char **pad, size_t *pad_length);
232
233 static int create_sha1_pad(int alloc_flag, unsigned long long hashed_length, char **pad, size_t *pad_length);
234
235 static int transform_ok(struct cryptocop_transform_init *tinit);
236
237 static struct cryptocop_session *get_session(cryptocop_session_id sid);
238
239 static struct cryptocop_transform_ctx *get_transform_ctx(struct cryptocop_session *sess, cryptocop_tfrm_id tid);
240
241 static void delete_internal_operation(struct cryptocop_int_operation *iop);
242
243 static void get_aes_decrypt_key(unsigned char *dec_key, const unsigned char *key, unsigned int keylength);
244
245 static int init_stream_coprocessor(void);
246
247 static void __exit exit_stream_coprocessor(void);
248
249 /*#define LDEBUG*/
250 #ifdef LDEBUG
251 #define DEBUG(s) s
252 #define DEBUG_API(s) s
253 static void print_cryptocop_operation(struct cryptocop_operation *cop);
254 static void print_dma_descriptors(struct cryptocop_int_operation *iop);
255 static void print_strcop_crypto_op(struct strcop_crypto_op *cop);
256 static void print_lock_status(void);
257 static void print_user_dma_lists(struct cryptocop_dma_list_operation *dma_op);
258 #define assert(s) do{if (!(s)) panic(#s);} while(0);
259 #else
260 #define DEBUG(s)
261 #define DEBUG_API(s)
262 #define assert(s)
263 #endif
264
265
266 /* Transform constants. */
267 #define DES_BLOCK_LENGTH (8)
268 #define AES_BLOCK_LENGTH (16)
269 #define MD5_BLOCK_LENGTH (64)
270 #define SHA1_BLOCK_LENGTH (64)
271 #define CSUM_BLOCK_LENGTH (2)
272 #define MD5_STATE_LENGTH (16)
273 #define SHA1_STATE_LENGTH (20)
274
275 /* The device number. */
276 #define CRYPTOCOP_MAJOR (254)
277 #define CRYPTOCOP_MINOR (0)
278
279
280
281 const struct file_operations cryptocop_fops = {
282 .owner = THIS_MODULE,
283 .open = cryptocop_open,
284 .release = cryptocop_release,
285 .ioctl = cryptocop_ioctl
286 };
287
288
free_cdesc(struct cryptocop_dma_desc * cdesc)289 static 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
alloc_cdesc(int alloc_flag)307 static 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
setup_descr_chain(struct cryptocop_dma_desc * cd)351 static 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 /* Create a pad descriptor for the transform.
367 * Return -1 for error, 0 if pad created. */
create_pad_descriptor(struct cryptocop_tfrm_ctx * tc,struct cryptocop_dma_desc ** pad_desc,int alloc_flag)368 static 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 /* Setup pad descriptor. */
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; /* Use any pointer. */
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; /* Since this is a pad output is pushed. EOP is ok here since the padded unit is the only one active. */
425 cdesc->dma_descr->buf = (char*)virt_to_phys((char*)pad);
426 cdesc->dma_descr->after = cdesc->dma_descr->buf + plen;
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
setup_key_dl_desc(struct cryptocop_tfrm_ctx * tc,struct cryptocop_dma_desc ** kd,int alloc_flag)439 static 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 /* Download key. */
452 if ((tc->tctx->init.alg == cryptocop_alg_aes) && (tc->tcfg->flags & CRYPTOCOP_DECRYPT)) {
453 /* Precook the AES decrypt key. */
454 if (!tc->tctx->dec_key_set){
455 get_aes_decrypt_key(tc->tctx->dec_key, tc->tctx->init.key, tc->tctx->init.keylen);
456 tc->tctx->dec_key_set = 1;
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 /* Setup metadata. */
465 mo.dlkey = 1;
466 switch (tc->tctx->init.keylen) {
467 case 64:
468 mo.decrypt = 0;
469 mo.hashmode = 0;
470 break;
471 case 128:
472 mo.decrypt = 0;
473 mo.hashmode = 1;
474 break;
475 case 192:
476 mo.decrypt = 1;
477 mo.hashmode = 0;
478 break;
479 case 256:
480 mo.decrypt = 1;
481 mo.hashmode = 1;
482 break;
483 default:
484 break;
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
setup_cipher_iv_desc(struct cryptocop_tfrm_ctx * tc,struct cryptocop_dma_desc ** id,int alloc_flag)497 static 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 /* Download IV. */
509 iv_desc->dma_descr->buf = (char*)virt_to_phys(tc->tcfg->iv);
510 iv_desc->dma_descr->after = iv_desc->dma_descr->buf + tc->blocklength;
511
512 /* Setup metadata. */
513 mo.hashsel = mo.csumsel = src_none;
514 mo.ciphsel = src_dma;
515 mo.ciphconf = tc->ciph_conf;
516 mo.cbcmode = tc->cbcmode;
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 /* Map the ouput length of the transform to operation output starting on the inject index. */
create_input_descriptors(struct cryptocop_operation * operation,struct cryptocop_tfrm_ctx * tc,struct cryptocop_dma_desc ** id,int alloc_flag)529 static 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 /* Traverse the out iovec until the result inject index is reached. */
549 while ((outiov_ix < operation->tfrm_op.outcount) && ((out_ix + operation->tfrm_op.outdata[outiov_ix].iov_len) <= tc->tcfg->inject_ix)){
550 out_ix += operation->tfrm_op.outdata[outiov_ix].iov_len;
551 outiov_ix++;
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 /* Setup the output descriptors. */
561 while ((out_length > 0) && (outiov_ix < operation->tfrm_op.outcount)) {
562 outdesc->next = alloc_cdesc(alloc_flag);
563 if (!outdesc->next) {
564 DEBUG_API(printk("create_input_descriptors: alloc_cdesc\n"));
565 err = -ENOMEM;
566 goto error_cleanup;
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 /* Set sync in last descriptor. */
595 mi.sync = 1;
596 outdesc->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_in, mi);
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
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)611 static int create_output_descriptors(struct cryptocop_operation *operation, int *iniov_ix, int *iniov_offset, size_t desc_len, struct cryptocop_dma_desc **current_out_cdesc, struct strcop_meta_out *meta_out, int alloc_flag)
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 desc_len -= dlength;
632 *iniov_offset += dlength;
633 assert(desc_len >= 0);
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 } /* while (desc_len != 0) */
644 /* Last DMA descriptor gets a 'wait' bit to signal expected change in metadata. */
645 (*current_out_cdesc)->dma_descr->wait = 1; /* This will set extraneous WAIT in some situations, e.g. when padding hashes and checksums. */
646
647 return 0;
648 }
649
650
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)651 static int append_input_descriptors(struct cryptocop_operation *operation, struct cryptocop_dma_desc **current_in_cdesc, struct cryptocop_dma_desc **current_out_cdesc, struct cryptocop_tfrm_ctx *tc, int alloc_flag)
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 /* Setup and append output descriptors to DMA in list. */
669 if (tc->unit_no == src_dma){
670 /* mem2mem. Setup DMA in descriptors to discard all input prior to the requested mem2mem data. */
671 struct strcop_meta_in mi = {.sync = 0, .dmasel = src_dma};
672 unsigned int start_ix = tc->start_ix;
673 while (start_ix){
674 unsigned int desclen = start_ix < MEM2MEM_DISCARD_BUF_LENGTH ? start_ix : MEM2MEM_DISCARD_BUF_LENGTH;
675 (*current_in_cdesc)->next = alloc_cdesc(alloc_flag);
676 if (!(*current_in_cdesc)->next){
677 DEBUG_API(printk("append_input_descriptors: alloc_cdesc mem2mem discard failed\n"));
678 return -ENOMEM;
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
cryptocop_setup_dma_list(struct cryptocop_operation * operation,struct cryptocop_int_operation ** int_op,int alloc_flag)708 static 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 /* iovec accounting. */
777 int iniov_ix = 0;
778 int iniov_offset = 0;
779
780 /* Operation descriptor cfg traversal pointer. */
781 struct cryptocop_desc *odsc;
782
783 int failed = 0;
784 /* List heads for allocated descriptors. */
785 struct cryptocop_dma_desc out_cdesc_head = {0};
786 struct cryptocop_dma_desc in_cdesc_head = {0};
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 /* Scan operation->tfrm_op.tfrm_cfg for bad configuration and set up the local contexts. */
826 if (!tcfg) {
827 DEBUG_API(printk("cryptocop_setup_dma_list: no configured transforms in operation.\n"));
828 failed = -EINVAL;
829 goto error_cleanup;
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 /* mem2mem is handled as a NULL cipher. */
851 cipher_ctx.cbcmode = 0;
852 cipher_ctx.decrypt = 0;
853 cipher_ctx.blocklength = 1;
854 cipher_ctx.ciph_conf = 0;
855 cipher_ctx.unit_no = src_dma;
856 cipher_ctx.tcfg = tcfg;
857 cipher_ctx.tctx = tctx;
858 break;
859 case cryptocop_alg_des:
860 case cryptocop_alg_3des:
861 case cryptocop_alg_aes:
862 /* cipher */
863 if (cipher_ctx.tcfg != NULL){
864 DEBUG_API(printk("cryptocop_setup_dma_list: multiple ciphers in operation.\n"));
865 failed = -EINVAL;
866 goto error_cleanup;
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 /* digest */
910 if (digest_ctx.tcfg != NULL){
911 DEBUG_API(printk("cryptocop_setup_dma_list: multiple digests in operation.\n"));
912 failed = -EINVAL;
913 goto error_cleanup;
914 }
915 digest_ctx.tcfg = tcfg;
916 digest_ctx.tctx = tctx;
917 digest_ctx.hash_mode = 0; /* Don't use explicit IV in this API. */
918 switch (tctx->init.alg){
919 case cryptocop_alg_md5:
920 digest_ctx.blocklength = MD5_BLOCK_LENGTH;
921 digest_ctx.unit_no = src_md5;
922 digest_ctx.hash_conf = 1; /* 1 => MD-5 */
923 break;
924 case cryptocop_alg_sha1:
925 digest_ctx.blocklength = SHA1_BLOCK_LENGTH;
926 digest_ctx.unit_no = src_sha1;
927 digest_ctx.hash_conf = 0; /* 0 => SHA-1 */
928 break;
929 default:
930 panic("cryptocop_setup_dma_list: impossible digest algorithm\n");
931 }
932 break;
933 case cryptocop_alg_csum:
934 /* digest */
935 if (csum_ctx.tcfg != NULL){
936 DEBUG_API(printk("cryptocop_setup_dma_list: multiple checksums in operation.\n"));
937 failed = -EINVAL;
938 goto error_cleanup;
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 /* no algorithm. */
946 DEBUG_API(printk("cryptocop_setup_dma_list: invalid algorithm %d specified in tfrm %d.\n", tctx->init.alg, tcfg->tid));
947 failed = -EINVAL;
948 goto error_cleanup;
949 }
950 tcfg = tcfg->next;
951 }
952 /* Download key if a cipher is used. */
953 if (cipher_ctx.tcfg && (cipher_ctx.tctx->init.alg != cryptocop_alg_mem2mem)){
954 struct cryptocop_dma_desc *key_desc = NULL;
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 /* Download explicit IV if a cipher is used and CBC mode and explicit IV selected. */
966 if ((cipher_ctx.tctx->init.cipher_mode == cryptocop_cipher_mode_cbc) && (cipher_ctx.tcfg->flags & CRYPTOCOP_EXPLICIT_IV)) {
967 struct cryptocop_dma_desc *iv_desc = NULL;
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 /* Process descriptors. */
983 odsc = operation->tfrm_op.desc;
984 while (odsc) {
985 struct cryptocop_desc_cfg *dcfg = odsc->cfg;
986 struct strcop_meta_out meta_out = {0};
987 size_t desc_len = odsc->length;
988 int active_count, eop_needed_count;
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 /* Get the local context for the transform and mark it as the output unit if it produces output. */
999 if (digest_ctx.tcfg && (digest_ctx.tcfg->tid == dcfg->tid)){
1000 tc = &digest_ctx;
1001 } else if (cipher_ctx.tcfg && (cipher_ctx.tcfg->tid == dcfg->tid)){
1002 tc = &cipher_ctx;
1003 } else if (csum_ctx.tcfg && (csum_ctx.tcfg->tid == dcfg->tid)){
1004 tc = &csum_ctx;
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 /* Map source unit id to DMA source config. */
1024 switch (dcfg->src){
1025 case cryptocop_source_dma:
1026 tc->current_src = src_dma;
1027 break;
1028 case cryptocop_source_des:
1029 tc->current_src = src_des;
1030 break;
1031 case cryptocop_source_3des:
1032 tc->current_src = src_des;
1033 break;
1034 case cryptocop_source_aes:
1035 tc->current_src = src_aes;
1036 break;
1037 case cryptocop_source_md5:
1038 case cryptocop_source_sha1:
1039 case cryptocop_source_csum:
1040 case cryptocop_source_none:
1041 default:
1042 /* We do not allow using accumulating style units (SHA-1, MD5, checksum) as sources to other units.
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 /* Find the unit we are sourcing from. */
1050 if (digest_ctx.unit_no == tc->current_src){
1051 tc->curr_src = &digest_ctx;
1052 } else if (cipher_ctx.unit_no == tc->current_src){
1053 tc->curr_src = &cipher_ctx;
1054 } else if (csum_ctx.unit_no == tc->current_src){
1055 tc->curr_src = &csum_ctx;
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 /* Detect source switch. */
1067 DEBUG(printk("cryptocop_setup_dma_list: tc->active=%d tc->unit_no=%d tc->current_src=%d tc->previous_src=%d, tc->curr_src=0x%p, tc->prev_srv=0x%p\n", tc->active, tc->unit_no, tc->current_src, tc->previous_src, tc->curr_src, tc->prev_src));
1068 if (tc->active && (tc->current_src != tc->previous_src)) {
1069 /* Only allow source switch when both the old source unit and the new one have
1070 * no pending data to process (i.e. the consumed length must be a multiple of the
1071 * transform blocklength). */
1072 /* Note: if the src == NULL we are actually sourcing from DMA out. */
1073 if (((tc->prev_src != NULL) && (tc->prev_src->consumed % tc->prev_src->blocklength)) ||
1074 ((tc->curr_src != NULL) && (tc->curr_src->consumed % tc->curr_src->blocklength)))
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 /* Detect unit deactivation. */
1082 if (dcfg->last) {
1083 /* Length check of this is handled below. */
1084 tc->done = 1;
1085 }
1086 dcfg = dcfg->next;
1087 } /* while (dcfg) */
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 /* Update consumed and produced lengths.
1107
1108 The consumed length accounting here is actually cheating. If a unit source from DMA (or any
1109 other unit that process data in blocks of one octet) it is correct, but if it source from a
1110 block processing unit, i.e. a cipher, it will be temporarily incorrect at some times. However
1111 since it is only allowed--by the HW--to change source to or from a block processing unit at times where that
1112 unit has processed an exact multiple of its block length the end result will be correct.
1113 Beware that if the source change restriction change this code will need to be (much) reworked.
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 /* Ciphers are allowed only to source from DMA out. That is filtered above. */
1137 assert(cipher_ctx.current_src == src_dma);
1138 cipher_ctx.consumed += desc_len;
1139 cipher_ctx.produced = cipher_ctx.blocklength * (cipher_ctx.consumed / cipher_ctx.blocklength);
1140 if (cipher_ctx.cbcmode && !(cipher_ctx.tcfg->flags & CRYPTOCOP_EXPLICIT_IV) && cipher_ctx.produced){
1141 cipher_ctx.produced -= cipher_ctx.blocklength; /* Compensate for CBC iv. */
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 /* Setup the DMA out descriptors. */
1147 /* Configure the metadata. */
1148 active_count = 0;
1149 eop_needed_count = 0;
1150 if (cipher_ctx.active) {
1151 ++active_count;
1152 if (cipher_ctx.unit_no == src_dma){
1153 /* mem2mem */
1154 meta_out.ciphsel = src_none;
1155 } else {
1156 meta_out.ciphsel = cipher_ctx.current_src;
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; /* Explicit mode is not used here. */
1172 DEBUG(printk("set hashsel=%d hashconf=%d hashmode=%d\n", meta_out.hashsel, meta_out.hashconf, meta_out.hashmode));
1173 if (digest_ctx.done) {
1174 assert(digest_ctx.pad_descs == NULL);
1175 failed = create_pad_descriptor(&digest_ctx, &digest_ctx.pad_descs, alloc_flag);
1176 if (failed) {
1177 DEBUG_API(printk("cryptocop_setup_dma_list: failed digest pad creation.\n"));
1178 goto error_cleanup;
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 /* Setup DMA out descriptors for the indata. */
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 /* Setup out EOP. If there are active units that are not done here they cannot get an EOP
1207 * so we ust setup a zero length descriptor to DMA to signal EOP only to done units.
1208 * If there is a pad descriptor EOP for the padded unit will be EOPed by it.
1209 */
1210 assert(active_count >= eop_needed_count);
1211 assert((eop_needed_count == 0) || (eop_needed_count == 1));
1212 if (eop_needed_count) {
1213 /* This means that the bulk operation (cipeher/m2m) is terminated. */
1214 if (active_count > 1) {
1215 /* Use zero length EOP descriptor. */
1216 struct cryptocop_dma_desc *ed = alloc_cdesc(alloc_flag);
1217 struct strcop_meta_out ed_mo = {0};
1218 if (!ed) {
1219 DEBUG_API(printk("cryptocop_setup_dma_list: alloc EOP descriptor for cipher\n"));
1220 failed = -ENOMEM;
1221 goto error_cleanup;
1222 }
1223
1224 assert(cipher_ctx.active && cipher_ctx.done);
1225
1226 if (cipher_ctx.unit_no == src_dma){
1227 /* mem2mem */
1228 ed_mo.ciphsel = src_none;
1229 } else {
1230 ed_mo.ciphsel = cipher_ctx.current_src;
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); /* Use any valid physical address for zero length descriptor. */
1241 ed->dma_descr->after = ed->dma_descr->buf;
1242 ed->dma_descr->md = REG_TYPE_CONV(unsigned short int, struct strcop_meta_out, ed_mo);
1243 current_out_cdesc->next = ed;
1244 current_out_cdesc = ed;
1245 } else {
1246 /* Set EOP in the current out descriptor since the only active module is
1247 * the one needing the EOP. */
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 } /* while (odsc) */ /* Process descriptors. */
1259 DEBUG(printk("cryptocop_setup_dma_list: done parsing operation descriptors\n"));
1260 if (cipher_ctx.tcfg && (cipher_ctx.active || !cipher_ctx.done)){
1261 DEBUG_API(printk("cryptocop_setup_dma_list: cipher operation not terminated.\n"));
1262 failed = -EINVAL;
1263 goto error_cleanup;
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 /* Last but not least: mark the last DMA in descriptor for a INTR and EOL and the the
1301 * last DMA out descriptor for EOL.
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 /* Setup DMA contexts. */
1308 (*int_op)->ctx_out.next = NULL;
1309 (*int_op)->ctx_out.eol = 1;
1310 (*int_op)->ctx_out.intr = 0;
1311 (*int_op)->ctx_out.store_mode = 0;
1312 (*int_op)->ctx_out.en = 0;
1313 (*int_op)->ctx_out.dis = 0;
1314 (*int_op)->ctx_out.md0 = 0;
1315 (*int_op)->ctx_out.md1 = 0;
1316 (*int_op)->ctx_out.md2 = 0;
1317 (*int_op)->ctx_out.md3 = 0;
1318 (*int_op)->ctx_out.md4 = 0;
1319 (*int_op)->ctx_out.saved_data = (dma_descr_data*)virt_to_phys((*int_op)->cdesc_out->dma_descr);
1320 (*int_op)->ctx_out.saved_data_buf = (*int_op)->cdesc_out->dma_descr->buf; /* Already physical address. */
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; /* Already physical address. */
1336
1337 DEBUG(printk("cryptocop_setup_dma_list: done\n"));
1338 return 0;
1339
1340 error_cleanup:
1341 {
1342 /* Free all allocated resources. */
1343 struct cryptocop_dma_desc *tmp_cdesc;
1344 while (digest_ctx.pad_descs){
1345 tmp_cdesc = digest_ctx.pad_descs->next;
1346 free_cdesc(digest_ctx.pad_descs);
1347 digest_ctx.pad_descs = tmp_cdesc;
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); /* The ciphers are never padded. */
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
delete_internal_operation(struct cryptocop_int_operation * iop)1363 static 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
create_md5_pad(int alloc_flag,unsigned long long hashed_length,char ** pad,size_t * pad_length)1388 static 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 = kmalloc(padlen, alloc_flag);
1398 if (!pad) return -ENOMEM;
1399
1400 *p = 0x80;
1401 memset(p+1, 0, padlen - 1);
1402
1403 DEBUG(printk("create_md5_pad: hashed_length=%lld bits == %lld bytes\n", bit_length, hashed_length));
1404
1405 i = padlen - MD5_PAD_LENGTH_FIELD_LENGTH;
1406 while (bit_length != 0){
1407 p[i++] = bit_length % 0x100;
1408 bit_length >>= 8;
1409 }
1410
1411 *pad = (char*)p;
1412 *pad_length = padlen;
1413
1414 return 0;
1415 }
1416
1417 #define SHA1_MIN_PAD_LENGTH (9)
1418 #define SHA1_PAD_LENGTH_FIELD_LENGTH (8)
1419
create_sha1_pad(int alloc_flag,unsigned long long hashed_length,char ** pad,size_t * pad_length)1420 static int create_sha1_pad(int alloc_flag, unsigned long long hashed_length, char **pad, size_t *pad_length)
1421 {
1422 size_t padlen = SHA1_BLOCK_LENGTH - (hashed_length % SHA1_BLOCK_LENGTH);
1423 unsigned char *p;
1424 int i;
1425 unsigned long long int bit_length = hashed_length << 3;
1426
1427 if (padlen < SHA1_MIN_PAD_LENGTH) padlen += SHA1_BLOCK_LENGTH;
1428
1429 p = kmalloc(padlen, alloc_flag);
1430 if (!pad) return -ENOMEM;
1431
1432 *p = 0x80;
1433 memset(p+1, 0, padlen - 1);
1434
1435 DEBUG(printk("create_sha1_pad: hashed_length=%lld bits == %lld bytes\n", bit_length, hashed_length));
1436
1437 i = padlen - 1;
1438 while (bit_length != 0){
1439 p[i--] = bit_length % 0x100;
1440 bit_length >>= 8;
1441 }
1442
1443 *pad = (char*)p;
1444 *pad_length = padlen;
1445
1446 return 0;
1447 }
1448
1449
transform_ok(struct cryptocop_transform_init * tinit)1450 static int transform_ok(struct cryptocop_transform_init *tinit)
1451 {
1452 switch (tinit->alg){
1453 case cryptocop_alg_csum:
1454 switch (tinit->csum_mode){
1455 case cryptocop_csum_le:
1456 case cryptocop_csum_be:
1457 break;
1458 default:
1459 DEBUG_API(printk("transform_ok: Bad mode set for csum transform\n"));
1460 return -EINVAL;
1461 }
1462 case cryptocop_alg_mem2mem:
1463 case cryptocop_alg_md5:
1464 case cryptocop_alg_sha1:
1465 if (tinit->keylen != 0) {
1466 DEBUG_API(printk("transform_ok: non-zero keylength, %d, for a digest/csum algorithm\n", tinit->keylen));
1467 return -EINVAL; /* This check is a bit strict. */
1468 }
1469 break;
1470 case cryptocop_alg_des:
1471 if (tinit->keylen != 64) {
1472 DEBUG_API(printk("transform_ok: keylen %d invalid for DES\n", tinit->keylen));
1473 return -EINVAL;
1474 }
1475 break;
1476 case cryptocop_alg_3des:
1477 if (tinit->keylen != 192) {
1478 DEBUG_API(printk("transform_ok: keylen %d invalid for 3DES\n", tinit->keylen));
1479 return -EINVAL;
1480 }
1481 break;
1482 case cryptocop_alg_aes:
1483 if (tinit->keylen != 128 && tinit->keylen != 192 && tinit->keylen != 256) {
1484 DEBUG_API(printk("transform_ok: keylen %d invalid for AES\n", tinit->keylen));
1485 return -EINVAL;
1486 }
1487 break;
1488 case cryptocop_no_alg:
1489 default:
1490 DEBUG_API(printk("transform_ok: no such algorithm %d\n", tinit->alg));
1491 return -EINVAL;
1492 }
1493
1494 switch (tinit->alg){
1495 case cryptocop_alg_des:
1496 case cryptocop_alg_3des:
1497 case cryptocop_alg_aes:
1498 if (tinit->cipher_mode != cryptocop_cipher_mode_ecb && tinit->cipher_mode != cryptocop_cipher_mode_cbc) return -EINVAL;
1499 default:
1500 break;
1501 }
1502 return 0;
1503 }
1504
1505
cryptocop_new_session(cryptocop_session_id * sid,struct cryptocop_transform_init * tinit,int alloc_flag)1506 int cryptocop_new_session(cryptocop_session_id *sid, struct cryptocop_transform_init *tinit, int alloc_flag)
1507 {
1508 struct cryptocop_session *sess;
1509 struct cryptocop_transform_init *tfrm_in = tinit;
1510 struct cryptocop_transform_init *tmp_in;
1511 int no_tfrms = 0;
1512 int i;
1513 unsigned long int flags;
1514
1515 init_stream_coprocessor(); /* For safety if we are called early */
1516
1517 while (tfrm_in){
1518 int err;
1519 ++no_tfrms;
1520 if ((err = transform_ok(tfrm_in))) {
1521 DEBUG_API(printk("cryptocop_new_session, bad transform\n"));
1522 return err;
1523 }
1524 tfrm_in = tfrm_in->next;
1525 }
1526 if (0 == no_tfrms) {
1527 DEBUG_API(printk("cryptocop_new_session, no transforms specified\n"));
1528 return -EINVAL;
1529 }
1530
1531 sess = kmalloc(sizeof(struct cryptocop_session), alloc_flag);
1532 if (!sess){
1533 DEBUG_API(printk("cryptocop_new_session, kmalloc cryptocop_session\n"));
1534 return -ENOMEM;
1535 }
1536
1537 sess->tfrm_ctx = kmalloc(no_tfrms * sizeof(struct cryptocop_transform_ctx), alloc_flag);
1538 if (!sess->tfrm_ctx) {
1539 DEBUG_API(printk("cryptocop_new_session, kmalloc cryptocop_transform_ctx\n"));
1540 kfree(sess);
1541 return -ENOMEM;
1542 }
1543
1544 tfrm_in = tinit;
1545 for (i = 0; i < no_tfrms; i++){
1546 tmp_in = tfrm_in->next;
1547 while (tmp_in){
1548 if (tmp_in->tid == tfrm_in->tid) {
1549 DEBUG_API(printk("cryptocop_new_session, duplicate transform ids\n"));
1550 kfree(sess->tfrm_ctx);
1551 kfree(sess);
1552 return -EINVAL;
1553 }
1554 tmp_in = tmp_in->next;
1555 }
1556 memcpy(&sess->tfrm_ctx[i].init, tfrm_in, sizeof(struct cryptocop_transform_init));
1557 sess->tfrm_ctx[i].dec_key_set = 0;
1558 sess->tfrm_ctx[i].next = &sess->tfrm_ctx[i] + 1;
1559
1560 tfrm_in = tfrm_in->next;
1561 }
1562 sess->tfrm_ctx[i-1].next = NULL;
1563
1564 spin_lock_irqsave(&cryptocop_sessions_lock, flags);
1565 sess->sid = next_sid;
1566 next_sid++;
1567 /* TODO If we are really paranoid we should do duplicate check to handle sid wraparound.
1568 * OTOH 2^64 is a really large number of session. */
1569 if (next_sid == 0) next_sid = 1;
1570
1571 /* Prepend to session list. */
1572 sess->next = cryptocop_sessions;
1573 cryptocop_sessions = sess;
1574 spin_unlock_irqrestore(&cryptocop_sessions_lock, flags);
1575 *sid = sess->sid;
1576 return 0;
1577 }
1578
1579
cryptocop_free_session(cryptocop_session_id sid)1580 int cryptocop_free_session(cryptocop_session_id sid)
1581 {
1582 struct cryptocop_transform_ctx *tc;
1583 struct cryptocop_session *sess = NULL;
1584 struct cryptocop_session *psess = NULL;
1585 unsigned long int flags;
1586 int i;
1587 LIST_HEAD(remove_list);
1588 struct list_head *node, *tmp;
1589 struct cryptocop_prio_job *pj;
1590
1591 DEBUG(printk("cryptocop_free_session: sid=%lld\n", sid));
1592
1593 spin_lock_irqsave(&cryptocop_sessions_lock, flags);
1594 sess = cryptocop_sessions;
1595 while (sess && sess->sid != sid){
1596 psess = sess;
1597 sess = sess->next;
1598 }
1599 if (sess){
1600 if (psess){
1601 psess->next = sess->next;
1602 } else {
1603 cryptocop_sessions = sess->next;
1604 }
1605 }
1606 spin_unlock_irqrestore(&cryptocop_sessions_lock, flags);
1607
1608 if (!sess) return -EINVAL;
1609
1610 /* Remove queued jobs. */
1611 spin_lock_irqsave(&cryptocop_job_queue_lock, flags);
1612
1613 for (i = 0; i < cryptocop_prio_no_prios; i++){
1614 if (!list_empty(&(cryptocop_job_queues[i].jobs))){
1615 list_for_each_safe(node, tmp, &(cryptocop_job_queues[i].jobs)) {
1616 pj = list_entry(node, struct cryptocop_prio_job, node);
1617 if (pj->oper->sid == sid) {
1618 list_move_tail(node, &remove_list);
1619 }
1620 }
1621 }
1622 }
1623 spin_unlock_irqrestore(&cryptocop_job_queue_lock, flags);
1624
1625 list_for_each_safe(node, tmp, &remove_list) {
1626 list_del(node);
1627 pj = list_entry(node, struct cryptocop_prio_job, node);
1628 pj->oper->operation_status = -EAGAIN; /* EAGAIN is not ideal for job/session terminated but it's the best choice I know of. */
1629 DEBUG(printk("cryptocop_free_session: pj=0x%p, pj->oper=0x%p, pj->iop=0x%p\n", pj, pj->oper, pj->iop));
1630 pj->oper->cb(pj->oper, pj->oper->cb_data);
1631 delete_internal_operation(pj->iop);
1632 kfree(pj);
1633 }
1634
1635 tc = sess->tfrm_ctx;
1636 /* Erase keying data. */
1637 while (tc){
1638 DEBUG(printk("cryptocop_free_session: memset keys, tfrm id=%d\n", tc->init.tid));
1639 memset(tc->init.key, 0xff, CRYPTOCOP_MAX_KEY_LENGTH);
1640 memset(tc->dec_key, 0xff, CRYPTOCOP_MAX_KEY_LENGTH);
1641 tc = tc->next;
1642 }
1643 kfree(sess->tfrm_ctx);
1644 kfree(sess);
1645
1646 return 0;
1647 }
1648
get_session(cryptocop_session_id sid)1649 static struct cryptocop_session *get_session(cryptocop_session_id sid)
1650 {
1651 struct cryptocop_session *sess;
1652 unsigned long int flags;
1653
1654 spin_lock_irqsave(&cryptocop_sessions_lock, flags);
1655 sess = cryptocop_sessions;
1656 while (sess && (sess->sid != sid)){
1657 sess = sess->next;
1658 }
1659 spin_unlock_irqrestore(&cryptocop_sessions_lock, flags);
1660
1661 return sess;
1662 }
1663
get_transform_ctx(struct cryptocop_session * sess,cryptocop_tfrm_id tid)1664 static struct cryptocop_transform_ctx *get_transform_ctx(struct cryptocop_session *sess, cryptocop_tfrm_id tid)
1665 {
1666 struct cryptocop_transform_ctx *tc = sess->tfrm_ctx;
1667
1668 DEBUG(printk("get_transform_ctx, sess=0x%p, tid=%d\n", sess, tid));
1669 assert(sess != NULL);
1670 while (tc && tc->init.tid != tid){
1671 DEBUG(printk("tc=0x%p, tc->next=0x%p\n", tc, tc->next));
1672 tc = tc->next;
1673 }
1674 DEBUG(printk("get_transform_ctx, returning tc=0x%p\n", tc));
1675 return tc;
1676 }
1677
1678
1679
1680 /* The AES s-transform matrix (s-box). */
1681 static const u8 aes_sbox[256] = {
1682 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
1683 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
1684 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
1685 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
1686 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
1687 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
1688 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
1689 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
1690 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
1691 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
1692 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
1693 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
1694 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
1695 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
1696 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
1697 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22
1698 };
1699
1700 /* AES has a 32 bit word round constants for each round in the
1701 * key schedule. round_constant[i] is really Rcon[i+1] in FIPS187.
1702 */
1703 static u32 round_constant[11] = {
1704 0x01000000, 0x02000000, 0x04000000, 0x08000000,
1705 0x10000000, 0x20000000, 0x40000000, 0x80000000,
1706 0x1B000000, 0x36000000, 0x6C000000
1707 };
1708
1709 /* Apply the s-box to each of the four occtets in w. */
aes_ks_subword(const u32 w)1710 static u32 aes_ks_subword(const u32 w)
1711 {
1712 u8 bytes[4];
1713
1714 *(u32*)(&bytes[0]) = w;
1715 bytes[0] = aes_sbox[bytes[0]];
1716 bytes[1] = aes_sbox[bytes[1]];
1717 bytes[2] = aes_sbox[bytes[2]];
1718 bytes[3] = aes_sbox[bytes[3]];
1719 return *(u32*)(&bytes[0]);
1720 }
1721
1722 /* The encrypt (forward) Rijndael key schedule algorithm pseudo code:
1723 * (Note that AES words are 32 bit long)
1724 *
1725 * KeyExpansion(byte key[4*Nk], word w[Nb*(Nr+1)], Nk){
1726 * word temp
1727 * i = 0
1728 * while (i < Nk) {
1729 * w[i] = word(key[4*i, 4*i + 1, 4*i + 2, 4*i + 3])
1730 * i = i + 1
1731 * }
1732 * i = Nk
1733 *
1734 * while (i < (Nb * (Nr + 1))) {
1735 * temp = w[i - 1]
1736 * if ((i mod Nk) == 0) {
1737 * temp = SubWord(RotWord(temp)) xor Rcon[i/Nk]
1738 * }
1739 * else if ((Nk > 6) && ((i mod Nk) == 4)) {
1740 * temp = SubWord(temp)
1741 * }
1742 * w[i] = w[i - Nk] xor temp
1743 * }
1744 * RotWord(t) does a 8 bit cyclic shift left on a 32 bit word.
1745 * SubWord(t) applies the AES s-box individually to each octet
1746 * in a 32 bit word.
1747 *
1748 * For AES Nk can have the values 4, 6, and 8 (corresponding to
1749 * values for Nr of 10, 12, and 14). Nb is always 4.
1750 *
1751 * To construct w[i], w[i - 1] and w[i - Nk] must be
1752 * available. Consequently we must keep a state of the last Nk words
1753 * to be able to create the last round keys.
1754 */
get_aes_decrypt_key(unsigned char * dec_key,const unsigned char * key,unsigned int keylength)1755 static void get_aes_decrypt_key(unsigned char *dec_key, const unsigned char *key, unsigned int keylength)
1756 {
1757 u32 temp;
1758 u32 w_ring[8]; /* nk is max 8, use elements 0..(nk - 1) as a ringbuffer */
1759 u8 w_last_ix;
1760 int i;
1761 u8 nr, nk;
1762
1763 switch (keylength){
1764 case 128:
1765 nk = 4;
1766 nr = 10;
1767 break;
1768 case 192:
1769 nk = 6;
1770 nr = 12;
1771 break;
1772 case 256:
1773 nk = 8;
1774 nr = 14;
1775 break;
1776 default:
1777 panic("stream co-processor: bad aes key length in get_aes_decrypt_key\n");
1778 };
1779
1780 /* Need to do host byte order correction here since key is byte oriented and the
1781 * kx algorithm is word (u32) oriented. */
1782 for (i = 0; i < nk; i+=1) {
1783 w_ring[i] = be32_to_cpu(*(u32*)&key[4*i]);
1784 }
1785
1786 i = (int)nk;
1787 w_last_ix = i - 1;
1788 while (i < (4 * (nr + 2))) {
1789 temp = w_ring[w_last_ix];
1790 if (!(i % nk)) {
1791 /* RotWord(temp) */
1792 temp = (temp << 8) | (temp >> 24);
1793 temp = aes_ks_subword(temp);
1794 temp ^= round_constant[i/nk - 1];
1795 } else if ((nk > 6) && ((i % nk) == 4)) {
1796 temp = aes_ks_subword(temp);
1797 }
1798 w_last_ix = (w_last_ix + 1) % nk; /* This is the same as (i-Nk) mod Nk */
1799 temp ^= w_ring[w_last_ix];
1800 w_ring[w_last_ix] = temp;
1801
1802 /* We need the round keys for round Nr+1 and Nr+2 (round key
1803 * Nr+2 is the round key beyond the last one used when
1804 * encrypting). Rounds are numbered starting from 0, Nr=10
1805 * implies 11 rounds are used in encryption/decryption.
1806 */
1807 if (i >= (4 * nr)) {
1808 /* Need to do host byte order correction here, the key
1809 * is byte oriented. */
1810 *(u32*)dec_key = cpu_to_be32(temp);
1811 dec_key += 4;
1812 }
1813 ++i;
1814 }
1815 }
1816
1817
1818 /**** Job/operation management. ****/
1819
cryptocop_job_queue_insert_csum(struct cryptocop_operation * operation)1820 int cryptocop_job_queue_insert_csum(struct cryptocop_operation *operation)
1821 {
1822 return cryptocop_job_queue_insert(cryptocop_prio_kernel_csum, operation);
1823 }
1824
cryptocop_job_queue_insert_crypto(struct cryptocop_operation * operation)1825 int cryptocop_job_queue_insert_crypto(struct cryptocop_operation *operation)
1826 {
1827 return cryptocop_job_queue_insert(cryptocop_prio_kernel, operation);
1828 }
1829
cryptocop_job_queue_insert_user_job(struct cryptocop_operation * operation)1830 int cryptocop_job_queue_insert_user_job(struct cryptocop_operation *operation)
1831 {
1832 return cryptocop_job_queue_insert(cryptocop_prio_user, operation);
1833 }
1834
cryptocop_job_queue_insert(cryptocop_queue_priority prio,struct cryptocop_operation * operation)1835 static int cryptocop_job_queue_insert(cryptocop_queue_priority prio, struct cryptocop_operation *operation)
1836 {
1837 int ret;
1838 struct cryptocop_prio_job *pj = NULL;
1839 unsigned long int flags;
1840
1841 DEBUG(printk("cryptocop_job_queue_insert(%d, 0x%p)\n", prio, operation));
1842
1843 if (!operation || !operation->cb){
1844 DEBUG_API(printk("cryptocop_job_queue_insert oper=0x%p, NULL operation or callback\n", operation));
1845 return -EINVAL;
1846 }
1847
1848 if ((ret = cryptocop_job_setup(&pj, operation)) != 0){
1849 DEBUG_API(printk("cryptocop_job_queue_insert: job setup failed\n"));
1850 return ret;
1851 }
1852 assert(pj != NULL);
1853
1854 spin_lock_irqsave(&cryptocop_job_queue_lock, flags);
1855 list_add_tail(&pj->node, &cryptocop_job_queues[prio].jobs);
1856 spin_unlock_irqrestore(&cryptocop_job_queue_lock, flags);
1857
1858 /* Make sure a job is running */
1859 cryptocop_start_job();
1860 return 0;
1861 }
1862
1863 static void cryptocop_do_tasklet(unsigned long unused);
1864 DECLARE_TASKLET (cryptocop_tasklet, cryptocop_do_tasklet, 0);
1865
cryptocop_do_tasklet(unsigned long unused)1866 static void cryptocop_do_tasklet(unsigned long unused)
1867 {
1868 struct list_head *node;
1869 struct cryptocop_prio_job *pj = NULL;
1870 unsigned long flags;
1871
1872 DEBUG(printk("cryptocop_do_tasklet: entering\n"));
1873
1874 do {
1875 spin_lock_irqsave(&cryptocop_completed_jobs_lock, flags);
1876 if (!list_empty(&cryptocop_completed_jobs)){
1877 node = cryptocop_completed_jobs.next;
1878 list_del(node);
1879 pj = list_entry(node, struct cryptocop_prio_job, node);
1880 } else {
1881 pj = NULL;
1882 }
1883 spin_unlock_irqrestore(&cryptocop_completed_jobs_lock, flags);
1884 if (pj) {
1885 assert(pj->oper != NULL);
1886
1887 /* Notify consumer of operation completeness. */
1888 DEBUG(printk("cryptocop_do_tasklet: callback 0x%p, data 0x%p\n", pj->oper->cb, pj->oper->cb_data));
1889
1890 pj->oper->operation_status = 0; /* Job is completed. */
1891 pj->oper->cb(pj->oper, pj->oper->cb_data);
1892 delete_internal_operation(pj->iop);
1893 kfree(pj);
1894 }
1895 } while (pj != NULL);
1896
1897 DEBUG(printk("cryptocop_do_tasklet: exiting\n"));
1898 }
1899
1900 static irqreturn_t
dma_done_interrupt(int irq,void * dev_id)1901 dma_done_interrupt(int irq, void *dev_id)
1902 {
1903 struct cryptocop_prio_job *done_job;
1904 reg_dma_rw_ack_intr ack_intr = {
1905 .data = 1,
1906 };
1907
1908 REG_WR(dma, IN_DMA_INST, rw_ack_intr, ack_intr);
1909
1910 DEBUG(printk("cryptocop DMA done\n"));
1911
1912 spin_lock(&running_job_lock);
1913 if (cryptocop_running_job == NULL){
1914 printk("stream co-processor got interrupt when not busy\n");
1915 spin_unlock(&running_job_lock);
1916 return IRQ_HANDLED;
1917 }
1918 done_job = cryptocop_running_job;
1919 cryptocop_running_job = NULL;
1920 spin_unlock(&running_job_lock);
1921
1922 /* Start processing a job. */
1923 if (!spin_trylock(&cryptocop_process_lock)){
1924 DEBUG(printk("cryptocop irq handler, not starting a job\n"));
1925 } else {
1926 cryptocop_start_job();
1927 spin_unlock(&cryptocop_process_lock);
1928 }
1929
1930 done_job->oper->operation_status = 0; /* Job is completed. */
1931 if (done_job->oper->fast_callback){
1932 /* This operation wants callback from interrupt. */
1933 done_job->oper->cb(done_job->oper, done_job->oper->cb_data);
1934 delete_internal_operation(done_job->iop);
1935 kfree(done_job);
1936 } else {
1937 spin_lock(&cryptocop_completed_jobs_lock);
1938 list_add_tail(&(done_job->node), &cryptocop_completed_jobs);
1939 spin_unlock(&cryptocop_completed_jobs_lock);
1940 tasklet_schedule(&cryptocop_tasklet);
1941 }
1942
1943 DEBUG(printk("cryptocop leave irq handler\n"));
1944 return IRQ_HANDLED;
1945 }
1946
1947
1948 /* Setup interrupts and DMA channels. */
init_cryptocop(void)1949 static int init_cryptocop(void)
1950 {
1951 unsigned long flags;
1952 reg_dma_rw_cfg dma_cfg = {.en = 1};
1953 reg_dma_rw_intr_mask intr_mask_in = {.data = regk_dma_yes}; /* Only want descriptor interrupts from the DMA in channel. */
1954 reg_dma_rw_ack_intr ack_intr = {.data = 1,.in_eop = 1 };
1955 reg_strcop_rw_cfg strcop_cfg = {
1956 .ipend = regk_strcop_little,
1957 .td1 = regk_strcop_e,
1958 .td2 = regk_strcop_d,
1959 .td3 = regk_strcop_e,
1960 .ignore_sync = 0,
1961 .en = 1
1962 };
1963
1964 if (request_irq(DMA_IRQ, dma_done_interrupt, 0,
1965 "stream co-processor DMA", NULL))
1966 panic("request_irq stream co-processor irq dma9");
1967
1968 (void)crisv32_request_dma(OUT_DMA, "strcop", DMA_PANIC_ON_ERROR,
1969 0, dma_strp);
1970 (void)crisv32_request_dma(IN_DMA, "strcop", DMA_PANIC_ON_ERROR,
1971 0, dma_strp);
1972
1973 local_irq_save(flags);
1974
1975 /* Reset and enable the cryptocop. */
1976 strcop_cfg.en = 0;
1977 REG_WR(strcop, regi_strcop, rw_cfg, strcop_cfg);
1978 strcop_cfg.en = 1;
1979 REG_WR(strcop, regi_strcop, rw_cfg, strcop_cfg);
1980
1981 /* Enable DMAs. */
1982 REG_WR(dma, IN_DMA_INST, rw_cfg, dma_cfg); /* input DMA */
1983 REG_WR(dma, OUT_DMA_INST, rw_cfg, dma_cfg); /* output DMA */
1984
1985 /* Set up wordsize = 4 for DMAs. */
1986 DMA_WR_CMD(OUT_DMA_INST, regk_dma_set_w_size4);
1987 DMA_WR_CMD(IN_DMA_INST, regk_dma_set_w_size4);
1988
1989 /* Enable interrupts. */
1990 REG_WR(dma, IN_DMA_INST, rw_intr_mask, intr_mask_in);
1991
1992 /* Clear intr ack. */
1993 REG_WR(dma, IN_DMA_INST, rw_ack_intr, ack_intr);
1994
1995 local_irq_restore(flags);
1996
1997 return 0;
1998 }
1999
2000 /* Free used cryptocop hw resources (interrupt and DMA channels). */
release_cryptocop(void)2001 static void release_cryptocop(void)
2002 {
2003 unsigned long flags;
2004 reg_dma_rw_cfg dma_cfg = {.en = 0};
2005 reg_dma_rw_intr_mask intr_mask_in = {0};
2006 reg_dma_rw_ack_intr ack_intr = {.data = 1,.in_eop = 1 };
2007
2008 local_irq_save(flags);
2009
2010 /* Clear intr ack. */
2011 REG_WR(dma, IN_DMA_INST, rw_ack_intr, ack_intr);
2012
2013 /* Disable DMAs. */
2014 REG_WR(dma, IN_DMA_INST, rw_cfg, dma_cfg); /* input DMA */
2015 REG_WR(dma, OUT_DMA_INST, rw_cfg, dma_cfg); /* output DMA */
2016
2017 /* Disable interrupts. */
2018 REG_WR(dma, IN_DMA_INST, rw_intr_mask, intr_mask_in);
2019
2020 local_irq_restore(flags);
2021
2022 free_irq(DMA_IRQ, NULL);
2023
2024 (void)crisv32_free_dma(OUT_DMA);
2025 (void)crisv32_free_dma(IN_DMA);
2026 }
2027
2028
2029 /* Init job queue. */
cryptocop_job_queue_init(void)2030 static int cryptocop_job_queue_init(void)
2031 {
2032 int i;
2033
2034 INIT_LIST_HEAD(&cryptocop_completed_jobs);
2035
2036 for (i = 0; i < cryptocop_prio_no_prios; i++){
2037 cryptocop_job_queues[i].prio = (cryptocop_queue_priority)i;
2038 INIT_LIST_HEAD(&cryptocop_job_queues[i].jobs);
2039 }
2040 return 0;
2041 }
2042
2043
cryptocop_job_queue_close(void)2044 static void cryptocop_job_queue_close(void)
2045 {
2046 struct list_head *node, *tmp;
2047 struct cryptocop_prio_job *pj = NULL;
2048 unsigned long int process_flags, flags;
2049 int i;
2050
2051 /* FIXME: This is as yet untested code. */
2052
2053 /* Stop strcop from getting an operation to process while we are closing the
2054 module. */
2055 spin_lock_irqsave(&cryptocop_process_lock, process_flags);
2056
2057 /* Empty the job queue. */
2058 for (i = 0; i < cryptocop_prio_no_prios; i++){
2059 if (!list_empty(&(cryptocop_job_queues[i].jobs))){
2060 list_for_each_safe(node, tmp, &(cryptocop_job_queues[i].jobs)) {
2061 pj = list_entry(node, struct cryptocop_prio_job, node);
2062 list_del(node);
2063
2064 /* Call callback to notify consumer of job removal. */
2065 DEBUG(printk("cryptocop_job_queue_close: callback 0x%p, data 0x%p\n", pj->oper->cb, pj->oper->cb_data));
2066 pj->oper->operation_status = -EINTR; /* Job is terminated without completion. */
2067 pj->oper->cb(pj->oper, pj->oper->cb_data);
2068
2069 delete_internal_operation(pj->iop);
2070 kfree(pj);
2071 }
2072 }
2073 }
2074 spin_unlock_irqrestore(&cryptocop_process_lock, process_flags);
2075
2076 /* Remove the running job, if any. */
2077 spin_lock_irqsave(&running_job_lock, flags);
2078 if (cryptocop_running_job){
2079 reg_strcop_rw_cfg rw_cfg;
2080 reg_dma_rw_cfg dma_out_cfg, dma_in_cfg;
2081
2082 /* Stop DMA. */
2083 dma_out_cfg = REG_RD(dma, OUT_DMA_INST, rw_cfg);
2084 dma_out_cfg.en = regk_dma_no;
2085 REG_WR(dma, OUT_DMA_INST, rw_cfg, dma_out_cfg);
2086
2087 dma_in_cfg = REG_RD(dma, IN_DMA_INST, rw_cfg);
2088 dma_in_cfg.en = regk_dma_no;
2089 REG_WR(dma, IN_DMA_INST, rw_cfg, dma_in_cfg);
2090
2091 /* Disble the cryptocop. */
2092 rw_cfg = REG_RD(strcop, regi_strcop, rw_cfg);
2093 rw_cfg.en = 0;
2094 REG_WR(strcop, regi_strcop, rw_cfg, rw_cfg);
2095
2096 pj = cryptocop_running_job;
2097 cryptocop_running_job = NULL;
2098
2099 /* Call callback to notify consumer of job removal. */
2100 DEBUG(printk("cryptocop_job_queue_close: callback 0x%p, data 0x%p\n", pj->oper->cb, pj->oper->cb_data));
2101 pj->oper->operation_status = -EINTR; /* Job is terminated without completion. */
2102 pj->oper->cb(pj->oper, pj->oper->cb_data);
2103
2104 delete_internal_operation(pj->iop);
2105 kfree(pj);
2106 }
2107 spin_unlock_irqrestore(&running_job_lock, flags);
2108
2109 /* Remove completed jobs, if any. */
2110 spin_lock_irqsave(&cryptocop_completed_jobs_lock, flags);
2111
2112 list_for_each_safe(node, tmp, &cryptocop_completed_jobs) {
2113 pj = list_entry(node, struct cryptocop_prio_job, node);
2114 list_del(node);
2115 /* Call callback to notify consumer of job removal. */
2116 DEBUG(printk("cryptocop_job_queue_close: callback 0x%p, data 0x%p\n", pj->oper->cb, pj->oper->cb_data));
2117 pj->oper->operation_status = -EINTR; /* Job is terminated without completion. */
2118 pj->oper->cb(pj->oper, pj->oper->cb_data);
2119
2120 delete_internal_operation(pj->iop);
2121 kfree(pj);
2122 }
2123 spin_unlock_irqrestore(&cryptocop_completed_jobs_lock, flags);
2124 }
2125
2126
cryptocop_start_job(void)2127 static void cryptocop_start_job(void)
2128 {
2129 int i;
2130 struct cryptocop_prio_job *pj;
2131 unsigned long int flags;
2132 unsigned long int running_job_flags;
2133 reg_strcop_rw_cfg rw_cfg = {.en = 1, .ignore_sync = 0};
2134
2135 DEBUG(printk("cryptocop_start_job: entering\n"));
2136
2137 spin_lock_irqsave(&running_job_lock, running_job_flags);
2138 if (cryptocop_running_job != NULL){
2139 /* Already running. */
2140 DEBUG(printk("cryptocop_start_job: already running, exit\n"));
2141 spin_unlock_irqrestore(&running_job_lock, running_job_flags);
2142 return;
2143 }
2144 spin_lock_irqsave(&cryptocop_job_queue_lock, flags);
2145
2146 /* Check the queues in priority order. */
2147 for (i = cryptocop_prio_kernel_csum; (i < cryptocop_prio_no_prios) && list_empty(&cryptocop_job_queues[i].jobs); i++);
2148 if (i == cryptocop_prio_no_prios) {
2149 spin_unlock_irqrestore(&cryptocop_job_queue_lock, flags);
2150 spin_unlock_irqrestore(&running_job_lock, running_job_flags);
2151 DEBUG(printk("cryptocop_start_job: no jobs to run\n"));
2152 return; /* No jobs to run */
2153 }
2154 DEBUG(printk("starting job for prio %d\n", i));
2155
2156 /* TODO: Do not starve lower priority jobs. Let in a lower
2157 * prio job for every N-th processed higher prio job or some
2158 * other scheduling policy. This could reasonably be
2159 * tweakable since the optimal balance would depend on the
2160 * type of load on the system. */
2161
2162 /* Pull the DMA lists from the job and start the DMA client. */
2163 pj = list_entry(cryptocop_job_queues[i].jobs.next, struct cryptocop_prio_job, node);
2164 list_del(&pj->node);
2165 spin_unlock_irqrestore(&cryptocop_job_queue_lock, flags);
2166 cryptocop_running_job = pj;
2167
2168 /* Set config register (3DES and CSUM modes). */
2169 switch (pj->iop->tdes_mode){
2170 case cryptocop_3des_eee:
2171 rw_cfg.td1 = regk_strcop_e;
2172 rw_cfg.td2 = regk_strcop_e;
2173 rw_cfg.td3 = regk_strcop_e;
2174 break;
2175 case cryptocop_3des_eed:
2176 rw_cfg.td1 = regk_strcop_e;
2177 rw_cfg.td2 = regk_strcop_e;
2178 rw_cfg.td3 = regk_strcop_d;
2179 break;
2180 case cryptocop_3des_ede:
2181 rw_cfg.td1 = regk_strcop_e;
2182 rw_cfg.td2 = regk_strcop_d;
2183 rw_cfg.td3 = regk_strcop_e;
2184 break;
2185 case cryptocop_3des_edd:
2186 rw_cfg.td1 = regk_strcop_e;
2187 rw_cfg.td2 = regk_strcop_d;
2188 rw_cfg.td3 = regk_strcop_d;
2189 break;
2190 case cryptocop_3des_dee:
2191 rw_cfg.td1 = regk_strcop_d;
2192 rw_cfg.td2 = regk_strcop_e;
2193 rw_cfg.td3 = regk_strcop_e;
2194 break;
2195 case cryptocop_3des_ded:
2196 rw_cfg.td1 = regk_strcop_d;
2197 rw_cfg.td2 = regk_strcop_e;
2198 rw_cfg.td3 = regk_strcop_d;
2199 break;
2200 case cryptocop_3des_dde:
2201 rw_cfg.td1 = regk_strcop_d;
2202 rw_cfg.td2 = regk_strcop_d;
2203 rw_cfg.td3 = regk_strcop_e;
2204 break;
2205 case cryptocop_3des_ddd:
2206 rw_cfg.td1 = regk_strcop_d;
2207 rw_cfg.td2 = regk_strcop_d;
2208 rw_cfg.td3 = regk_strcop_d;
2209 break;
2210 default:
2211 DEBUG(printk("cryptocop_setup_dma_list: bad 3DES mode\n"));
2212 }
2213 switch (pj->iop->csum_mode){
2214 case cryptocop_csum_le:
2215 rw_cfg.ipend = regk_strcop_little;
2216 break;
2217 case cryptocop_csum_be:
2218 rw_cfg.ipend = regk_strcop_big;
2219 break;
2220 default:
2221 DEBUG(printk("cryptocop_setup_dma_list: bad checksum mode\n"));
2222 }
2223 REG_WR(strcop, regi_strcop, rw_cfg, rw_cfg);
2224
2225 DEBUG(printk("cryptocop_start_job: starting DMA, new cryptocop_running_job=0x%p\n"
2226 "ctx_in: 0x%p, phys: 0x%p\n"
2227 "ctx_out: 0x%p, phys: 0x%p\n",
2228 pj,
2229 &pj->iop->ctx_in, (char*)virt_to_phys(&pj->iop->ctx_in),
2230 &pj->iop->ctx_out, (char*)virt_to_phys(&pj->iop->ctx_out)));
2231
2232 /* Start input DMA. */
2233 flush_dma_context(&pj->iop->ctx_in);
2234 DMA_START_CONTEXT(IN_DMA_INST, virt_to_phys(&pj->iop->ctx_in));
2235
2236 /* Start output DMA. */
2237 DMA_START_CONTEXT(OUT_DMA_INST, virt_to_phys(&pj->iop->ctx_out));
2238
2239 spin_unlock_irqrestore(&running_job_lock, running_job_flags);
2240 DEBUG(printk("cryptocop_start_job: exiting\n"));
2241 }
2242
2243
cryptocop_job_setup(struct cryptocop_prio_job ** pj,struct cryptocop_operation * operation)2244 static int cryptocop_job_setup(struct cryptocop_prio_job **pj, struct cryptocop_operation *operation)
2245 {
2246 int err;
2247 int alloc_flag = operation->in_interrupt ? GFP_ATOMIC : GFP_KERNEL;
2248 void *iop_alloc_ptr = NULL;
2249
2250 *pj = kmalloc(sizeof (struct cryptocop_prio_job), alloc_flag);
2251 if (!*pj) return -ENOMEM;
2252
2253 DEBUG(printk("cryptocop_job_setup: operation=0x%p\n", operation));
2254
2255 (*pj)->oper = operation;
2256 DEBUG(printk("cryptocop_job_setup, cb=0x%p cb_data=0x%p\n", (*pj)->oper->cb, (*pj)->oper->cb_data));
2257
2258 if (operation->use_dmalists) {
2259 DEBUG(print_user_dma_lists(&operation->list_op));
2260 if (!operation->list_op.inlist || !operation->list_op.outlist || !operation->list_op.out_data_buf || !operation->list_op.in_data_buf){
2261 DEBUG_API(printk("cryptocop_job_setup: bad indata (use_dmalists)\n"));
2262 kfree(*pj);
2263 return -EINVAL;
2264 }
2265 iop_alloc_ptr = kmalloc(DESCR_ALLOC_PAD + sizeof(struct cryptocop_int_operation), alloc_flag);
2266 if (!iop_alloc_ptr) {
2267 DEBUG_API(printk("cryptocop_job_setup: kmalloc cryptocop_int_operation\n"));
2268 kfree(*pj);
2269 return -ENOMEM;
2270 }
2271 (*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));
2272 DEBUG(memset((*pj)->iop, 0xff, sizeof(struct cryptocop_int_operation)));
2273 (*pj)->iop->alloc_ptr = iop_alloc_ptr;
2274 (*pj)->iop->sid = operation->sid;
2275 (*pj)->iop->cdesc_out = NULL;
2276 (*pj)->iop->cdesc_in = NULL;
2277 (*pj)->iop->tdes_mode = operation->list_op.tdes_mode;
2278 (*pj)->iop->csum_mode = operation->list_op.csum_mode;
2279 (*pj)->iop->ddesc_out = operation->list_op.outlist;
2280 (*pj)->iop->ddesc_in = operation->list_op.inlist;
2281
2282 /* Setup DMA contexts. */
2283 (*pj)->iop->ctx_out.next = NULL;
2284 (*pj)->iop->ctx_out.eol = 1;
2285 (*pj)->iop->ctx_out.saved_data = operation->list_op.outlist;
2286 (*pj)->iop->ctx_out.saved_data_buf = operation->list_op.out_data_buf;
2287
2288 (*pj)->iop->ctx_in.next = NULL;
2289 (*pj)->iop->ctx_in.eol = 1;
2290 (*pj)->iop->ctx_in.saved_data = operation->list_op.inlist;
2291 (*pj)->iop->ctx_in.saved_data_buf = operation->list_op.in_data_buf;
2292 } else {
2293 if ((err = cryptocop_setup_dma_list(operation, &(*pj)->iop, alloc_flag))) {
2294 DEBUG_API(printk("cryptocop_job_setup: cryptocop_setup_dma_list failed %d\n", err));
2295 kfree(*pj);
2296 return err;
2297 }
2298 }
2299 DEBUG(print_dma_descriptors((*pj)->iop));
2300
2301 DEBUG(printk("cryptocop_job_setup, DMA list setup successful\n"));
2302
2303 return 0;
2304 }
2305
cryptocop_open(struct inode * inode,struct file * filp)2306 static int cryptocop_open(struct inode *inode, struct file *filp)
2307 {
2308 int p = iminor(inode);
2309
2310 cycle_kernel_lock();
2311 if (p != CRYPTOCOP_MINOR) return -EINVAL;
2312
2313 filp->private_data = NULL;
2314 return 0;
2315 }
2316
2317
cryptocop_release(struct inode * inode,struct file * filp)2318 static int cryptocop_release(struct inode *inode, struct file *filp)
2319 {
2320 struct cryptocop_private *dev = filp->private_data;
2321 struct cryptocop_private *dev_next;
2322
2323 while (dev){
2324 dev_next = dev->next;
2325 if (dev->sid != CRYPTOCOP_SESSION_ID_NONE) {
2326 (void)cryptocop_free_session(dev->sid);
2327 }
2328 kfree(dev);
2329 dev = dev_next;
2330 }
2331
2332 return 0;
2333 }
2334
2335
cryptocop_ioctl_close_session(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)2336 static int cryptocop_ioctl_close_session(struct inode *inode, struct file *filp,
2337 unsigned int cmd, unsigned long arg)
2338 {
2339 struct cryptocop_private *dev = filp->private_data;
2340 struct cryptocop_private *prev_dev = NULL;
2341 struct strcop_session_op *sess_op = (struct strcop_session_op *)arg;
2342 struct strcop_session_op sop;
2343 int err;
2344
2345 DEBUG(printk("cryptocop_ioctl_close_session\n"));
2346
2347 if (!access_ok(VERIFY_READ, sess_op, sizeof(struct strcop_session_op)))
2348 return -EFAULT;
2349 err = copy_from_user(&sop, sess_op, sizeof(struct strcop_session_op));
2350 if (err) return -EFAULT;
2351
2352 while (dev && (dev->sid != sop.ses_id)) {
2353 prev_dev = dev;
2354 dev = dev->next;
2355 }
2356 if (dev){
2357 if (prev_dev){
2358 prev_dev->next = dev->next;
2359 } else {
2360 filp->private_data = dev->next;
2361 }
2362 err = cryptocop_free_session(dev->sid);
2363 if (err) return -EFAULT;
2364 } else {
2365 DEBUG_API(printk("cryptocop_ioctl_close_session: session %lld not found\n", sop.ses_id));
2366 return -EINVAL;
2367 }
2368 return 0;
2369 }
2370
2371
ioctl_process_job_callback(struct cryptocop_operation * op,void * cb_data)2372 static void ioctl_process_job_callback(struct cryptocop_operation *op, void*cb_data)
2373 {
2374 struct ioctl_job_cb_ctx *jc = (struct ioctl_job_cb_ctx *)cb_data;
2375
2376 DEBUG(printk("ioctl_process_job_callback: op=0x%p, cb_data=0x%p\n", op, cb_data));
2377
2378 jc->processed = 1;
2379 wake_up(&cryptocop_ioc_process_wq);
2380 }
2381
2382
2383 #define CRYPTOCOP_IOCTL_CIPHER_TID (1)
2384 #define CRYPTOCOP_IOCTL_DIGEST_TID (2)
2385 #define CRYPTOCOP_IOCTL_CSUM_TID (3)
2386
first_cfg_change_ix(struct strcop_crypto_op * crp_op)2387 static size_t first_cfg_change_ix(struct strcop_crypto_op *crp_op)
2388 {
2389 size_t ch_ix = 0;
2390
2391 if (crp_op->do_cipher) ch_ix = crp_op->cipher_start;
2392 if (crp_op->do_digest && (crp_op->digest_start < ch_ix)) ch_ix = crp_op->digest_start;
2393 if (crp_op->do_csum && (crp_op->csum_start < ch_ix)) ch_ix = crp_op->csum_start;
2394
2395 DEBUG(printk("first_cfg_change_ix: ix=%d\n", ch_ix));
2396 return ch_ix;
2397 }
2398
2399
next_cfg_change_ix(struct strcop_crypto_op * crp_op,size_t ix)2400 static size_t next_cfg_change_ix(struct strcop_crypto_op *crp_op, size_t ix)
2401 {
2402 size_t ch_ix = INT_MAX;
2403 size_t tmp_ix = 0;
2404
2405 if (crp_op->do_cipher && ((crp_op->cipher_start + crp_op->cipher_len) > ix)){
2406 if (crp_op->cipher_start > ix) {
2407 ch_ix = crp_op->cipher_start;
2408 } else {
2409 ch_ix = crp_op->cipher_start + crp_op->cipher_len;
2410 }
2411 }
2412 if (crp_op->do_digest && ((crp_op->digest_start + crp_op->digest_len) > ix)){
2413 if (crp_op->digest_start > ix) {
2414 tmp_ix = crp_op->digest_start;
2415 } else {
2416 tmp_ix = crp_op->digest_start + crp_op->digest_len;
2417 }
2418 if (tmp_ix < ch_ix) ch_ix = tmp_ix;
2419 }
2420 if (crp_op->do_csum && ((crp_op->csum_start + crp_op->csum_len) > ix)){
2421 if (crp_op->csum_start > ix) {
2422 tmp_ix = crp_op->csum_start;
2423 } else {
2424 tmp_ix = crp_op->csum_start + crp_op->csum_len;
2425 }
2426 if (tmp_ix < ch_ix) ch_ix = tmp_ix;
2427 }
2428 if (ch_ix == INT_MAX) ch_ix = ix;
2429 DEBUG(printk("next_cfg_change_ix prev ix=%d, next ix=%d\n", ix, ch_ix));
2430 return ch_ix;
2431 }
2432
2433
2434 /* Map map_length bytes from the pages starting on *pageix and *pageoffset to iovecs starting on *iovix.
2435 * Return -1 for ok, 0 for fail. */
map_pages_to_iovec(struct iovec * iov,int iovlen,int * iovix,struct page ** pages,int nopages,int * pageix,int * pageoffset,int map_length)2436 static int map_pages_to_iovec(struct iovec *iov, int iovlen, int *iovix, struct page **pages, int nopages, int *pageix, int *pageoffset, int map_length )
2437 {
2438 int tmplen;
2439
2440 assert(iov != NULL);
2441 assert(iovix != NULL);
2442 assert(pages != NULL);
2443 assert(pageix != NULL);
2444 assert(pageoffset != NULL);
2445
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
2448 while (map_length > 0){
2449 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));
2450 if (*iovix >= iovlen){
2451 DEBUG_API(printk("map_page_to_iovec: *iovix=%d >= iovlen=%d\n", *iovix, iovlen));
2452 return 0;
2453 }
2454 if (*pageix >= nopages){
2455 DEBUG_API(printk("map_page_to_iovec: *pageix=%d >= nopages=%d\n", *pageix, nopages));
2456 return 0;
2457 }
2458 iov[*iovix].iov_base = (unsigned char*)page_address(pages[*pageix]) + *pageoffset;
2459 tmplen = PAGE_SIZE - *pageoffset;
2460 if (tmplen < map_length){
2461 (*pageoffset) = 0;
2462 (*pageix)++;
2463 } else {
2464 tmplen = map_length;
2465 (*pageoffset) += map_length;
2466 }
2467 DEBUG(printk("mapping %d bytes from page %d (or %d) to iovec %d\n", tmplen, *pageix, *pageix-1, *iovix));
2468 iov[*iovix].iov_len = tmplen;
2469 map_length -= tmplen;
2470 (*iovix)++;
2471 }
2472 DEBUG(printk("map_page_to_iovec, exit, *iovix=%d\n", *iovix));
2473 return -1;
2474 }
2475
2476
2477
cryptocop_ioctl_process(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)2478 static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
2479 {
2480 int i;
2481 struct cryptocop_private *dev = filp->private_data;
2482 struct strcop_crypto_op *crp_oper = (struct strcop_crypto_op *)arg;
2483 struct strcop_crypto_op oper = {0};
2484 int err = 0;
2485 struct cryptocop_operation *cop = NULL;
2486
2487 struct ioctl_job_cb_ctx *jc = NULL;
2488
2489 struct page **inpages = NULL;
2490 struct page **outpages = NULL;
2491 int noinpages = 0;
2492 int nooutpages = 0;
2493
2494 struct cryptocop_desc descs[5]; /* Max 5 descriptors are needed, there are three transforms that
2495 * can get connected/disconnected on different places in the indata. */
2496 struct cryptocop_desc_cfg dcfgs[5*3];
2497 int desc_ix = 0;
2498 int dcfg_ix = 0;
2499 struct cryptocop_tfrm_cfg ciph_tcfg = {0};
2500 struct cryptocop_tfrm_cfg digest_tcfg = {0};
2501 struct cryptocop_tfrm_cfg csum_tcfg = {0};
2502
2503 unsigned char *digest_result = NULL;
2504 int digest_length = 0;
2505 int cblocklen = 0;
2506 unsigned char csum_result[CSUM_BLOCK_LENGTH];
2507 struct cryptocop_session *sess;
2508
2509 int iovlen = 0;
2510 int iovix = 0;
2511 int pageix = 0;
2512 int pageoffset = 0;
2513
2514 size_t prev_ix = 0;
2515 size_t next_ix;
2516
2517 int cipher_active, digest_active, csum_active;
2518 int end_digest, end_csum;
2519 int digest_done = 0;
2520 int cipher_done = 0;
2521 int csum_done = 0;
2522
2523 DEBUG(printk("cryptocop_ioctl_process\n"));
2524
2525 if (!access_ok(VERIFY_WRITE, crp_oper, sizeof(struct strcop_crypto_op))){
2526 DEBUG_API(printk("cryptocop_ioctl_process: !access_ok crp_oper!\n"));
2527 return -EFAULT;
2528 }
2529 if (copy_from_user(&oper, crp_oper, sizeof(struct strcop_crypto_op))) {
2530 DEBUG_API(printk("cryptocop_ioctl_process: copy_from_user\n"));
2531 return -EFAULT;
2532 }
2533 DEBUG(print_strcop_crypto_op(&oper));
2534
2535 while (dev && dev->sid != oper.ses_id) dev = dev->next;
2536 if (!dev){
2537 DEBUG_API(printk("cryptocop_ioctl_process: session %lld not found\n", oper.ses_id));
2538 return -EINVAL;
2539 }
2540
2541 /* Check buffers. */
2542 if (((oper.indata + oper.inlen) < oper.indata) || ((oper.cipher_outdata + oper.cipher_outlen) < oper.cipher_outdata)){
2543 DEBUG_API(printk("cryptocop_ioctl_process: user buffers wrapped around, bad user!\n"));
2544 return -EINVAL;
2545 }
2546
2547 if (!access_ok(VERIFY_WRITE, oper.cipher_outdata, oper.cipher_outlen)){
2548 DEBUG_API(printk("cryptocop_ioctl_process: !access_ok out data!\n"));
2549 return -EFAULT;
2550 }
2551 if (!access_ok(VERIFY_READ, oper.indata, oper.inlen)){
2552 DEBUG_API(printk("cryptocop_ioctl_process: !access_ok in data!\n"));
2553 return -EFAULT;
2554 }
2555
2556 cop = kmalloc(sizeof(struct cryptocop_operation), GFP_KERNEL);
2557 if (!cop) {
2558 DEBUG_API(printk("cryptocop_ioctl_process: kmalloc\n"));
2559 return -ENOMEM;
2560 }
2561 jc = kmalloc(sizeof(struct ioctl_job_cb_ctx), GFP_KERNEL);
2562 if (!jc) {
2563 DEBUG_API(printk("cryptocop_ioctl_process: kmalloc\n"));
2564 err = -ENOMEM;
2565 goto error_cleanup;
2566 }
2567 jc->processed = 0;
2568
2569 cop->cb_data = jc;
2570 cop->cb = ioctl_process_job_callback;
2571 cop->operation_status = 0;
2572 cop->use_dmalists = 0;
2573 cop->in_interrupt = 0;
2574 cop->fast_callback = 0;
2575 cop->tfrm_op.tfrm_cfg = NULL;
2576 cop->tfrm_op.desc = NULL;
2577 cop->tfrm_op.indata = NULL;
2578 cop->tfrm_op.incount = 0;
2579 cop->tfrm_op.inlen = 0;
2580 cop->tfrm_op.outdata = NULL;
2581 cop->tfrm_op.outcount = 0;
2582 cop->tfrm_op.outlen = 0;
2583
2584 sess = get_session(oper.ses_id);
2585 if (!sess){
2586 DEBUG_API(printk("cryptocop_ioctl_process: bad session id.\n"));
2587 kfree(cop);
2588 kfree(jc);
2589 return -EINVAL;
2590 }
2591
2592 if (oper.do_cipher) {
2593 unsigned int cipher_outlen = 0;
2594 struct cryptocop_transform_ctx *tc = get_transform_ctx(sess, CRYPTOCOP_IOCTL_CIPHER_TID);
2595 if (!tc) {
2596 DEBUG_API(printk("cryptocop_ioctl_process: no cipher transform in session.\n"));
2597 err = -EINVAL;
2598 goto error_cleanup;
2599 }
2600 ciph_tcfg.tid = CRYPTOCOP_IOCTL_CIPHER_TID;
2601 ciph_tcfg.inject_ix = 0;
2602 ciph_tcfg.flags = 0;
2603 if ((oper.cipher_start < 0) || (oper.cipher_len <= 0) || (oper.cipher_start > oper.inlen) || ((oper.cipher_start + oper.cipher_len) > oper.inlen)){
2604 DEBUG_API(printk("cryptocop_ioctl_process: bad cipher length\n"));
2605 kfree(cop);
2606 kfree(jc);
2607 return -EINVAL;
2608 }
2609 cblocklen = tc->init.alg == cryptocop_alg_aes ? AES_BLOCK_LENGTH : DES_BLOCK_LENGTH;
2610 if (oper.cipher_len % cblocklen) {
2611 kfree(cop);
2612 kfree(jc);
2613 DEBUG_API(printk("cryptocop_ioctl_process: cipher inlength not multiple of block length.\n"));
2614 return -EINVAL;
2615 }
2616 cipher_outlen = oper.cipher_len;
2617 if (tc->init.cipher_mode == cryptocop_cipher_mode_cbc){
2618 if (oper.cipher_explicit) {
2619 ciph_tcfg.flags |= CRYPTOCOP_EXPLICIT_IV;
2620 memcpy(ciph_tcfg.iv, oper.cipher_iv, cblocklen);
2621 } else {
2622 cipher_outlen = oper.cipher_len - cblocklen;
2623 }
2624 } else {
2625 if (oper.cipher_explicit){
2626 kfree(cop);
2627 kfree(jc);
2628 DEBUG_API(printk("cryptocop_ioctl_process: explicit_iv when not CBC mode\n"));
2629 return -EINVAL;
2630 }
2631 }
2632 if (oper.cipher_outlen != cipher_outlen) {
2633 kfree(cop);
2634 kfree(jc);
2635 DEBUG_API(printk("cryptocop_ioctl_process: cipher_outlen incorrect, should be %d not %d.\n", cipher_outlen, oper.cipher_outlen));
2636 return -EINVAL;
2637 }
2638
2639 if (oper.decrypt){
2640 ciph_tcfg.flags |= CRYPTOCOP_DECRYPT;
2641 } else {
2642 ciph_tcfg.flags |= CRYPTOCOP_ENCRYPT;
2643 }
2644 ciph_tcfg.next = cop->tfrm_op.tfrm_cfg;
2645 cop->tfrm_op.tfrm_cfg = &ciph_tcfg;
2646 }
2647 if (oper.do_digest){
2648 struct cryptocop_transform_ctx *tc = get_transform_ctx(sess, CRYPTOCOP_IOCTL_DIGEST_TID);
2649 if (!tc) {
2650 DEBUG_API(printk("cryptocop_ioctl_process: no digest transform in session.\n"));
2651 err = -EINVAL;
2652 goto error_cleanup;
2653 }
2654 digest_length = tc->init.alg == cryptocop_alg_md5 ? 16 : 20;
2655 digest_result = kmalloc(digest_length, GFP_KERNEL);
2656 if (!digest_result) {
2657 DEBUG_API(printk("cryptocop_ioctl_process: kmalloc digest_result\n"));
2658 err = -EINVAL;
2659 goto error_cleanup;
2660 }
2661 DEBUG(memset(digest_result, 0xff, digest_length));
2662
2663 digest_tcfg.tid = CRYPTOCOP_IOCTL_DIGEST_TID;
2664 digest_tcfg.inject_ix = 0;
2665 ciph_tcfg.inject_ix += digest_length;
2666 if ((oper.digest_start < 0) || (oper.digest_len <= 0) || (oper.digest_start > oper.inlen) || ((oper.digest_start + oper.digest_len) > oper.inlen)){
2667 DEBUG_API(printk("cryptocop_ioctl_process: bad digest length\n"));
2668 err = -EINVAL;
2669 goto error_cleanup;
2670 }
2671
2672 digest_tcfg.next = cop->tfrm_op.tfrm_cfg;
2673 cop->tfrm_op.tfrm_cfg = &digest_tcfg;
2674 }
2675 if (oper.do_csum){
2676 csum_tcfg.tid = CRYPTOCOP_IOCTL_CSUM_TID;
2677 csum_tcfg.inject_ix = digest_length;
2678 ciph_tcfg.inject_ix += 2;
2679
2680 if ((oper.csum_start < 0) || (oper.csum_len <= 0) || (oper.csum_start > oper.inlen) || ((oper.csum_start + oper.csum_len) > oper.inlen)){
2681 DEBUG_API(printk("cryptocop_ioctl_process: bad csum length\n"));
2682 kfree(cop);
2683 kfree(jc);
2684 return -EINVAL;
2685 }
2686
2687 csum_tcfg.next = cop->tfrm_op.tfrm_cfg;
2688 cop->tfrm_op.tfrm_cfg = &csum_tcfg;
2689 }
2690
2691 prev_ix = first_cfg_change_ix(&oper);
2692 if (prev_ix > oper.inlen) {
2693 DEBUG_API(printk("cryptocop_ioctl_process: length mismatch\n"));
2694 nooutpages = noinpages = 0;
2695 err = -EINVAL;
2696 goto error_cleanup;
2697 }
2698 DEBUG(printk("cryptocop_ioctl_process: inlen=%d, cipher_outlen=%d\n", oper.inlen, oper.cipher_outlen));
2699
2700 /* Map user pages for in and out data of the operation. */
2701 noinpages = (((unsigned long int)(oper.indata + prev_ix) & ~PAGE_MASK) + oper.inlen - 1 - prev_ix + ~PAGE_MASK) >> PAGE_SHIFT;
2702 DEBUG(printk("cryptocop_ioctl_process: noinpages=%d\n", noinpages));
2703 inpages = kmalloc(noinpages * sizeof(struct page*), GFP_KERNEL);
2704 if (!inpages){
2705 DEBUG_API(printk("cryptocop_ioctl_process: kmalloc inpages\n"));
2706 nooutpages = noinpages = 0;
2707 err = -ENOMEM;
2708 goto error_cleanup;
2709 }
2710 if (oper.do_cipher){
2711 nooutpages = (((unsigned long int)oper.cipher_outdata & ~PAGE_MASK) + oper.cipher_outlen - 1 + ~PAGE_MASK) >> PAGE_SHIFT;
2712 DEBUG(printk("cryptocop_ioctl_process: nooutpages=%d\n", nooutpages));
2713 outpages = kmalloc(nooutpages * sizeof(struct page*), GFP_KERNEL);
2714 if (!outpages){
2715 DEBUG_API(printk("cryptocop_ioctl_process: kmalloc outpages\n"));
2716 nooutpages = noinpages = 0;
2717 err = -ENOMEM;
2718 goto error_cleanup;
2719 }
2720 }
2721
2722 /* Acquire the mm page semaphore. */
2723 down_read(¤t->mm->mmap_sem);
2724
2725 err = get_user_pages(current,
2726 current->mm,
2727 (unsigned long int)(oper.indata + prev_ix),
2728 noinpages,
2729 0, /* read access only for in data */
2730 0, /* no force */
2731 inpages,
2732 NULL);
2733
2734 if (err < 0) {
2735 up_read(¤t->mm->mmap_sem);
2736 nooutpages = noinpages = 0;
2737 DEBUG_API(printk("cryptocop_ioctl_process: get_user_pages indata\n"));
2738 goto error_cleanup;
2739 }
2740 noinpages = err;
2741 if (oper.do_cipher){
2742 err = get_user_pages(current,
2743 current->mm,
2744 (unsigned long int)oper.cipher_outdata,
2745 nooutpages,
2746 1, /* write access for out data */
2747 0, /* no force */
2748 outpages,
2749 NULL);
2750 up_read(¤t->mm->mmap_sem);
2751 if (err < 0) {
2752 nooutpages = 0;
2753 DEBUG_API(printk("cryptocop_ioctl_process: get_user_pages outdata\n"));
2754 goto error_cleanup;
2755 }
2756 nooutpages = err;
2757 } else {
2758 up_read(¤t->mm->mmap_sem);
2759 }
2760
2761 /* Add 6 to nooutpages to make room for possibly inserted buffers for storing digest and
2762 * csum output and splits when units are (dis-)connected. */
2763 cop->tfrm_op.indata = kmalloc((noinpages) * sizeof(struct iovec), GFP_KERNEL);
2764 cop->tfrm_op.outdata = kmalloc((6 + nooutpages) * sizeof(struct iovec), GFP_KERNEL);
2765 if (!cop->tfrm_op.indata || !cop->tfrm_op.outdata) {
2766 DEBUG_API(printk("cryptocop_ioctl_process: kmalloc iovecs\n"));
2767 err = -ENOMEM;
2768 goto error_cleanup;
2769 }
2770
2771 cop->tfrm_op.inlen = oper.inlen - prev_ix;
2772 cop->tfrm_op.outlen = 0;
2773 if (oper.do_cipher) cop->tfrm_op.outlen += oper.cipher_outlen;
2774 if (oper.do_digest) cop->tfrm_op.outlen += digest_length;
2775 if (oper.do_csum) cop->tfrm_op.outlen += 2;
2776
2777 /* Setup the in iovecs. */
2778 cop->tfrm_op.incount = noinpages;
2779 if (noinpages > 1){
2780 size_t tmplen = cop->tfrm_op.inlen;
2781
2782 cop->tfrm_op.indata[0].iov_len = PAGE_SIZE - ((unsigned long int)(oper.indata + prev_ix) & ~PAGE_MASK);
2783 cop->tfrm_op.indata[0].iov_base = (unsigned char*)page_address(inpages[0]) + ((unsigned long int)(oper.indata + prev_ix) & ~PAGE_MASK);
2784 tmplen -= cop->tfrm_op.indata[0].iov_len;
2785 for (i = 1; i<noinpages; i++){
2786 cop->tfrm_op.indata[i].iov_len = tmplen < PAGE_SIZE ? tmplen : PAGE_SIZE;
2787 cop->tfrm_op.indata[i].iov_base = (unsigned char*)page_address(inpages[i]);
2788 tmplen -= PAGE_SIZE;
2789 }
2790 } else {
2791 cop->tfrm_op.indata[0].iov_len = oper.inlen - prev_ix;
2792 cop->tfrm_op.indata[0].iov_base = (unsigned char*)page_address(inpages[0]) + ((unsigned long int)(oper.indata + prev_ix) & ~PAGE_MASK);
2793 }
2794
2795 iovlen = nooutpages + 6;
2796 pageoffset = oper.do_cipher ? ((unsigned long int)oper.cipher_outdata & ~PAGE_MASK) : 0;
2797
2798 next_ix = next_cfg_change_ix(&oper, prev_ix);
2799 if (prev_ix == next_ix){
2800 DEBUG_API(printk("cryptocop_ioctl_process: length configuration broken.\n"));
2801 err = -EINVAL; /* This should be impossible barring bugs. */
2802 goto error_cleanup;
2803 }
2804 while (prev_ix != next_ix){
2805 end_digest = end_csum = cipher_active = digest_active = csum_active = 0;
2806 descs[desc_ix].cfg = NULL;
2807 descs[desc_ix].length = next_ix - prev_ix;
2808
2809 if (oper.do_cipher && (oper.cipher_start < next_ix) && (prev_ix < (oper.cipher_start + oper.cipher_len))) {
2810 dcfgs[dcfg_ix].tid = CRYPTOCOP_IOCTL_CIPHER_TID;
2811 dcfgs[dcfg_ix].src = cryptocop_source_dma;
2812 cipher_active = 1;
2813
2814 if (next_ix == (oper.cipher_start + oper.cipher_len)){
2815 cipher_done = 1;
2816 dcfgs[dcfg_ix].last = 1;
2817 } else {
2818 dcfgs[dcfg_ix].last = 0;
2819 }
2820 dcfgs[dcfg_ix].next = descs[desc_ix].cfg;
2821 descs[desc_ix].cfg = &dcfgs[dcfg_ix];
2822 ++dcfg_ix;
2823 }
2824 if (oper.do_digest && (oper.digest_start < next_ix) && (prev_ix < (oper.digest_start + oper.digest_len))) {
2825 digest_active = 1;
2826 dcfgs[dcfg_ix].tid = CRYPTOCOP_IOCTL_DIGEST_TID;
2827 dcfgs[dcfg_ix].src = cryptocop_source_dma;
2828 if (next_ix == (oper.digest_start + oper.digest_len)){
2829 assert(!digest_done);
2830 digest_done = 1;
2831 dcfgs[dcfg_ix].last = 1;
2832 } else {
2833 dcfgs[dcfg_ix].last = 0;
2834 }
2835 dcfgs[dcfg_ix].next = descs[desc_ix].cfg;
2836 descs[desc_ix].cfg = &dcfgs[dcfg_ix];
2837 ++dcfg_ix;
2838 }
2839 if (oper.do_csum && (oper.csum_start < next_ix) && (prev_ix < (oper.csum_start + oper.csum_len))){
2840 csum_active = 1;
2841 dcfgs[dcfg_ix].tid = CRYPTOCOP_IOCTL_CSUM_TID;
2842 dcfgs[dcfg_ix].src = cryptocop_source_dma;
2843 if (next_ix == (oper.csum_start + oper.csum_len)){
2844 csum_done = 1;
2845 dcfgs[dcfg_ix].last = 1;
2846 } else {
2847 dcfgs[dcfg_ix].last = 0;
2848 }
2849 dcfgs[dcfg_ix].next = descs[desc_ix].cfg;
2850 descs[desc_ix].cfg = &dcfgs[dcfg_ix];
2851 ++dcfg_ix;
2852 }
2853 if (!descs[desc_ix].cfg){
2854 DEBUG_API(printk("cryptocop_ioctl_process: data segment %d (%d to %d) had no active transforms\n", desc_ix, prev_ix, next_ix));
2855 err = -EINVAL;
2856 goto error_cleanup;
2857 }
2858 descs[desc_ix].next = &(descs[desc_ix]) + 1;
2859 ++desc_ix;
2860 prev_ix = next_ix;
2861 next_ix = next_cfg_change_ix(&oper, prev_ix);
2862 }
2863 if (desc_ix > 0){
2864 descs[desc_ix-1].next = NULL;
2865 } else {
2866 descs[0].next = NULL;
2867 }
2868 if (oper.do_digest) {
2869 DEBUG(printk("cryptocop_ioctl_process: mapping %d byte digest output to iovec %d\n", digest_length, iovix));
2870 /* Add outdata iovec, length == <length of type of digest> */
2871 cop->tfrm_op.outdata[iovix].iov_base = digest_result;
2872 cop->tfrm_op.outdata[iovix].iov_len = digest_length;
2873 ++iovix;
2874 }
2875 if (oper.do_csum) {
2876 /* Add outdata iovec, length == 2, the length of csum. */
2877 DEBUG(printk("cryptocop_ioctl_process: mapping 2 byte csum output to iovec %d\n", iovix));
2878 /* Add outdata iovec, length == <length of type of digest> */
2879 cop->tfrm_op.outdata[iovix].iov_base = csum_result;
2880 cop->tfrm_op.outdata[iovix].iov_len = 2;
2881 ++iovix;
2882 }
2883 if (oper.do_cipher) {
2884 if (!map_pages_to_iovec(cop->tfrm_op.outdata, iovlen, &iovix, outpages, nooutpages, &pageix, &pageoffset, oper.cipher_outlen)){
2885 DEBUG_API(printk("cryptocop_ioctl_process: failed to map pages to iovec.\n"));
2886 err = -ENOSYS; /* This should be impossible barring bugs. */
2887 goto error_cleanup;
2888 }
2889 }
2890 DEBUG(printk("cryptocop_ioctl_process: setting cop->tfrm_op.outcount %d\n", iovix));
2891 cop->tfrm_op.outcount = iovix;
2892 assert(iovix <= (nooutpages + 6));
2893
2894 cop->sid = oper.ses_id;
2895 cop->tfrm_op.desc = &descs[0];
2896
2897 DEBUG(printk("cryptocop_ioctl_process: inserting job, cb_data=0x%p\n", cop->cb_data));
2898
2899 if ((err = cryptocop_job_queue_insert_user_job(cop)) != 0) {
2900 DEBUG_API(printk("cryptocop_ioctl_process: insert job %d\n", err));
2901 err = -EINVAL;
2902 goto error_cleanup;
2903 }
2904
2905 DEBUG(printk("cryptocop_ioctl_process: begin wait for result\n"));
2906
2907 wait_event(cryptocop_ioc_process_wq, (jc->processed != 0));
2908 DEBUG(printk("cryptocop_ioctl_process: end wait for result\n"));
2909 if (!jc->processed){
2910 printk(KERN_WARNING "cryptocop_ioctl_process: job not processed at completion\n");
2911 err = -EIO;
2912 goto error_cleanup;
2913 }
2914
2915 /* Job process done. Cipher output should already be correct in job so no post processing of outdata. */
2916 DEBUG(printk("cryptocop_ioctl_process: operation_status = %d\n", cop->operation_status));
2917 if (cop->operation_status == 0){
2918 if (oper.do_digest){
2919 DEBUG(printk("cryptocop_ioctl_process: copy %d bytes digest to user\n", digest_length));
2920 err = copy_to_user((unsigned char*)crp_oper + offsetof(struct strcop_crypto_op, digest), digest_result, digest_length);
2921 if (0 != err){
2922 DEBUG_API(printk("cryptocop_ioctl_process: copy_to_user, digest length %d, err %d\n", digest_length, err));
2923 err = -EFAULT;
2924 goto error_cleanup;
2925 }
2926 }
2927 if (oper.do_csum){
2928 DEBUG(printk("cryptocop_ioctl_process: copy 2 bytes checksum to user\n"));
2929 err = copy_to_user((unsigned char*)crp_oper + offsetof(struct strcop_crypto_op, csum), csum_result, 2);
2930 if (0 != err){
2931 DEBUG_API(printk("cryptocop_ioctl_process: copy_to_user, csum, err %d\n", err));
2932 err = -EFAULT;
2933 goto error_cleanup;
2934 }
2935 }
2936 err = 0;
2937 } else {
2938 DEBUG(printk("cryptocop_ioctl_process: returning err = operation_status = %d\n", cop->operation_status));
2939 err = cop->operation_status;
2940 }
2941
2942 error_cleanup:
2943 /* Release page caches. */
2944 for (i = 0; i < noinpages; i++){
2945 put_page(inpages[i]);
2946 }
2947 for (i = 0; i < nooutpages; i++){
2948 int spdl_err;
2949 /* Mark output pages dirty. */
2950 spdl_err = set_page_dirty_lock(outpages[i]);
2951 DEBUG(if (spdl_err < 0)printk("cryptocop_ioctl_process: set_page_dirty_lock returned %d\n", spdl_err));
2952 }
2953 for (i = 0; i < nooutpages; i++){
2954 put_page(outpages[i]);
2955 }
2956
2957 kfree(digest_result);
2958 kfree(inpages);
2959 kfree(outpages);
2960 if (cop){
2961 kfree(cop->tfrm_op.indata);
2962 kfree(cop->tfrm_op.outdata);
2963 kfree(cop);
2964 }
2965 kfree(jc);
2966
2967 DEBUG(print_lock_status());
2968
2969 return err;
2970 }
2971
2972
cryptocop_ioctl_create_session(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)2973 static int cryptocop_ioctl_create_session(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
2974 {
2975 cryptocop_session_id sid;
2976 int err;
2977 struct cryptocop_private *dev;
2978 struct strcop_session_op *sess_op = (struct strcop_session_op *)arg;
2979 struct strcop_session_op sop;
2980 struct cryptocop_transform_init *tis = NULL;
2981 struct cryptocop_transform_init ti_cipher = {0};
2982 struct cryptocop_transform_init ti_digest = {0};
2983 struct cryptocop_transform_init ti_csum = {0};
2984
2985 if (!access_ok(VERIFY_WRITE, sess_op, sizeof(struct strcop_session_op)))
2986 return -EFAULT;
2987 err = copy_from_user(&sop, sess_op, sizeof(struct strcop_session_op));
2988 if (err) return -EFAULT;
2989 if (sop.cipher != cryptocop_cipher_none) {
2990 if (!access_ok(VERIFY_READ, sop.key, sop.keylen)) return -EFAULT;
2991 }
2992 DEBUG(printk("cryptocop_ioctl_create_session, sess_op:\n"));
2993
2994 DEBUG(printk("\tcipher:%d\n"
2995 "\tcipher_mode:%d\n"
2996 "\tdigest:%d\n"
2997 "\tcsum:%d\n",
2998 (int)sop.cipher,
2999 (int)sop.cmode,
3000 (int)sop.digest,
3001 (int)sop.csum));
3002
3003 if (sop.cipher != cryptocop_cipher_none){
3004 /* Init the cipher. */
3005 switch (sop.cipher){
3006 case cryptocop_cipher_des:
3007 ti_cipher.alg = cryptocop_alg_des;
3008 break;
3009 case cryptocop_cipher_3des:
3010 ti_cipher.alg = cryptocop_alg_3des;
3011 break;
3012 case cryptocop_cipher_aes:
3013 ti_cipher.alg = cryptocop_alg_aes;
3014 break;
3015 default:
3016 DEBUG_API(printk("create session, bad cipher algorithm %d\n", sop.cipher));
3017 return -EINVAL;
3018 };
3019 DEBUG(printk("setting cipher transform %d\n", ti_cipher.alg));
3020 copy_from_user(ti_cipher.key, sop.key, sop.keylen/8);
3021 ti_cipher.keylen = sop.keylen;
3022 switch (sop.cmode){
3023 case cryptocop_cipher_mode_cbc:
3024 case cryptocop_cipher_mode_ecb:
3025 ti_cipher.cipher_mode = sop.cmode;
3026 break;
3027 default:
3028 DEBUG_API(printk("create session, bad cipher mode %d\n", sop.cmode));
3029 return -EINVAL;
3030 }
3031 DEBUG(printk("cryptocop_ioctl_create_session: setting CBC mode %d\n", ti_cipher.cipher_mode));
3032 switch (sop.des3_mode){
3033 case cryptocop_3des_eee:
3034 case cryptocop_3des_eed:
3035 case cryptocop_3des_ede:
3036 case cryptocop_3des_edd:
3037 case cryptocop_3des_dee:
3038 case cryptocop_3des_ded:
3039 case cryptocop_3des_dde:
3040 case cryptocop_3des_ddd:
3041 ti_cipher.tdes_mode = sop.des3_mode;
3042 break;
3043 default:
3044 DEBUG_API(printk("create session, bad 3DES mode %d\n", sop.des3_mode));
3045 return -EINVAL;
3046 }
3047 ti_cipher.tid = CRYPTOCOP_IOCTL_CIPHER_TID;
3048 ti_cipher.next = tis;
3049 tis = &ti_cipher;
3050 } /* if (sop.cipher != cryptocop_cipher_none) */
3051 if (sop.digest != cryptocop_digest_none){
3052 DEBUG(printk("setting digest transform\n"));
3053 switch (sop.digest){
3054 case cryptocop_digest_md5:
3055 ti_digest.alg = cryptocop_alg_md5;
3056 break;
3057 case cryptocop_digest_sha1:
3058 ti_digest.alg = cryptocop_alg_sha1;
3059 break;
3060 default:
3061 DEBUG_API(printk("create session, bad digest algorithm %d\n", sop.digest));
3062 return -EINVAL;
3063 }
3064 ti_digest.tid = CRYPTOCOP_IOCTL_DIGEST_TID;
3065 ti_digest.next = tis;
3066 tis = &ti_digest;
3067 } /* if (sop.digest != cryptocop_digest_none) */
3068 if (sop.csum != cryptocop_csum_none){
3069 DEBUG(printk("setting csum transform\n"));
3070 switch (sop.csum){
3071 case cryptocop_csum_le:
3072 case cryptocop_csum_be:
3073 ti_csum.csum_mode = sop.csum;
3074 break;
3075 default:
3076 DEBUG_API(printk("create session, bad checksum algorithm %d\n", sop.csum));
3077 return -EINVAL;
3078 }
3079 ti_csum.alg = cryptocop_alg_csum;
3080 ti_csum.tid = CRYPTOCOP_IOCTL_CSUM_TID;
3081 ti_csum.next = tis;
3082 tis = &ti_csum;
3083 } /* (sop.csum != cryptocop_csum_none) */
3084 dev = kmalloc(sizeof(struct cryptocop_private), GFP_KERNEL);
3085 if (!dev){
3086 DEBUG_API(printk("create session, alloc dev\n"));
3087 return -ENOMEM;
3088 }
3089
3090 err = cryptocop_new_session(&sid, tis, GFP_KERNEL);
3091 DEBUG({ if (err) printk("create session, cryptocop_new_session %d\n", err);});
3092
3093 if (err) {
3094 kfree(dev);
3095 return err;
3096 }
3097 sess_op->ses_id = sid;
3098 dev->sid = sid;
3099 dev->next = filp->private_data;
3100 filp->private_data = dev;
3101
3102 return 0;
3103 }
3104
cryptocop_ioctl(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)3105 static int cryptocop_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
3106 {
3107 int err = 0;
3108 if (_IOC_TYPE(cmd) != ETRAXCRYPTOCOP_IOCTYPE) {
3109 DEBUG_API(printk("cryptocop_ioctl: wrong type\n"));
3110 return -ENOTTY;
3111 }
3112 if (_IOC_NR(cmd) > CRYPTOCOP_IO_MAXNR){
3113 return -ENOTTY;
3114 }
3115 /* Access check of the argument. Some commands, e.g. create session and process op,
3116 needs additional checks. Those are handled in the command handling functions. */
3117 if (_IOC_DIR(cmd) & _IOC_READ)
3118 err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
3119 else if (_IOC_DIR(cmd) & _IOC_WRITE)
3120 err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
3121 if (err) return -EFAULT;
3122
3123 switch (cmd) {
3124 case CRYPTOCOP_IO_CREATE_SESSION:
3125 return cryptocop_ioctl_create_session(inode, filp, cmd, arg);
3126 case CRYPTOCOP_IO_CLOSE_SESSION:
3127 return cryptocop_ioctl_close_session(inode, filp, cmd, arg);
3128 case CRYPTOCOP_IO_PROCESS_OP:
3129 return cryptocop_ioctl_process(inode, filp, cmd, arg);
3130 default:
3131 DEBUG_API(printk("cryptocop_ioctl: unknown command\n"));
3132 return -ENOTTY;
3133 }
3134 return 0;
3135 }
3136
3137
3138 #ifdef LDEBUG
print_dma_descriptors(struct cryptocop_int_operation * iop)3139 static void print_dma_descriptors(struct cryptocop_int_operation *iop)
3140 {
3141 struct cryptocop_dma_desc *cdesc_out = iop->cdesc_out;
3142 struct cryptocop_dma_desc *cdesc_in = iop->cdesc_in;
3143 int i;
3144
3145 printk("print_dma_descriptors start\n");
3146
3147 printk("iop:\n");
3148 printk("\tsid: 0x%lld\n", iop->sid);
3149
3150 printk("\tcdesc_out: 0x%p\n", iop->cdesc_out);
3151 printk("\tcdesc_in: 0x%p\n", iop->cdesc_in);
3152 printk("\tddesc_out: 0x%p\n", iop->ddesc_out);
3153 printk("\tddesc_in: 0x%p\n", iop->ddesc_in);
3154
3155 printk("\niop->ctx_out: 0x%p phys: 0x%p\n", &iop->ctx_out, (char*)virt_to_phys(&iop->ctx_out));
3156 printk("\tnext: 0x%p\n"
3157 "\tsaved_data: 0x%p\n"
3158 "\tsaved_data_buf: 0x%p\n",
3159 iop->ctx_out.next,
3160 iop->ctx_out.saved_data,
3161 iop->ctx_out.saved_data_buf);
3162
3163 printk("\niop->ctx_in: 0x%p phys: 0x%p\n", &iop->ctx_in, (char*)virt_to_phys(&iop->ctx_in));
3164 printk("\tnext: 0x%p\n"
3165 "\tsaved_data: 0x%p\n"
3166 "\tsaved_data_buf: 0x%p\n",
3167 iop->ctx_in.next,
3168 iop->ctx_in.saved_data,
3169 iop->ctx_in.saved_data_buf);
3170
3171 i = 0;
3172 while (cdesc_out) {
3173 dma_descr_data *td;
3174 printk("cdesc_out %d, desc=0x%p\n", i, cdesc_out->dma_descr);
3175 printk("\n\tvirt_to_phys(desc): 0x%p\n", (char*)virt_to_phys(cdesc_out->dma_descr));
3176 td = cdesc_out->dma_descr;
3177 printk("\n\tbuf: 0x%p\n"
3178 "\tafter: 0x%p\n"
3179 "\tmd: 0x%04x\n"
3180 "\tnext: 0x%p\n",
3181 td->buf,
3182 td->after,
3183 td->md,
3184 td->next);
3185 printk("flags:\n"
3186 "\twait:\t%d\n"
3187 "\teol:\t%d\n"
3188 "\touteop:\t%d\n"
3189 "\tineop:\t%d\n"
3190 "\tintr:\t%d\n",
3191 td->wait,
3192 td->eol,
3193 td->out_eop,
3194 td->in_eop,
3195 td->intr);
3196 cdesc_out = cdesc_out->next;
3197 i++;
3198 }
3199 i = 0;
3200 while (cdesc_in) {
3201 dma_descr_data *td;
3202 printk("cdesc_in %d, desc=0x%p\n", i, cdesc_in->dma_descr);
3203 printk("\n\tvirt_to_phys(desc): 0x%p\n", (char*)virt_to_phys(cdesc_in->dma_descr));
3204 td = cdesc_in->dma_descr;
3205 printk("\n\tbuf: 0x%p\n"
3206 "\tafter: 0x%p\n"
3207 "\tmd: 0x%04x\n"
3208 "\tnext: 0x%p\n",
3209 td->buf,
3210 td->after,
3211 td->md,
3212 td->next);
3213 printk("flags:\n"
3214 "\twait:\t%d\n"
3215 "\teol:\t%d\n"
3216 "\touteop:\t%d\n"
3217 "\tineop:\t%d\n"
3218 "\tintr:\t%d\n",
3219 td->wait,
3220 td->eol,
3221 td->out_eop,
3222 td->in_eop,
3223 td->intr);
3224 cdesc_in = cdesc_in->next;
3225 i++;
3226 }
3227
3228 printk("print_dma_descriptors end\n");
3229 }
3230
3231
print_strcop_crypto_op(struct strcop_crypto_op * cop)3232 static void print_strcop_crypto_op(struct strcop_crypto_op *cop)
3233 {
3234 printk("print_strcop_crypto_op, 0x%p\n", cop);
3235
3236 /* Indata. */
3237 printk("indata=0x%p\n"
3238 "inlen=%d\n"
3239 "do_cipher=%d\n"
3240 "decrypt=%d\n"
3241 "cipher_explicit=%d\n"
3242 "cipher_start=%d\n"
3243 "cipher_len=%d\n"
3244 "outdata=0x%p\n"
3245 "outlen=%d\n",
3246 cop->indata,
3247 cop->inlen,
3248 cop->do_cipher,
3249 cop->decrypt,
3250 cop->cipher_explicit,
3251 cop->cipher_start,
3252 cop->cipher_len,
3253 cop->cipher_outdata,
3254 cop->cipher_outlen);
3255
3256 printk("do_digest=%d\n"
3257 "digest_start=%d\n"
3258 "digest_len=%d\n",
3259 cop->do_digest,
3260 cop->digest_start,
3261 cop->digest_len);
3262
3263 printk("do_csum=%d\n"
3264 "csum_start=%d\n"
3265 "csum_len=%d\n",
3266 cop->do_csum,
3267 cop->csum_start,
3268 cop->csum_len);
3269 }
3270
print_cryptocop_operation(struct cryptocop_operation * cop)3271 static void print_cryptocop_operation(struct cryptocop_operation *cop)
3272 {
3273 struct cryptocop_desc *d;
3274 struct cryptocop_tfrm_cfg *tc;
3275 struct cryptocop_desc_cfg *dc;
3276 int i;
3277
3278 printk("print_cryptocop_operation, cop=0x%p\n\n", cop);
3279 printk("sid: %lld\n", cop->sid);
3280 printk("operation_status=%d\n"
3281 "use_dmalists=%d\n"
3282 "in_interrupt=%d\n"
3283 "fast_callback=%d\n",
3284 cop->operation_status,
3285 cop->use_dmalists,
3286 cop->in_interrupt,
3287 cop->fast_callback);
3288
3289 if (cop->use_dmalists){
3290 print_user_dma_lists(&cop->list_op);
3291 } else {
3292 printk("cop->tfrm_op\n"
3293 "tfrm_cfg=0x%p\n"
3294 "desc=0x%p\n"
3295 "indata=0x%p\n"
3296 "incount=%d\n"
3297 "inlen=%d\n"
3298 "outdata=0x%p\n"
3299 "outcount=%d\n"
3300 "outlen=%d\n\n",
3301 cop->tfrm_op.tfrm_cfg,
3302 cop->tfrm_op.desc,
3303 cop->tfrm_op.indata,
3304 cop->tfrm_op.incount,
3305 cop->tfrm_op.inlen,
3306 cop->tfrm_op.outdata,
3307 cop->tfrm_op.outcount,
3308 cop->tfrm_op.outlen);
3309
3310 tc = cop->tfrm_op.tfrm_cfg;
3311 while (tc){
3312 printk("tfrm_cfg, 0x%p\n"
3313 "tid=%d\n"
3314 "flags=%d\n"
3315 "inject_ix=%d\n"
3316 "next=0x%p\n",
3317 tc,
3318 tc->tid,
3319 tc->flags,
3320 tc->inject_ix,
3321 tc->next);
3322 tc = tc->next;
3323 }
3324 d = cop->tfrm_op.desc;
3325 while (d){
3326 printk("\n======================desc, 0x%p\n"
3327 "length=%d\n"
3328 "cfg=0x%p\n"
3329 "next=0x%p\n",
3330 d,
3331 d->length,
3332 d->cfg,
3333 d->next);
3334 dc = d->cfg;
3335 while (dc){
3336 printk("=========desc_cfg, 0x%p\n"
3337 "tid=%d\n"
3338 "src=%d\n"
3339 "last=%d\n"
3340 "next=0x%p\n",
3341 dc,
3342 dc->tid,
3343 dc->src,
3344 dc->last,
3345 dc->next);
3346 dc = dc->next;
3347 }
3348 d = d->next;
3349 }
3350 printk("\n====iniov\n");
3351 for (i = 0; i < cop->tfrm_op.incount; i++){
3352 printk("indata[%d]\n"
3353 "base=0x%p\n"
3354 "len=%d\n",
3355 i,
3356 cop->tfrm_op.indata[i].iov_base,
3357 cop->tfrm_op.indata[i].iov_len);
3358 }
3359 printk("\n====outiov\n");
3360 for (i = 0; i < cop->tfrm_op.outcount; i++){
3361 printk("outdata[%d]\n"
3362 "base=0x%p\n"
3363 "len=%d\n",
3364 i,
3365 cop->tfrm_op.outdata[i].iov_base,
3366 cop->tfrm_op.outdata[i].iov_len);
3367 }
3368 }
3369 printk("------------end print_cryptocop_operation\n");
3370 }
3371
3372
print_user_dma_lists(struct cryptocop_dma_list_operation * dma_op)3373 static void print_user_dma_lists(struct cryptocop_dma_list_operation *dma_op)
3374 {
3375 dma_descr_data *dd;
3376 int i;
3377
3378 printk("print_user_dma_lists, dma_op=0x%p\n", dma_op);
3379
3380 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));
3381 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));
3382
3383 printk("##############outlist\n");
3384 dd = phys_to_virt((unsigned long int)dma_op->outlist);
3385 i = 0;
3386 while (dd != NULL) {
3387 printk("#%d phys_to_virt(desc) 0x%p\n", i, dd);
3388 printk("\n\tbuf: 0x%p\n"
3389 "\tafter: 0x%p\n"
3390 "\tmd: 0x%04x\n"
3391 "\tnext: 0x%p\n",
3392 dd->buf,
3393 dd->after,
3394 dd->md,
3395 dd->next);
3396 printk("flags:\n"
3397 "\twait:\t%d\n"
3398 "\teol:\t%d\n"
3399 "\touteop:\t%d\n"
3400 "\tineop:\t%d\n"
3401 "\tintr:\t%d\n",
3402 dd->wait,
3403 dd->eol,
3404 dd->out_eop,
3405 dd->in_eop,
3406 dd->intr);
3407 if (dd->eol)
3408 dd = NULL;
3409 else
3410 dd = phys_to_virt((unsigned long int)dd->next);
3411 ++i;
3412 }
3413
3414 printk("##############inlist\n");
3415 dd = phys_to_virt((unsigned long int)dma_op->inlist);
3416 i = 0;
3417 while (dd != NULL) {
3418 printk("#%d phys_to_virt(desc) 0x%p\n", i, dd);
3419 printk("\n\tbuf: 0x%p\n"
3420 "\tafter: 0x%p\n"
3421 "\tmd: 0x%04x\n"
3422 "\tnext: 0x%p\n",
3423 dd->buf,
3424 dd->after,
3425 dd->md,
3426 dd->next);
3427 printk("flags:\n"
3428 "\twait:\t%d\n"
3429 "\teol:\t%d\n"
3430 "\touteop:\t%d\n"
3431 "\tineop:\t%d\n"
3432 "\tintr:\t%d\n",
3433 dd->wait,
3434 dd->eol,
3435 dd->out_eop,
3436 dd->in_eop,
3437 dd->intr);
3438 if (dd->eol)
3439 dd = NULL;
3440 else
3441 dd = phys_to_virt((unsigned long int)dd->next);
3442 ++i;
3443 }
3444 }
3445
3446
print_lock_status(void)3447 static void print_lock_status(void)
3448 {
3449 printk("**********************print_lock_status\n");
3450 printk("cryptocop_completed_jobs_lock %d\n", spin_is_locked(&cryptocop_completed_jobs_lock));
3451 printk("cryptocop_job_queue_lock %d\n", spin_is_locked(&cryptocop_job_queue_lock));
3452 printk("descr_pool_lock %d\n", spin_is_locked(&descr_pool_lock));
3453 printk("cryptocop_sessions_lock %d\n", spin_is_locked(cryptocop_sessions_lock));
3454 printk("running_job_lock %d\n", spin_is_locked(running_job_lock));
3455 printk("cryptocop_process_lock %d\n", spin_is_locked(cryptocop_process_lock));
3456 }
3457 #endif /* LDEBUG */
3458
3459
3460 static const char cryptocop_name[] = "ETRAX FS stream co-processor";
3461
init_stream_coprocessor(void)3462 static int init_stream_coprocessor(void)
3463 {
3464 int err;
3465 int i;
3466 static int initialized = 0;
3467
3468 if (initialized)
3469 return 0;
3470
3471 initialized = 1;
3472
3473 printk("ETRAX FS stream co-processor driver v0.01, (c) 2003 Axis Communications AB\n");
3474
3475 err = register_chrdev(CRYPTOCOP_MAJOR, cryptocop_name, &cryptocop_fops);
3476 if (err < 0) {
3477 printk(KERN_ERR "stream co-processor: could not get major number.\n");
3478 return err;
3479 }
3480
3481 err = init_cryptocop();
3482 if (err) {
3483 (void)unregister_chrdev(CRYPTOCOP_MAJOR, cryptocop_name);
3484 return err;
3485 }
3486 err = cryptocop_job_queue_init();
3487 if (err) {
3488 release_cryptocop();
3489 (void)unregister_chrdev(CRYPTOCOP_MAJOR, cryptocop_name);
3490 return err;
3491 }
3492 /* Init the descriptor pool. */
3493 for (i = 0; i < CRYPTOCOP_DESCRIPTOR_POOL_SIZE - 1; i++) {
3494 descr_pool[i].from_pool = 1;
3495 descr_pool[i].next = &descr_pool[i + 1];
3496 }
3497 descr_pool[i].from_pool = 1;
3498 descr_pool[i].next = NULL;
3499 descr_pool_free_list = &descr_pool[0];
3500 descr_pool_no_free = CRYPTOCOP_DESCRIPTOR_POOL_SIZE;
3501
3502 spin_lock_init(&cryptocop_completed_jobs_lock);
3503 spin_lock_init(&cryptocop_job_queue_lock);
3504 spin_lock_init(&descr_pool_lock);
3505 spin_lock_init(&cryptocop_sessions_lock);
3506 spin_lock_init(&running_job_lock);
3507 spin_lock_init(&cryptocop_process_lock);
3508
3509 cryptocop_sessions = NULL;
3510 next_sid = 1;
3511
3512 cryptocop_running_job = NULL;
3513
3514 printk("stream co-processor: init done.\n");
3515 return 0;
3516 }
3517
exit_stream_coprocessor(void)3518 static void __exit exit_stream_coprocessor(void)
3519 {
3520 release_cryptocop();
3521 cryptocop_job_queue_close();
3522 }
3523
3524 module_init(init_stream_coprocessor);
3525 module_exit(exit_stream_coprocessor);
3526
3527