~ubuntu-branches/ubuntu/karmic/linux-mvl-dove/karmic-proposed

« back to all changes in this revision

Viewing changes to crypto/ocf/ixp4xx/ixp4xx.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Bader
  • Date: 2010-03-10 22:24:12 UTC
  • mto: (15.1.2 karmic-security)
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: james.westby@ubuntu.com-20100310222412-k86m3r53jw0je7x1
Tags: upstream-2.6.31
ImportĀ upstreamĀ versionĀ 2.6.31

Show diffs side-by-side

added added

removed removed

Lines of Context:
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)");