[rdc] add the prereq-check on lzma
[openwrt.git] / target / linux / generic-2.6 / files / crypto / ocf / ixp4xx / ixp4xx.c
1 /*
2 * An OCF module that uses Intels IXP CryptACC API to do the crypto.
3 * This driver requires the IXP400 Access Library that is available
4 * from Intel in order to operate (or compile).
5 *
6 * Written by David McCullough <david_mccullough@securecomputing.com>
7 * Copyright (C) 2006-2007 David McCullough
8 * Copyright (C) 2004-2005 Intel Corporation.
9 *
10 * LICENSE TERMS
11 *
12 * The free distribution and use of this software in both source and binary
13 * form is allowed (with or without changes) provided that:
14 *
15 * 1. distributions of this source code include the above copyright
16 * notice, this list of conditions and the following disclaimer;
17 *
18 * 2. distributions in binary form include the above copyright
19 * notice, this list of conditions and the following disclaimer
20 * in the documentation and/or other associated materials;
21 *
22 * 3. the copyright holder's name is not used to endorse products
23 * built using this software without specific written permission.
24 *
25 * ALTERNATIVELY, provided that this notice is retained in full, this product
26 * may be distributed under the terms of the GNU General Public License (GPL),
27 * in which case the provisions of the GPL apply INSTEAD OF those given above.
28 *
29 * DISCLAIMER
30 *
31 * This software is provided 'as is' with no explicit or implied warranties
32 * in respect of its properties, including, but not limited to, correctness
33 * and/or fitness for purpose.
34 */
35
36 #ifndef AUTOCONF_INCLUDED
37 #include <linux/config.h>
38 #endif
39 #include <linux/module.h>
40 #include <linux/init.h>
41 #include <linux/list.h>
42 #include <linux/slab.h>
43 #include <linux/sched.h>
44 #include <linux/wait.h>
45 #include <linux/crypto.h>
46 #include <linux/interrupt.h>
47 #include <asm/scatterlist.h>
48
49 #include <IxTypes.h>
50 #include <IxOsBuffMgt.h>
51 #include <IxNpeDl.h>
52 #include <IxCryptoAcc.h>
53 #include <IxQMgr.h>
54 #include <IxOsServices.h>
55 #include <IxOsCacheMMU.h>
56
57 #include <cryptodev.h>
58 #include <uio.h>
59
60 #ifndef IX_MBUF_PRIV
61 #define IX_MBUF_PRIV(x) ((x)->priv)
62 #endif
63
64 struct ixp_data;
65
66 struct ixp_q {
67 struct list_head ixp_q_list;
68 struct ixp_data *ixp_q_data;
69 struct cryptop *ixp_q_crp;
70 struct cryptodesc *ixp_q_ccrd;
71 struct cryptodesc *ixp_q_acrd;
72 IX_MBUF ixp_q_mbuf;
73 UINT8 *ixp_hash_dest; /* Location for hash in client buffer */
74 UINT8 *ixp_hash_src; /* Location of hash in internal buffer */
75 unsigned char ixp_q_iv_data[IX_CRYPTO_ACC_MAX_CIPHER_IV_LENGTH];
76 unsigned char *ixp_q_iv;
77 };
78
79 struct ixp_data {
80 int ixp_registered; /* is the context registered */
81 int ixp_crd_flags; /* detect direction changes */
82
83 int ixp_cipher_alg;
84 int ixp_auth_alg;
85
86 UINT32 ixp_ctx_id;
87 UINT32 ixp_hash_key_id; /* used when hashing */
88 IxCryptoAccCtx ixp_ctx;
89 IX_MBUF ixp_pri_mbuf;
90 IX_MBUF ixp_sec_mbuf;
91
92 struct work_struct ixp_pending_work;
93 struct work_struct ixp_registration_work;
94 struct list_head ixp_q; /* unprocessed requests */
95 };
96
97 #ifdef __ixp46X
98
99 #define MAX_IOP_SIZE 64 /* words */
100 #define MAX_OOP_SIZE 128
101
102 #define MAX_PARAMS 3
103
104 struct ixp_pkq {
105 struct list_head pkq_list;
106 struct cryptkop *pkq_krp;
107
108 IxCryptoAccPkeEauInOperands pkq_op;
109 IxCryptoAccPkeEauOpResult pkq_result;
110
111 UINT32 pkq_ibuf0[MAX_IOP_SIZE];
112 UINT32 pkq_ibuf1[MAX_IOP_SIZE];
113 UINT32 pkq_ibuf2[MAX_IOP_SIZE];
114 UINT32 pkq_obuf[MAX_OOP_SIZE];
115 };
116
117 static LIST_HEAD(ixp_pkq); /* current PK wait list */
118 static struct ixp_pkq *ixp_pk_cur;
119 static spinlock_t ixp_pkq_lock;
120
121 #endif /* __ixp46X */
122
123 static int ixp_blocked = 0;
124
125 static int32_t ixp_id = -1;
126 static struct ixp_data **ixp_sessions = NULL;
127 static u_int32_t ixp_sesnum = 0;
128
129 static int ixp_process(device_t, struct cryptop *, int);
130 static int ixp_newsession(device_t, u_int32_t *, struct cryptoini *);
131 static int ixp_freesession(device_t, u_int64_t);
132 #ifdef __ixp46X
133 static int ixp_kprocess(device_t, struct cryptkop *krp, int hint);
134 #endif
135
136 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
137 static kmem_cache_t *qcache;
138 #else
139 static struct kmem_cache *qcache;
140 #endif
141
142 #define debug ixp_debug
143 static int ixp_debug = 0;
144 module_param(ixp_debug, int, 0644);
145 MODULE_PARM_DESC(ixp_debug, "Enable debug");
146
147 static int ixp_init_crypto = 1;
148 module_param(ixp_init_crypto, int, 0444); /* RO after load/boot */
149 MODULE_PARM_DESC(ixp_init_crypto, "Call ixCryptoAccInit (default is 1)");
150
151 static void ixp_process_pending(void *arg);
152 static void ixp_registration(void *arg);
153 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
154 static void ixp_process_pending_wq(struct work_struct *work);
155 static void ixp_registration_wq(struct work_struct *work);
156 #endif
157
158 /*
159 * dummy device structure
160 */
161
162 static struct {
163 softc_device_decl sc_dev;
164 } ixpdev;
165
166 static device_method_t ixp_methods = {
167 /* crypto device methods */
168 DEVMETHOD(cryptodev_newsession, ixp_newsession),
169 DEVMETHOD(cryptodev_freesession,ixp_freesession),
170 DEVMETHOD(cryptodev_process, ixp_process),
171 #ifdef __ixp46X
172 DEVMETHOD(cryptodev_kprocess, ixp_kprocess),
173 #endif
174 };
175
176 /*
177 * Generate a new software session.
178 */
179 static int
180 ixp_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
181 {
182 struct ixp_data *ixp;
183 u_int32_t i;
184 #define AUTH_LEN(cri, def) \
185 (cri->cri_mlen ? cri->cri_mlen : (def))
186
187 dprintk("%s():alg %d\n", __FUNCTION__,cri->cri_alg);
188 if (sid == NULL || cri == NULL) {
189 dprintk("%s,%d - EINVAL\n", __FILE__, __LINE__);
190 return EINVAL;
191 }
192
193 if (ixp_sessions) {
194 for (i = 1; i < ixp_sesnum; i++)
195 if (ixp_sessions[i] == NULL)
196 break;
197 } else
198 i = 1; /* NB: to silence compiler warning */
199
200 if (ixp_sessions == NULL || i == ixp_sesnum) {
201 struct ixp_data **ixpd;
202
203 if (ixp_sessions == NULL) {
204 i = 1; /* We leave ixp_sessions[0] empty */
205 ixp_sesnum = CRYPTO_SW_SESSIONS;
206 } else
207 ixp_sesnum *= 2;
208
209 ixpd = kmalloc(ixp_sesnum * sizeof(struct ixp_data *), SLAB_ATOMIC);
210 if (ixpd == NULL) {
211 /* Reset session number */
212 if (ixp_sesnum == CRYPTO_SW_SESSIONS)
213 ixp_sesnum = 0;
214 else
215 ixp_sesnum /= 2;
216 dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
217 return ENOBUFS;
218 }
219 memset(ixpd, 0, ixp_sesnum * sizeof(struct ixp_data *));
220
221 /* Copy existing sessions */
222 if (ixp_sessions) {
223 memcpy(ixpd, ixp_sessions,
224 (ixp_sesnum / 2) * sizeof(struct ixp_data *));
225 kfree(ixp_sessions);
226 }
227
228 ixp_sessions = ixpd;
229 }
230
231 ixp_sessions[i] = (struct ixp_data *) kmalloc(sizeof(struct ixp_data),
232 SLAB_ATOMIC);
233 if (ixp_sessions[i] == NULL) {
234 ixp_freesession(NULL, i);
235 dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
236 return ENOBUFS;
237 }
238
239 *sid = i;
240
241 ixp = ixp_sessions[i];
242 memset(ixp, 0, sizeof(*ixp));
243
244 ixp->ixp_cipher_alg = -1;
245 ixp->ixp_auth_alg = -1;
246 ixp->ixp_ctx_id = -1;
247 INIT_LIST_HEAD(&ixp->ixp_q);
248
249 ixp->ixp_ctx.useDifferentSrcAndDestMbufs = 0;
250
251 while (cri) {
252 switch (cri->cri_alg) {
253 case CRYPTO_DES_CBC:
254 ixp->ixp_cipher_alg = cri->cri_alg;
255 ixp->ixp_ctx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_DES;
256 ixp->ixp_ctx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC;
257 ixp->ixp_ctx.cipherCtx.cipherKeyLen = (cri->cri_klen + 7) / 8;
258 ixp->ixp_ctx.cipherCtx.cipherBlockLen = IX_CRYPTO_ACC_DES_BLOCK_64;
259 ixp->ixp_ctx.cipherCtx.cipherInitialVectorLen =
260 IX_CRYPTO_ACC_DES_IV_64;
261 memcpy(ixp->ixp_ctx.cipherCtx.key.cipherKey,
262 cri->cri_key, (cri->cri_klen + 7) / 8);
263 break;
264
265 case CRYPTO_3DES_CBC:
266 ixp->ixp_cipher_alg = cri->cri_alg;
267 ixp->ixp_ctx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_3DES;
268 ixp->ixp_ctx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC;
269 ixp->ixp_ctx.cipherCtx.cipherKeyLen = (cri->cri_klen + 7) / 8;
270 ixp->ixp_ctx.cipherCtx.cipherBlockLen = IX_CRYPTO_ACC_DES_BLOCK_64;
271 ixp->ixp_ctx.cipherCtx.cipherInitialVectorLen =
272 IX_CRYPTO_ACC_DES_IV_64;
273 memcpy(ixp->ixp_ctx.cipherCtx.key.cipherKey,
274 cri->cri_key, (cri->cri_klen + 7) / 8);
275 break;
276
277 case CRYPTO_RIJNDAEL128_CBC:
278 ixp->ixp_cipher_alg = cri->cri_alg;
279 ixp->ixp_ctx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_AES;
280 ixp->ixp_ctx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC;
281 ixp->ixp_ctx.cipherCtx.cipherKeyLen = (cri->cri_klen + 7) / 8;
282 ixp->ixp_ctx.cipherCtx.cipherBlockLen = 16;
283 ixp->ixp_ctx.cipherCtx.cipherInitialVectorLen = 16;
284 memcpy(ixp->ixp_ctx.cipherCtx.key.cipherKey,
285 cri->cri_key, (cri->cri_klen + 7) / 8);
286 break;
287
288 case CRYPTO_MD5:
289 case CRYPTO_MD5_HMAC:
290 ixp->ixp_auth_alg = cri->cri_alg;
291 ixp->ixp_ctx.authCtx.authAlgo = IX_CRYPTO_ACC_AUTH_MD5;
292 ixp->ixp_ctx.authCtx.authDigestLen = AUTH_LEN(cri, MD5_HASH_LEN);
293 ixp->ixp_ctx.authCtx.aadLen = 0;
294 /* Only MD5_HMAC needs a key */
295 if (cri->cri_alg == CRYPTO_MD5_HMAC) {
296 ixp->ixp_ctx.authCtx.authKeyLen = (cri->cri_klen + 7) / 8;
297 if (ixp->ixp_ctx.authCtx.authKeyLen >
298 sizeof(ixp->ixp_ctx.authCtx.key.authKey)) {
299 printk(
300 "ixp4xx: Invalid key length for MD5_HMAC - %d bits\n",
301 cri->cri_klen);
302 ixp_freesession(NULL, i);
303 return EINVAL;
304 }
305 memcpy(ixp->ixp_ctx.authCtx.key.authKey,
306 cri->cri_key, (cri->cri_klen + 7) / 8);
307 }
308 break;
309
310 case CRYPTO_SHA1:
311 case CRYPTO_SHA1_HMAC:
312 ixp->ixp_auth_alg = cri->cri_alg;
313 ixp->ixp_ctx.authCtx.authAlgo = IX_CRYPTO_ACC_AUTH_SHA1;
314 ixp->ixp_ctx.authCtx.authDigestLen = AUTH_LEN(cri, SHA1_HASH_LEN);
315 ixp->ixp_ctx.authCtx.aadLen = 0;
316 /* Only SHA1_HMAC needs a key */
317 if (cri->cri_alg == CRYPTO_SHA1_HMAC) {
318 ixp->ixp_ctx.authCtx.authKeyLen = (cri->cri_klen + 7) / 8;
319 if (ixp->ixp_ctx.authCtx.authKeyLen >
320 sizeof(ixp->ixp_ctx.authCtx.key.authKey)) {
321 printk(
322 "ixp4xx: Invalid key length for SHA1_HMAC - %d bits\n",
323 cri->cri_klen);
324 ixp_freesession(NULL, i);
325 return EINVAL;
326 }
327 memcpy(ixp->ixp_ctx.authCtx.key.authKey,
328 cri->cri_key, (cri->cri_klen + 7) / 8);
329 }
330 break;
331
332 default:
333 printk("ixp: unknown algo 0x%x\n", cri->cri_alg);
334 ixp_freesession(NULL, i);
335 return EINVAL;
336 }
337 cri = cri->cri_next;
338 }
339
340 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
341 INIT_WORK(&ixp->ixp_pending_work, ixp_process_pending_wq);
342 INIT_WORK(&ixp->ixp_registration_work, ixp_registration_wq);
343 #else
344 INIT_WORK(&ixp->ixp_pending_work, ixp_process_pending, ixp);
345 INIT_WORK(&ixp->ixp_registration_work, ixp_registration, ixp);
346 #endif
347
348 return 0;
349 }
350
351
352 /*
353 * Free a session.
354 */
355 static int
356 ixp_freesession(device_t dev, u_int64_t tid)
357 {
358 u_int32_t sid = CRYPTO_SESID2LID(tid);
359
360 dprintk("%s()\n", __FUNCTION__);
361 if (sid > ixp_sesnum || ixp_sessions == NULL ||
362 ixp_sessions[sid] == NULL) {
363 dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
364 return EINVAL;
365 }
366
367 /* Silently accept and return */
368 if (sid == 0)
369 return 0;
370
371 if (ixp_sessions[sid]) {
372 if (ixp_sessions[sid]->ixp_ctx_id != -1) {
373 ixCryptoAccCtxUnregister(ixp_sessions[sid]->ixp_ctx_id);
374 ixp_sessions[sid]->ixp_ctx_id = -1;
375 }
376
377 flush_scheduled_work();
378
379 kfree(ixp_sessions[sid]);
380 }
381 ixp_sessions[sid] = NULL;
382 if (ixp_blocked) {
383 ixp_blocked = 0;
384 crypto_unblock(ixp_id, CRYPTO_SYMQ);
385 }
386 return 0;
387 }
388
389
390 /*
391 * callback for when hash processing is complete
392 */
393
394 static void
395 ixp_hash_perform_cb(
396 UINT32 hash_key_id,
397 IX_MBUF *bufp,
398 IxCryptoAccStatus status)
399 {
400 struct ixp_q *q;
401
402 dprintk("%s(%u, %p, 0x%x)\n", __FUNCTION__, hash_key_id, bufp, status);
403
404 if (bufp == NULL) {
405 printk("ixp: NULL buf in %s\n", __FUNCTION__);
406 return;
407 }
408
409 q = IX_MBUF_PRIV(bufp);
410 if (q == NULL) {
411 printk("ixp: NULL priv in %s\n", __FUNCTION__);
412 return;
413 }
414
415 if (status == IX_CRYPTO_ACC_STATUS_SUCCESS) {
416 /* On success, need to copy hash back into original client buffer */
417 memcpy(q->ixp_hash_dest, q->ixp_hash_src,
418 (q->ixp_q_data->ixp_auth_alg == CRYPTO_SHA1) ?
419 SHA1_HASH_LEN : MD5_HASH_LEN);
420 }
421 else {
422 printk("ixp: hash perform failed status=%d\n", status);
423 q->ixp_q_crp->crp_etype = EINVAL;
424 }
425
426 /* Free internal buffer used for hashing */
427 kfree(IX_MBUF_MDATA(&q->ixp_q_mbuf));
428
429 crypto_done(q->ixp_q_crp);
430 kmem_cache_free(qcache, q);
431 }
432
433 /*
434 * setup a request and perform it
435 */
436 static void
437 ixp_q_process(struct ixp_q *q)
438 {
439 IxCryptoAccStatus status;
440 struct ixp_data *ixp = q->ixp_q_data;
441 int auth_off = 0;
442 int auth_len = 0;
443 int crypt_off = 0;
444 int crypt_len = 0;
445 int icv_off = 0;
446 char *crypt_func;
447
448 dprintk("%s(%p)\n", __FUNCTION__, q);
449
450 if (q->ixp_q_ccrd) {
451 if (q->ixp_q_ccrd->crd_flags & CRD_F_IV_EXPLICIT) {
452 q->ixp_q_iv = q->ixp_q_ccrd->crd_iv;
453 } else {
454 q->ixp_q_iv = q->ixp_q_iv_data;
455 crypto_copydata(q->ixp_q_crp->crp_flags, q->ixp_q_crp->crp_buf,
456 q->ixp_q_ccrd->crd_inject,
457 ixp->ixp_ctx.cipherCtx.cipherInitialVectorLen,
458 (caddr_t) q->ixp_q_iv);
459 }
460
461 if (q->ixp_q_acrd) {
462 auth_off = q->ixp_q_acrd->crd_skip;
463 auth_len = q->ixp_q_acrd->crd_len;
464 icv_off = q->ixp_q_acrd->crd_inject;
465 }
466
467 crypt_off = q->ixp_q_ccrd->crd_skip;
468 crypt_len = q->ixp_q_ccrd->crd_len;
469 } else { /* if (q->ixp_q_acrd) */
470 auth_off = q->ixp_q_acrd->crd_skip;
471 auth_len = q->ixp_q_acrd->crd_len;
472 icv_off = q->ixp_q_acrd->crd_inject;
473 }
474
475 if (q->ixp_q_crp->crp_flags & CRYPTO_F_SKBUF) {
476 struct sk_buff *skb = (struct sk_buff *) q->ixp_q_crp->crp_buf;
477 if (skb_shinfo(skb)->nr_frags) {
478 /*
479 * DAVIDM fix this limitation one day by using
480 * a buffer pool and chaining, it is not currently
481 * needed for current user/kernel space acceleration
482 */
483 printk("ixp: Cannot handle fragmented skb's yet !\n");
484 q->ixp_q_crp->crp_etype = ENOENT;
485 goto done;
486 }
487 IX_MBUF_MLEN(&q->ixp_q_mbuf) =
488 IX_MBUF_PKT_LEN(&q->ixp_q_mbuf) = skb->len;
489 IX_MBUF_MDATA(&q->ixp_q_mbuf) = skb->data;
490 } else if (q->ixp_q_crp->crp_flags & CRYPTO_F_IOV) {
491 struct uio *uiop = (struct uio *) q->ixp_q_crp->crp_buf;
492 if (uiop->uio_iovcnt != 1) {
493 /*
494 * DAVIDM fix this limitation one day by using
495 * a buffer pool and chaining, it is not currently
496 * needed for current user/kernel space acceleration
497 */
498 printk("ixp: Cannot handle more than 1 iovec yet !\n");
499 q->ixp_q_crp->crp_etype = ENOENT;
500 goto done;
501 }
502 IX_MBUF_MLEN(&q->ixp_q_mbuf) =
503 IX_MBUF_PKT_LEN(&q->ixp_q_mbuf) = uiop->uio_iov[0].iov_len;
504 IX_MBUF_MDATA(&q->ixp_q_mbuf) = uiop->uio_iov[0].iov_base;
505 } else /* contig buffer */ {
506 IX_MBUF_MLEN(&q->ixp_q_mbuf) =
507 IX_MBUF_PKT_LEN(&q->ixp_q_mbuf) = q->ixp_q_crp->crp_ilen;
508 IX_MBUF_MDATA(&q->ixp_q_mbuf) = q->ixp_q_crp->crp_buf;
509 }
510
511 IX_MBUF_PRIV(&q->ixp_q_mbuf) = q;
512
513 if (ixp->ixp_auth_alg == CRYPTO_SHA1 || ixp->ixp_auth_alg == CRYPTO_MD5) {
514 /*
515 * For SHA1 and MD5 hash, need to create an internal buffer that is big
516 * enough to hold the original data + the appropriate padding for the
517 * hash algorithm.
518 */
519 UINT8 *tbuf = NULL;
520
521 IX_MBUF_MLEN(&q->ixp_q_mbuf) = IX_MBUF_PKT_LEN(&q->ixp_q_mbuf) =
522 ((IX_MBUF_MLEN(&q->ixp_q_mbuf) * 8) + 72 + 511) / 8;
523 tbuf = kmalloc(IX_MBUF_MLEN(&q->ixp_q_mbuf), SLAB_ATOMIC);
524
525 if (IX_MBUF_MDATA(&q->ixp_q_mbuf) == NULL) {
526 printk("ixp: kmalloc(%u, SLAB_ATOMIC) failed\n",
527 IX_MBUF_MLEN(&q->ixp_q_mbuf));
528 q->ixp_q_crp->crp_etype = ENOMEM;
529 goto done;
530 }
531 memcpy(tbuf, &(IX_MBUF_MDATA(&q->ixp_q_mbuf))[auth_off], auth_len);
532
533 /* Set location in client buffer to copy hash into */
534 q->ixp_hash_dest =
535 &(IX_MBUF_MDATA(&q->ixp_q_mbuf))[auth_off + auth_len];
536
537 IX_MBUF_MDATA(&q->ixp_q_mbuf) = tbuf;
538
539 /* Set location in internal buffer for where hash starts */
540 q->ixp_hash_src = &(IX_MBUF_MDATA(&q->ixp_q_mbuf))[auth_len];
541
542 crypt_func = "ixCryptoAccHashPerform";
543 status = ixCryptoAccHashPerform(ixp->ixp_ctx.authCtx.authAlgo,
544 &q->ixp_q_mbuf, ixp_hash_perform_cb, 0, auth_len, auth_len,
545 &ixp->ixp_hash_key_id);
546 }
547 else {
548 crypt_func = "ixCryptoAccAuthCryptPerform";
549 status = ixCryptoAccAuthCryptPerform(ixp->ixp_ctx_id, &q->ixp_q_mbuf,
550 NULL, auth_off, auth_len, crypt_off, crypt_len, icv_off,
551 q->ixp_q_iv);
552 }
553
554 if (IX_CRYPTO_ACC_STATUS_SUCCESS == status)
555 return;
556
557 if (IX_CRYPTO_ACC_STATUS_QUEUE_FULL == status) {
558 q->ixp_q_crp->crp_etype = ENOMEM;
559 goto done;
560 }
561
562 printk("ixp: %s failed %u\n", crypt_func, status);
563 q->ixp_q_crp->crp_etype = EINVAL;
564
565 done:
566 crypto_done(q->ixp_q_crp);
567 kmem_cache_free(qcache, q);
568 }
569
570
571 /*
572 * because we cannot process the Q from the Register callback
573 * we do it here on a task Q.
574 */
575
576 static void
577 ixp_process_pending(void *arg)
578 {
579 struct ixp_data *ixp = arg;
580 struct ixp_q *q = NULL;
581
582 dprintk("%s(%p)\n", __FUNCTION__, arg);
583
584 if (!ixp)
585 return;
586
587 while (!list_empty(&ixp->ixp_q)) {
588 q = list_entry(ixp->ixp_q.next, struct ixp_q, ixp_q_list);
589 list_del(&q->ixp_q_list);
590 ixp_q_process(q);
591 }
592 }
593
594 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
595 static void
596 ixp_process_pending_wq(struct work_struct *work)
597 {
598 struct ixp_data *ixp = container_of(work, struct ixp_data,
599 ixp_pending_work);
600 ixp_process_pending(ixp);
601 }
602 #endif
603
604 /*
605 * callback for when context registration is complete
606 */
607
608 static void
609 ixp_register_cb(UINT32 ctx_id, IX_MBUF *bufp, IxCryptoAccStatus status)
610 {
611 int i;
612 struct ixp_data *ixp;
613 struct ixp_q *q;
614
615 dprintk("%s(%d, %p, %d)\n", __FUNCTION__, ctx_id, bufp, status);
616
617 /*
618 * free any buffer passed in to this routine
619 */
620 if (bufp) {
621 IX_MBUF_MLEN(bufp) = IX_MBUF_PKT_LEN(bufp) = 0;
622 kfree(IX_MBUF_MDATA(bufp));
623 IX_MBUF_MDATA(bufp) = NULL;
624 }
625
626 for (i = 0; i < ixp_sesnum; i++) {
627 ixp = ixp_sessions[i];
628 if (ixp && ixp->ixp_ctx_id == ctx_id)
629 break;
630 }
631 if (i >= ixp_sesnum) {
632 printk("ixp: invalid context id %d\n", ctx_id);
633 return;
634 }
635
636 if (IX_CRYPTO_ACC_STATUS_WAIT == status) {
637 /* this is normal to free the first of two buffers */
638 dprintk("ixp: register not finished yet.\n");
639 return;
640 }
641
642 if (IX_CRYPTO_ACC_STATUS_SUCCESS != status) {
643 printk("ixp: register failed 0x%x\n", status);
644 while (!list_empty(&ixp->ixp_q)) {
645 q = list_entry(ixp->ixp_q.next, struct ixp_q, ixp_q_list);
646 list_del(&q->ixp_q_list);
647 q->ixp_q_crp->crp_etype = EINVAL;
648 crypto_done(q->ixp_q_crp);
649 kmem_cache_free(qcache, q);
650 }
651 return;
652 }
653
654 /*
655 * we are now registered, we cannot start processing the Q here
656 * or we get strange errors with AES (DES/3DES seem to be ok).
657 */
658 ixp->ixp_registered = 1;
659 schedule_work(&ixp->ixp_pending_work);
660 }
661
662
663 /*
664 * callback for when data processing is complete
665 */
666
667 static void
668 ixp_perform_cb(
669 UINT32 ctx_id,
670 IX_MBUF *sbufp,
671 IX_MBUF *dbufp,
672 IxCryptoAccStatus status)
673 {
674 struct ixp_q *q;
675
676 dprintk("%s(%d, %p, %p, 0x%x)\n", __FUNCTION__, ctx_id, sbufp,
677 dbufp, status);
678
679 if (sbufp == NULL) {
680 printk("ixp: NULL sbuf in ixp_perform_cb\n");
681 return;
682 }
683
684 q = IX_MBUF_PRIV(sbufp);
685 if (q == NULL) {
686 printk("ixp: NULL priv in ixp_perform_cb\n");
687 return;
688 }
689
690 if (status != IX_CRYPTO_ACC_STATUS_SUCCESS) {
691 printk("ixp: perform failed status=%d\n", status);
692 q->ixp_q_crp->crp_etype = EINVAL;
693 }
694
695 crypto_done(q->ixp_q_crp);
696 kmem_cache_free(qcache, q);
697 }
698
699
700 /*
701 * registration is not callable at IRQ time, so we defer
702 * to a task queue, this routines completes the registration for us
703 * when the task queue runs
704 *
705 * Unfortunately this means we cannot tell OCF that the driver is blocked,
706 * we do that on the next request.
707 */
708
709 static void
710 ixp_registration(void *arg)
711 {
712 struct ixp_data *ixp = arg;
713 struct ixp_q *q = NULL;
714 IX_MBUF *pri = NULL, *sec = NULL;
715 int status = IX_CRYPTO_ACC_STATUS_SUCCESS;
716
717 if (!ixp) {
718 printk("ixp: ixp_registration with no arg\n");
719 return;
720 }
721
722 if (ixp->ixp_ctx_id != -1) {
723 ixCryptoAccCtxUnregister(ixp->ixp_ctx_id);
724 ixp->ixp_ctx_id = -1;
725 }
726
727 if (list_empty(&ixp->ixp_q)) {
728 printk("ixp: ixp_registration with no Q\n");
729 return;
730 }
731
732 /*
733 * setup the primary and secondary buffers
734 */
735 q = list_entry(ixp->ixp_q.next, struct ixp_q, ixp_q_list);
736 if (q->ixp_q_acrd) {
737 pri = &ixp->ixp_pri_mbuf;
738 sec = &ixp->ixp_sec_mbuf;
739 IX_MBUF_MLEN(pri) = IX_MBUF_PKT_LEN(pri) = 128;
740 IX_MBUF_MDATA(pri) = (unsigned char *) kmalloc(128, SLAB_ATOMIC);
741 IX_MBUF_MLEN(sec) = IX_MBUF_PKT_LEN(sec) = 128;
742 IX_MBUF_MDATA(sec) = (unsigned char *) kmalloc(128, SLAB_ATOMIC);
743 }
744
745 /* Only need to register if a crypt op or HMAC op */
746 if (!(ixp->ixp_auth_alg == CRYPTO_SHA1 ||
747 ixp->ixp_auth_alg == CRYPTO_MD5)) {
748 status = ixCryptoAccCtxRegister(
749 &ixp->ixp_ctx,
750 pri, sec,
751 ixp_register_cb,
752 ixp_perform_cb,
753 &ixp->ixp_ctx_id);
754 }
755 else {
756 /* Otherwise we start processing pending q */
757 schedule_work(&ixp->ixp_pending_work);
758 }
759
760 if (IX_CRYPTO_ACC_STATUS_SUCCESS == status)
761 return;
762
763 if (IX_CRYPTO_ACC_STATUS_EXCEED_MAX_TUNNELS == status) {
764 printk("ixp: ixCryptoAccCtxRegister failed (out of tunnels)\n");
765 ixp_blocked = 1;
766 /* perhaps we should return EGAIN on queued ops ? */
767 return;
768 }
769
770 printk("ixp: ixCryptoAccCtxRegister failed %d\n", status);
771 ixp->ixp_ctx_id = -1;
772
773 /*
774 * everything waiting is toasted
775 */
776 while (!list_empty(&ixp->ixp_q)) {
777 q = list_entry(ixp->ixp_q.next, struct ixp_q, ixp_q_list);
778 list_del(&q->ixp_q_list);
779 q->ixp_q_crp->crp_etype = ENOENT;
780 crypto_done(q->ixp_q_crp);
781 kmem_cache_free(qcache, q);
782 }
783 }
784
785 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
786 static void
787 ixp_registration_wq(struct work_struct *work)
788 {
789 struct ixp_data *ixp = container_of(work, struct ixp_data,
790 ixp_registration_work);
791 ixp_registration(ixp);
792 }
793 #endif
794
795 /*
796 * Process a request.
797 */
798 static int
799 ixp_process(device_t dev, struct cryptop *crp, int hint)
800 {
801 struct ixp_data *ixp;
802 unsigned int lid;
803 struct ixp_q *q = NULL;
804 int status;
805
806 dprintk("%s()\n", __FUNCTION__);
807
808 /* Sanity check */
809 if (crp == NULL) {
810 dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
811 return EINVAL;
812 }
813
814 crp->crp_etype = 0;
815
816 if (ixp_blocked)
817 return ERESTART;
818
819 if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
820 dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
821 crp->crp_etype = EINVAL;
822 goto done;
823 }
824
825 /*
826 * find the session we are using
827 */
828
829 lid = crp->crp_sid & 0xffffffff;
830 if (lid >= ixp_sesnum || lid == 0 || ixp_sessions == NULL ||
831 ixp_sessions[lid] == NULL) {
832 crp->crp_etype = ENOENT;
833 dprintk("%s,%d: ENOENT\n", __FILE__, __LINE__);
834 goto done;
835 }
836 ixp = ixp_sessions[lid];
837
838 /*
839 * setup a new request ready for queuing
840 */
841 q = kmem_cache_alloc(qcache, SLAB_ATOMIC);
842 if (q == NULL) {
843 dprintk("%s,%d: ENOMEM\n", __FILE__, __LINE__);
844 crp->crp_etype = ENOMEM;
845 goto done;
846 }
847 /*
848 * save some cycles by only zeroing the important bits
849 */
850 memset(&q->ixp_q_mbuf, 0, sizeof(q->ixp_q_mbuf));
851 q->ixp_q_ccrd = NULL;
852 q->ixp_q_acrd = NULL;
853 q->ixp_q_crp = crp;
854 q->ixp_q_data = ixp;
855
856 /*
857 * point the cipher and auth descriptors appropriately
858 * check that we have something to do
859 */
860 if (crp->crp_desc->crd_alg == ixp->ixp_cipher_alg)
861 q->ixp_q_ccrd = crp->crp_desc;
862 else if (crp->crp_desc->crd_alg == ixp->ixp_auth_alg)
863 q->ixp_q_acrd = crp->crp_desc;
864 else {
865 crp->crp_etype = ENOENT;
866 dprintk("%s,%d: bad desc match: ENOENT\n", __FILE__, __LINE__);
867 goto done;
868 }
869 if (crp->crp_desc->crd_next) {
870 if (crp->crp_desc->crd_next->crd_alg == ixp->ixp_cipher_alg)
871 q->ixp_q_ccrd = crp->crp_desc->crd_next;
872 else if (crp->crp_desc->crd_next->crd_alg == ixp->ixp_auth_alg)
873 q->ixp_q_acrd = crp->crp_desc->crd_next;
874 else {
875 crp->crp_etype = ENOENT;
876 dprintk("%s,%d: bad desc match: ENOENT\n", __FILE__, __LINE__);
877 goto done;
878 }
879 }
880
881 /*
882 * If there is a direction change for this context then we mark it as
883 * unregistered and re-register is for the new direction. This is not
884 * a very expensive operation and currently only tends to happen when
885 * user-space application are doing benchmarks
886 *
887 * DM - we should be checking for pending requests before unregistering.
888 */
889 if (q->ixp_q_ccrd && ixp->ixp_registered &&
890 ixp->ixp_crd_flags != (q->ixp_q_ccrd->crd_flags & CRD_F_ENCRYPT)) {
891 dprintk("%s - detected direction change on session\n", __FUNCTION__);
892 ixp->ixp_registered = 0;
893 }
894
895 /*
896 * if we are registered, call straight into the perform code
897 */
898 if (ixp->ixp_registered) {
899 ixp_q_process(q);
900 return 0;
901 }
902
903 /*
904 * the only part of the context not set in newsession is the direction
905 * dependent parts
906 */
907 if (q->ixp_q_ccrd) {
908 ixp->ixp_crd_flags = (q->ixp_q_ccrd->crd_flags & CRD_F_ENCRYPT);
909 if (q->ixp_q_ccrd->crd_flags & CRD_F_ENCRYPT) {
910 ixp->ixp_ctx.operation = q->ixp_q_acrd ?
911 IX_CRYPTO_ACC_OP_ENCRYPT_AUTH : IX_CRYPTO_ACC_OP_ENCRYPT;
912 } else {
913 ixp->ixp_ctx.operation = q->ixp_q_acrd ?
914 IX_CRYPTO_ACC_OP_AUTH_DECRYPT : IX_CRYPTO_ACC_OP_DECRYPT;
915 }
916 } else {
917 /* q->ixp_q_acrd must be set if we are here */
918 ixp->ixp_ctx.operation = IX_CRYPTO_ACC_OP_AUTH_CALC;
919 }
920
921 status = list_empty(&ixp->ixp_q);
922 list_add_tail(&q->ixp_q_list, &ixp->ixp_q);
923 if (status)
924 schedule_work(&ixp->ixp_registration_work);
925 return 0;
926
927 done:
928 if (q)
929 kmem_cache_free(qcache, q);
930 crypto_done(crp);
931 return 0;
932 }
933
934
935 #ifdef __ixp46X
936 /*
937 * key processing support for the ixp465
938 */
939
940
941 /*
942 * copy a BN (LE) into a buffer (BE) an fill out the op appropriately
943 * assume zeroed and only copy bits that are significant
944 */
945
946 static int
947 ixp_copy_ibuf(struct crparam *p, IxCryptoAccPkeEauOperand *op, UINT32 *buf)
948 {
949 unsigned char *src = (unsigned char *) p->crp_p;
950 unsigned char *dst;
951 int len, bits = p->crp_nbits;
952
953 dprintk("%s()\n", __FUNCTION__);
954
955 if (bits > MAX_IOP_SIZE * sizeof(UINT32) * 8) {
956 dprintk("%s - ibuf too big (%d > %d)\n", __FUNCTION__,
957 bits, MAX_IOP_SIZE * sizeof(UINT32) * 8);
958 return -1;
959 }
960
961 len = (bits + 31) / 32; /* the number UINT32's needed */
962
963 dst = (unsigned char *) &buf[len];
964 dst--;
965
966 while (bits > 0) {
967 *dst-- = *src++;
968 bits -= 8;
969 }
970
971 #if 0 /* no need to zero remaining bits as it is done during request alloc */
972 while (dst > (unsigned char *) buf)
973 *dst-- = '\0';
974 #endif
975
976 op->pData = buf;
977 op->dataLen = len;
978 return 0;
979 }
980
981 /*
982 * copy out the result, be as forgiving as we can about small output buffers
983 */
984
985 static int
986 ixp_copy_obuf(struct crparam *p, IxCryptoAccPkeEauOpResult *op, UINT32 *buf)
987 {
988 unsigned char *dst = (unsigned char *) p->crp_p;
989 unsigned char *src = (unsigned char *) buf;
990 int len, z, bits = p->crp_nbits;
991
992 dprintk("%s()\n", __FUNCTION__);
993
994 len = op->dataLen * sizeof(UINT32);
995
996 /* skip leading zeroes to be small buffer friendly */
997 z = 0;
998 while (z < len && src[z] == '\0')
999 z++;
1000
1001 src += len;
1002 src--;
1003 len -= z;
1004
1005 while (len > 0 && bits > 0) {
1006 *dst++ = *src--;
1007 len--;
1008 bits -= 8;
1009 }
1010
1011 while (bits > 0) {
1012 *dst++ = '\0';
1013 bits -= 8;
1014 }
1015
1016 if (len > 0) {
1017 dprintk("%s - obuf is %d (z=%d, ob=%d) bytes too small\n",
1018 __FUNCTION__, len, z, p->crp_nbits / 8);
1019 return -1;
1020 }
1021
1022 return 0;
1023 }
1024
1025
1026 /*
1027 * the parameter offsets for exp_mod
1028 */
1029
1030 #define IXP_PARAM_BASE 0
1031 #define IXP_PARAM_EXP 1
1032 #define IXP_PARAM_MOD 2
1033 #define IXP_PARAM_RES 3
1034
1035 /*
1036 * key processing complete callback, is also used to start processing
1037 * by passing a NULL for pResult
1038 */
1039
1040 static void
1041 ixp_kperform_cb(
1042 IxCryptoAccPkeEauOperation operation,
1043 IxCryptoAccPkeEauOpResult *pResult,
1044 BOOL carryOrBorrow,
1045 IxCryptoAccStatus status)
1046 {
1047 struct ixp_pkq *q, *tmp;
1048 unsigned long flags;
1049
1050 dprintk("%s(0x%x, %p, %d, 0x%x)\n", __FUNCTION__, operation, pResult,
1051 carryOrBorrow, status);
1052
1053 /* handle a completed request */
1054 if (pResult) {
1055 if (ixp_pk_cur && &ixp_pk_cur->pkq_result == pResult) {
1056 q = ixp_pk_cur;
1057 if (status != IX_CRYPTO_ACC_STATUS_SUCCESS) {
1058 dprintk("%s() - op failed 0x%x\n", __FUNCTION__, status);
1059 q->pkq_krp->krp_status = ERANGE; /* could do better */
1060 } else {
1061 /* copy out the result */
1062 if (ixp_copy_obuf(&q->pkq_krp->krp_param[IXP_PARAM_RES],
1063 &q->pkq_result, q->pkq_obuf))
1064 q->pkq_krp->krp_status = ERANGE;
1065 }
1066 crypto_kdone(q->pkq_krp);
1067 kfree(q);
1068 ixp_pk_cur = NULL;
1069 } else
1070 printk("%s - callback with invalid result pointer\n", __FUNCTION__);
1071 }
1072
1073 spin_lock_irqsave(&ixp_pkq_lock, flags);
1074 if (ixp_pk_cur || list_empty(&ixp_pkq)) {
1075 spin_unlock_irqrestore(&ixp_pkq_lock, flags);
1076 return;
1077 }
1078
1079 list_for_each_entry_safe(q, tmp, &ixp_pkq, pkq_list) {
1080
1081 list_del(&q->pkq_list);
1082 ixp_pk_cur = q;
1083
1084 spin_unlock_irqrestore(&ixp_pkq_lock, flags);
1085
1086 status = ixCryptoAccPkeEauPerform(
1087 IX_CRYPTO_ACC_OP_EAU_MOD_EXP,
1088 &q->pkq_op,
1089 ixp_kperform_cb,
1090 &q->pkq_result);
1091
1092 if (status == IX_CRYPTO_ACC_STATUS_SUCCESS) {
1093 dprintk("%s() - ixCryptoAccPkeEauPerform SUCCESS\n", __FUNCTION__);
1094 return; /* callback will return here for callback */
1095 } else if (status == IX_CRYPTO_ACC_STATUS_RETRY) {
1096 printk("%s() - ixCryptoAccPkeEauPerform RETRY\n", __FUNCTION__);
1097 } else {
1098 printk("%s() - ixCryptoAccPkeEauPerform failed %d\n",
1099 __FUNCTION__, status);
1100 }
1101 q->pkq_krp->krp_status = ERANGE; /* could do better */
1102 crypto_kdone(q->pkq_krp);
1103 kfree(q);
1104 spin_lock_irqsave(&ixp_pkq_lock, flags);
1105 }
1106 spin_unlock_irqrestore(&ixp_pkq_lock, flags);
1107 }
1108
1109
1110 static int
1111 ixp_kprocess(device_t dev, struct cryptkop *krp, int hint)
1112 {
1113 struct ixp_pkq *q;
1114 int rc = 0;
1115 unsigned long flags;
1116
1117 dprintk("%s l1=%d l2=%d l3=%d l4=%d\n", __FUNCTION__,
1118 krp->krp_param[IXP_PARAM_BASE].crp_nbits,
1119 krp->krp_param[IXP_PARAM_EXP].crp_nbits,
1120 krp->krp_param[IXP_PARAM_MOD].crp_nbits,
1121 krp->krp_param[IXP_PARAM_RES].crp_nbits);
1122
1123
1124 if (krp->krp_op != CRK_MOD_EXP) {
1125 krp->krp_status = EOPNOTSUPP;
1126 goto err;
1127 }
1128
1129 q = (struct ixp_pkq *) kmalloc(sizeof(*q), GFP_KERNEL);
1130 if (q == NULL) {
1131 krp->krp_status = ENOMEM;
1132 goto err;
1133 }
1134
1135 /*
1136 * The PKE engine does not appear to zero the output buffer
1137 * appropriately, so we need to do it all here.
1138 */
1139 memset(q, 0, sizeof(*q));
1140
1141 q->pkq_krp = krp;
1142 INIT_LIST_HEAD(&q->pkq_list);
1143
1144 if (ixp_copy_ibuf(&krp->krp_param[IXP_PARAM_BASE], &q->pkq_op.modExpOpr.M,
1145 q->pkq_ibuf0))
1146 rc = 1;
1147 if (!rc && ixp_copy_ibuf(&krp->krp_param[IXP_PARAM_EXP],
1148 &q->pkq_op.modExpOpr.e, q->pkq_ibuf1))
1149 rc = 2;
1150 if (!rc && ixp_copy_ibuf(&krp->krp_param[IXP_PARAM_MOD],
1151 &q->pkq_op.modExpOpr.N, q->pkq_ibuf2))
1152 rc = 3;
1153
1154 if (rc) {
1155 kfree(q);
1156 krp->krp_status = ERANGE;
1157 goto err;
1158 }
1159
1160 q->pkq_result.pData = q->pkq_obuf;
1161 q->pkq_result.dataLen =
1162 (krp->krp_param[IXP_PARAM_RES].crp_nbits + 31) / 32;
1163
1164 spin_lock_irqsave(&ixp_pkq_lock, flags);
1165 list_add_tail(&q->pkq_list, &ixp_pkq);
1166 spin_unlock_irqrestore(&ixp_pkq_lock, flags);
1167
1168 if (!ixp_pk_cur)
1169 ixp_kperform_cb(0, NULL, 0, 0);
1170 return (0);
1171
1172 err:
1173 crypto_kdone(krp);
1174 return (0);
1175 }
1176
1177
1178
1179 #ifdef CONFIG_OCF_RANDOMHARVEST
1180 /*
1181 * We run the random number generator output through SHA so that it
1182 * is FIPS compliant.
1183 */
1184
1185 static volatile int sha_done = 0;
1186 static unsigned char sha_digest[20];
1187
1188 static void
1189 ixp_hash_cb(UINT8 *digest, IxCryptoAccStatus status)
1190 {
1191 dprintk("%s(%p, %d)\n", __FUNCTION__, digest, status);
1192 if (sha_digest != digest)
1193 printk("digest error\n");
1194 if (IX_CRYPTO_ACC_STATUS_SUCCESS == status)
1195 sha_done = 1;
1196 else
1197 sha_done = -status;
1198 }
1199
1200 static int
1201 ixp_read_random(void *arg, u_int32_t *buf, int maxwords)
1202 {
1203 IxCryptoAccStatus status;
1204 int i, n, rc;
1205
1206 dprintk("%s(%p, %d)\n", __FUNCTION__, buf, maxwords);
1207 memset(buf, 0, maxwords * sizeof(*buf));
1208 status = ixCryptoAccPkePseudoRandomNumberGet(maxwords, buf);
1209 if (status != IX_CRYPTO_ACC_STATUS_SUCCESS) {
1210 dprintk("%s: ixCryptoAccPkePseudoRandomNumberGet failed %d\n",
1211 __FUNCTION__, status);
1212 return 0;
1213 }
1214
1215 /*
1216 * run the random data through SHA to make it look more random
1217 */
1218
1219 n = sizeof(sha_digest); /* process digest bytes at a time */
1220
1221 rc = 0;
1222 for (i = 0; i < maxwords; i += n / sizeof(*buf)) {
1223 if ((maxwords - i) * sizeof(*buf) < n)
1224 n = (maxwords - i) * sizeof(*buf);
1225 sha_done = 0;
1226 status = ixCryptoAccPkeHashPerform(IX_CRYPTO_ACC_AUTH_SHA1,
1227 (UINT8 *) &buf[i], n, ixp_hash_cb, sha_digest);
1228 if (status != IX_CRYPTO_ACC_STATUS_SUCCESS) {
1229 dprintk("ixCryptoAccPkeHashPerform failed %d\n", status);
1230 return -EIO;
1231 }
1232 while (!sha_done)
1233 schedule();
1234 if (sha_done < 0) {
1235 dprintk("ixCryptoAccPkeHashPerform failed CB %d\n", -sha_done);
1236 return 0;
1237 }
1238 memcpy(&buf[i], sha_digest, n);
1239 rc += n / sizeof(*buf);;
1240 }
1241
1242 return rc;
1243 }
1244 #endif /* CONFIG_OCF_RANDOMHARVEST */
1245
1246 #endif /* __ixp46X */
1247
1248
1249
1250 /*
1251 * our driver startup and shutdown routines
1252 */
1253
1254 static int
1255 ixp_init(void)
1256 {
1257 dprintk("%s(%p)\n", __FUNCTION__, ixp_init);
1258
1259 if (ixp_init_crypto && ixCryptoAccInit() != IX_CRYPTO_ACC_STATUS_SUCCESS)
1260 printk("ixCryptoAccInit failed, assuming already initialised!\n");
1261
1262 qcache = kmem_cache_create("ixp4xx_q", sizeof(struct ixp_q), 0,
1263 SLAB_HWCACHE_ALIGN, NULL
1264 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
1265 , NULL
1266 #endif
1267 );
1268 if (!qcache) {
1269 printk("failed to create Qcache\n");
1270 return -ENOENT;
1271 }
1272
1273 memset(&ixpdev, 0, sizeof(ixpdev));
1274 softc_device_init(&ixpdev, "ixp4xx", 0, ixp_methods);
1275
1276 ixp_id = crypto_get_driverid(softc_get_device(&ixpdev),
1277 CRYPTOCAP_F_HARDWARE);
1278 if (ixp_id < 0)
1279 panic("IXP/OCF crypto device cannot initialize!");
1280
1281 #define REGISTER(alg) \
1282 crypto_register(ixp_id,alg,0,0)
1283
1284 REGISTER(CRYPTO_DES_CBC);
1285 REGISTER(CRYPTO_3DES_CBC);
1286 REGISTER(CRYPTO_RIJNDAEL128_CBC);
1287 #ifdef CONFIG_OCF_IXP4XX_SHA1_MD5
1288 REGISTER(CRYPTO_MD5);
1289 REGISTER(CRYPTO_SHA1);
1290 #endif
1291 REGISTER(CRYPTO_MD5_HMAC);
1292 REGISTER(CRYPTO_SHA1_HMAC);
1293 #undef REGISTER
1294
1295 #ifdef __ixp46X
1296 spin_lock_init(&ixp_pkq_lock);
1297 /*
1298 * we do not enable the go fast options here as they can potentially
1299 * allow timing based attacks
1300 *
1301 * http://www.openssl.org/news/secadv_20030219.txt
1302 */
1303 ixCryptoAccPkeEauExpConfig(0, 0);
1304 crypto_kregister(ixp_id, CRK_MOD_EXP, 0);
1305 #ifdef CONFIG_OCF_RANDOMHARVEST
1306 crypto_rregister(ixp_id, ixp_read_random, NULL);
1307 #endif
1308 #endif
1309
1310 return 0;
1311 }
1312
1313 static void
1314 ixp_exit(void)
1315 {
1316 dprintk("%s()\n", __FUNCTION__);
1317 crypto_unregister_all(ixp_id);
1318 ixp_id = -1;
1319 kmem_cache_destroy(qcache);
1320 qcache = NULL;
1321 }
1322
1323 module_init(ixp_init);
1324 module_exit(ixp_exit);
1325
1326 MODULE_LICENSE("Dual BSD/GPL");
1327 MODULE_AUTHOR("David McCullough <dmccullough@cyberguard.com>");
1328 MODULE_DESCRIPTION("ixp (OCF module for IXP4xx crypto)");
This page took 0.127821 seconds and 5 git commands to generate.