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

Archive Download this file



interactive