]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/mips/cavium/cryptocteon/cavium_crypto.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / mips / cavium / cryptocteon / cavium_crypto.c
1 /*
2  * vim:sw=4 ts=8
3  */
4 /*
5  * Copyright (c) 2009 David McCullough <david.mccullough@securecomputing.com>
6  *
7  * Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
8  * reserved.
9  * 
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  * must display the following acknowledgement:
19  * This product includes software developed by Cavium Networks
20  * 4. Cavium Networks' name may not be used to endorse or promote products
21  * derived from this software without specific prior written permission.
22  * 
23  * This Software, including technical data, may be subject to U.S. export
24  * control laws, including the U.S. Export Administration Act and its
25  * associated regulations, and may be subject to export or import regulations
26  * in other countries. You warrant that You will comply strictly in all
27  * respects with all such regulations and acknowledge that you have the
28  * responsibility to obtain licenses to export, re-export or import the
29  * Software.
30  * 
31  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" AND
32  * WITH ALL FAULTS AND CAVIUM MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES,
33  * EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE
34  * SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
35  * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
36  * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
37  * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
38  * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
39  * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
40  * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
41 */
42 /****************************************************************************/
43
44 #include <sys/cdefs.h>
45 __FBSDID("$FreeBSD$");
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/kernel.h>
50 #include <sys/module.h>
51 #include <sys/malloc.h>
52 #include <sys/uio.h>
53
54 #include <opencrypto/cryptodev.h>
55
56 #include <contrib/octeon-sdk/cvmx.h>
57
58 #include <mips/cavium/cryptocteon/cryptocteonvar.h>
59
60 /****************************************************************************/
61
62 #define IOV_INIT(iov, ptr, idx, len)                                    \
63         do {                                                            \
64             (idx) = 0;                                                  \
65             (ptr) = (iov)[(idx)].iov_base;                              \
66             (len) = (iov)[(idx)].iov_len;                               \
67         } while (0)
68
69 /*
70  * XXX
71  * It would be better if this were an IOV_READ/IOV_WRITE macro instead so
72  * that we could detect overflow before it happens rather than right after,
73  * which is especially bad since there is usually no IOV_CONSUME after the
74  * final read or write.
75  */
76 #define IOV_CONSUME(iov, ptr, idx, len)                                 \
77         do {                                                            \
78             if ((len) > sizeof *(ptr)) {                                \
79                 (len) -= sizeof *(ptr);                                 \
80                 (ptr)++;                                                \
81             } else {                                                    \
82                 if ((len) != sizeof *(ptr))                             \
83                         panic("%s: went past end of iovec.", __func__); \
84                 (idx)++;                                                \
85                 (ptr) = (iov)[(idx)].iov_base;                          \
86                 (len) = (iov)[(idx)].iov_len;                           \
87             }                                                           \
88         } while (0)
89
90 static inline unsigned long octeon_crypto_enable(void)
91 {
92     register_t s;
93     
94     s = intr_disable();
95     mips_wr_status(mips_rd_status() | MIPS_SR_COP_2_BIT);
96
97     return (s);
98 }
99
100 static inline void octeon_crypto_disable(register_t s)
101 {
102     mips_wr_status(mips_rd_status() & ~MIPS_SR_COP_2_BIT);
103     intr_restore(s);
104 }
105
106 #define ESP_HEADER_LENGTH     8
107 #define DES_CBC_IV_LENGTH     8
108 #define AES_CBC_IV_LENGTH     16
109 #define ESP_HMAC_LEN          12
110
111 #define ESP_HEADER_LENGTH 8
112 #define DES_CBC_IV_LENGTH 8
113
114 /****************************************************************************/
115
116 #define CVM_LOAD_SHA_UNIT(dat, next)  { \
117    if (next == 0) {                     \
118       next = 1;                         \
119       CVMX_MT_HSH_DAT (dat, 0);         \
120    } else if (next == 1) {              \
121       next = 2;                         \
122       CVMX_MT_HSH_DAT (dat, 1);         \
123    } else if (next == 2) {              \
124       next = 3;                    \
125       CVMX_MT_HSH_DAT (dat, 2);         \
126    } else if (next == 3) {              \
127       next = 4;                         \
128       CVMX_MT_HSH_DAT (dat, 3);         \
129    } else if (next == 4) {              \
130       next = 5;                           \
131       CVMX_MT_HSH_DAT (dat, 4);         \
132    } else if (next == 5) {              \
133       next = 6;                         \
134       CVMX_MT_HSH_DAT (dat, 5);         \
135    } else if (next == 6) {              \
136       next = 7;                         \
137       CVMX_MT_HSH_DAT (dat, 6);         \
138    } else {                             \
139      CVMX_MT_HSH_STARTSHA (dat);        \
140      next = 0;                          \
141    }                                    \
142 }
143
144 #define CVM_LOAD2_SHA_UNIT(dat1, dat2, next)  { \
145    if (next == 0) {                      \
146       CVMX_MT_HSH_DAT (dat1, 0);         \
147       CVMX_MT_HSH_DAT (dat2, 1);         \
148       next = 2;                          \
149    } else if (next == 1) {               \
150       CVMX_MT_HSH_DAT (dat1, 1);         \
151       CVMX_MT_HSH_DAT (dat2, 2);         \
152       next = 3;                          \
153    } else if (next == 2) {               \
154       CVMX_MT_HSH_DAT (dat1, 2);         \
155       CVMX_MT_HSH_DAT (dat2, 3);         \
156       next = 4;                          \
157    } else if (next == 3) {               \
158       CVMX_MT_HSH_DAT (dat1, 3);         \
159       CVMX_MT_HSH_DAT (dat2, 4);         \
160       next = 5;                          \
161    } else if (next == 4) {               \
162       CVMX_MT_HSH_DAT (dat1, 4);         \
163       CVMX_MT_HSH_DAT (dat2, 5);         \
164       next = 6;                          \
165    } else if (next == 5) {               \
166       CVMX_MT_HSH_DAT (dat1, 5);         \
167       CVMX_MT_HSH_DAT (dat2, 6);         \
168       next = 7;                          \
169    } else if (next == 6) {               \
170       CVMX_MT_HSH_DAT (dat1, 6);         \
171       CVMX_MT_HSH_STARTSHA (dat2);       \
172       next = 0;                          \
173    } else {                              \
174      CVMX_MT_HSH_STARTSHA (dat1);        \
175      CVMX_MT_HSH_DAT (dat2, 0);          \
176      next = 1;                           \
177    }                                     \
178 }
179
180 /****************************************************************************/
181
182 #define CVM_LOAD_MD5_UNIT(dat, next)  { \
183    if (next == 0) {                     \
184       next = 1;                         \
185       CVMX_MT_HSH_DAT (dat, 0);         \
186    } else if (next == 1) {              \
187       next = 2;                         \
188       CVMX_MT_HSH_DAT (dat, 1);         \
189    } else if (next == 2) {              \
190       next = 3;                    \
191       CVMX_MT_HSH_DAT (dat, 2);         \
192    } else if (next == 3) {              \
193       next = 4;                         \
194       CVMX_MT_HSH_DAT (dat, 3);         \
195    } else if (next == 4) {              \
196       next = 5;                           \
197       CVMX_MT_HSH_DAT (dat, 4);         \
198    } else if (next == 5) {              \
199       next = 6;                         \
200       CVMX_MT_HSH_DAT (dat, 5);         \
201    } else if (next == 6) {              \
202       next = 7;                         \
203       CVMX_MT_HSH_DAT (dat, 6);         \
204    } else {                             \
205      CVMX_MT_HSH_STARTMD5 (dat);        \
206      next = 0;                          \
207    }                                    \
208 }
209
210 #define CVM_LOAD2_MD5_UNIT(dat1, dat2, next)  { \
211    if (next == 0) {                      \
212       CVMX_MT_HSH_DAT (dat1, 0);         \
213       CVMX_MT_HSH_DAT (dat2, 1);         \
214       next = 2;                          \
215    } else if (next == 1) {               \
216       CVMX_MT_HSH_DAT (dat1, 1);         \
217       CVMX_MT_HSH_DAT (dat2, 2);         \
218       next = 3;                          \
219    } else if (next == 2) {               \
220       CVMX_MT_HSH_DAT (dat1, 2);         \
221       CVMX_MT_HSH_DAT (dat2, 3);         \
222       next = 4;                          \
223    } else if (next == 3) {               \
224       CVMX_MT_HSH_DAT (dat1, 3);         \
225       CVMX_MT_HSH_DAT (dat2, 4);         \
226       next = 5;                          \
227    } else if (next == 4) {               \
228       CVMX_MT_HSH_DAT (dat1, 4);         \
229       CVMX_MT_HSH_DAT (dat2, 5);         \
230       next = 6;                          \
231    } else if (next == 5) {               \
232       CVMX_MT_HSH_DAT (dat1, 5);         \
233       CVMX_MT_HSH_DAT (dat2, 6);         \
234       next = 7;                          \
235    } else if (next == 6) {               \
236       CVMX_MT_HSH_DAT (dat1, 6);         \
237       CVMX_MT_HSH_STARTMD5 (dat2);       \
238       next = 0;                          \
239    } else {                              \
240      CVMX_MT_HSH_STARTMD5 (dat1);        \
241      CVMX_MT_HSH_DAT (dat2, 0);          \
242      next = 1;                           \
243    }                                     \
244 }
245
246 /****************************************************************************/
247
248 void
249 octo_calc_hash(uint8_t auth, unsigned char *key, uint64_t *inner, uint64_t *outer)
250 {
251     uint8_t hash_key[64];
252     uint64_t *key1;
253     register uint64_t xor1 = 0x3636363636363636ULL;
254     register uint64_t xor2 = 0x5c5c5c5c5c5c5c5cULL;
255     register_t s;
256
257     dprintf("%s()\n", __func__);
258
259     memset(hash_key, 0, sizeof(hash_key));
260     memcpy(hash_key, (uint8_t *) key, (auth ? 20 : 16));
261     key1 = (uint64_t *) hash_key;
262     s = octeon_crypto_enable();
263     if (auth) {
264        CVMX_MT_HSH_IV(0x67452301EFCDAB89ULL, 0);
265        CVMX_MT_HSH_IV(0x98BADCFE10325476ULL, 1);
266        CVMX_MT_HSH_IV(0xC3D2E1F000000000ULL, 2);
267     } else {
268        CVMX_MT_HSH_IV(0x0123456789ABCDEFULL, 0);
269        CVMX_MT_HSH_IV(0xFEDCBA9876543210ULL, 1);
270     }
271
272     CVMX_MT_HSH_DAT((*key1 ^ xor1), 0);
273     key1++;
274     CVMX_MT_HSH_DAT((*key1 ^ xor1), 1);
275     key1++;
276     CVMX_MT_HSH_DAT((*key1 ^ xor1), 2);
277     key1++;
278     CVMX_MT_HSH_DAT((*key1 ^ xor1), 3);
279     key1++;
280     CVMX_MT_HSH_DAT((*key1 ^ xor1), 4);
281     key1++;
282     CVMX_MT_HSH_DAT((*key1 ^ xor1), 5);
283     key1++;
284     CVMX_MT_HSH_DAT((*key1 ^ xor1), 6);
285     key1++;
286     if (auth)
287                 CVMX_MT_HSH_STARTSHA((*key1 ^ xor1));
288     else
289                 CVMX_MT_HSH_STARTMD5((*key1 ^ xor1));
290
291     CVMX_MF_HSH_IV(inner[0], 0);
292     CVMX_MF_HSH_IV(inner[1], 1);
293     if (auth) {
294                 inner[2] = 0;
295                 CVMX_MF_HSH_IV(((uint64_t *) inner)[2], 2);
296     }
297
298     memset(hash_key, 0, sizeof(hash_key));
299     memcpy(hash_key, (uint8_t *) key, (auth ? 20 : 16));
300     key1 = (uint64_t *) hash_key;
301     if (auth) {
302       CVMX_MT_HSH_IV(0x67452301EFCDAB89ULL, 0);
303       CVMX_MT_HSH_IV(0x98BADCFE10325476ULL, 1);
304       CVMX_MT_HSH_IV(0xC3D2E1F000000000ULL, 2);
305     } else {
306       CVMX_MT_HSH_IV(0x0123456789ABCDEFULL, 0);
307       CVMX_MT_HSH_IV(0xFEDCBA9876543210ULL, 1);
308     }
309
310     CVMX_MT_HSH_DAT((*key1 ^ xor2), 0);
311     key1++;
312     CVMX_MT_HSH_DAT((*key1 ^ xor2), 1);
313     key1++;
314     CVMX_MT_HSH_DAT((*key1 ^ xor2), 2);
315     key1++;
316     CVMX_MT_HSH_DAT((*key1 ^ xor2), 3);
317     key1++;
318     CVMX_MT_HSH_DAT((*key1 ^ xor2), 4);
319     key1++;
320     CVMX_MT_HSH_DAT((*key1 ^ xor2), 5);
321     key1++;
322     CVMX_MT_HSH_DAT((*key1 ^ xor2), 6);
323     key1++;
324     if (auth)
325        CVMX_MT_HSH_STARTSHA((*key1 ^ xor2));
326     else 
327        CVMX_MT_HSH_STARTMD5((*key1 ^ xor2));
328
329     CVMX_MF_HSH_IV(outer[0], 0);
330     CVMX_MF_HSH_IV(outer[1], 1);
331     if (auth) {
332       outer[2] = 0;
333       CVMX_MF_HSH_IV(outer[2], 2);
334     }
335     octeon_crypto_disable(s);
336     return;
337 }
338
339 /****************************************************************************/
340 /* DES functions */
341
342 int
343 octo_des_cbc_encrypt(
344     struct octo_sess *od,
345     struct iovec *iov, size_t iovcnt, size_t iovlen,
346     int auth_off, int auth_len,
347     int crypt_off, int crypt_len,
348     int icv_off, uint8_t *ivp)
349 {
350     uint64_t *data;
351     int data_i, data_l;
352     register_t s;
353
354     dprintf("%s()\n", __func__);
355
356     if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
357             (crypt_off & 0x7) || (crypt_off + crypt_len > iovlen))) {
358         dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
359                 "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
360                 "icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
361                 auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
362         return -EINVAL;
363     }
364
365     IOV_INIT(iov, data, data_i, data_l);
366
367     CVMX_PREFETCH0(ivp);
368     CVMX_PREFETCH0(od->octo_enckey);
369
370     s = octeon_crypto_enable();
371
372     /* load 3DES Key */
373     CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
374     if (od->octo_encklen == 24) {
375         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
376         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
377     } else if (od->octo_encklen == 8) {
378         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
379         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
380     } else {
381         octeon_crypto_disable(s);
382         dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
383         return -EINVAL;
384     }
385
386     CVMX_MT_3DES_IV(* (uint64_t *) ivp);
387
388     while (crypt_off > 0) {
389         IOV_CONSUME(iov, data, data_i, data_l);
390         crypt_off -= 8;
391     }
392
393     while (crypt_len > 0) {
394         CVMX_MT_3DES_ENC_CBC(*data);
395         CVMX_MF_3DES_RESULT(*data);
396         IOV_CONSUME(iov, data, data_i, data_l);
397         crypt_len -= 8;
398     }
399
400     octeon_crypto_disable(s);
401     return 0;
402 }
403
404
405 int
406 octo_des_cbc_decrypt(
407     struct octo_sess *od,
408     struct iovec *iov, size_t iovcnt, size_t iovlen,
409     int auth_off, int auth_len,
410     int crypt_off, int crypt_len,
411     int icv_off, uint8_t *ivp)
412 {
413     uint64_t *data;
414     int data_i, data_l;
415     register_t s;
416
417     dprintf("%s()\n", __func__);
418
419     if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
420             (crypt_off & 0x7) || (crypt_off + crypt_len > iovlen))) {
421         dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
422                 "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
423                 "icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
424                 auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
425         return -EINVAL;
426     }
427
428     IOV_INIT(iov, data, data_i, data_l);
429
430     CVMX_PREFETCH0(ivp);
431     CVMX_PREFETCH0(od->octo_enckey);
432
433     s = octeon_crypto_enable();
434
435     /* load 3DES Key */
436     CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
437     if (od->octo_encklen == 24) {
438         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
439         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
440     } else if (od->octo_encklen == 8) {
441         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
442         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
443     } else {
444         octeon_crypto_disable(s);
445         dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
446         return -EINVAL;
447     }
448
449     CVMX_MT_3DES_IV(* (uint64_t *) ivp);
450
451     while (crypt_off > 0) {
452         IOV_CONSUME(iov, data, data_i, data_l);
453         crypt_off -= 8;
454     }
455
456     while (crypt_len > 0) {
457         CVMX_MT_3DES_DEC_CBC(*data);
458         CVMX_MF_3DES_RESULT(*data);
459         IOV_CONSUME(iov, data, data_i, data_l);
460         crypt_len -= 8;
461     }
462
463     octeon_crypto_disable(s);
464     return 0;
465 }
466
467 /****************************************************************************/
468 /* AES functions */
469
470 int
471 octo_aes_cbc_encrypt(
472     struct octo_sess *od,
473     struct iovec *iov, size_t iovcnt, size_t iovlen,
474     int auth_off, int auth_len,
475     int crypt_off, int crypt_len,
476     int icv_off, uint8_t *ivp)
477 {
478     uint64_t *data, *pdata;
479     int data_i, data_l;
480     register_t s;
481
482     dprintf("%s()\n", __func__);
483
484     if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
485             (crypt_off & 0x7) || (crypt_off + crypt_len > iovlen))) {
486         dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
487                 "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
488                 "icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
489                 auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
490         return -EINVAL;
491     }
492
493     IOV_INIT(iov, data, data_i, data_l);
494
495     CVMX_PREFETCH0(ivp);
496     CVMX_PREFETCH0(od->octo_enckey);
497
498     s = octeon_crypto_enable();
499
500     /* load AES Key */
501     CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
502     CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
503
504     if (od->octo_encklen == 16) {
505         CVMX_MT_AES_KEY(0x0, 2);
506         CVMX_MT_AES_KEY(0x0, 3);
507     } else if (od->octo_encklen == 24) {
508         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
509         CVMX_MT_AES_KEY(0x0, 3);
510     } else if (od->octo_encklen == 32) {
511         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
512         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
513     } else {
514         octeon_crypto_disable(s);
515         dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
516         return -EINVAL;
517     }
518     CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
519
520     CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
521     CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
522
523     while (crypt_off > 0) {
524         IOV_CONSUME(iov, data, data_i, data_l);
525         crypt_off -= 8;
526     }
527
528     while (crypt_len > 0) {
529         pdata = data;
530         CVMX_MT_AES_ENC_CBC0(*data);
531         IOV_CONSUME(iov, data, data_i, data_l);
532         CVMX_MT_AES_ENC_CBC1(*data);
533         CVMX_MF_AES_RESULT(*pdata, 0);
534         CVMX_MF_AES_RESULT(*data, 1);
535         IOV_CONSUME(iov, data, data_i, data_l);
536         crypt_len -= 16;
537     }
538
539     octeon_crypto_disable(s);
540     return 0;
541 }
542
543
544 int
545 octo_aes_cbc_decrypt(
546     struct octo_sess *od,
547     struct iovec *iov, size_t iovcnt, size_t iovlen,
548     int auth_off, int auth_len,
549     int crypt_off, int crypt_len,
550     int icv_off, uint8_t *ivp)
551 {
552     uint64_t *data, *pdata;
553     int data_i, data_l;
554     register_t s;
555
556     dprintf("%s()\n", __func__);
557
558     if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
559             (crypt_off & 0x7) || (crypt_off + crypt_len > iovlen))) {
560         dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
561                 "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
562                 "icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
563                 auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
564         return -EINVAL;
565     }
566
567     IOV_INIT(iov, data, data_i, data_l);
568
569     CVMX_PREFETCH0(ivp);
570     CVMX_PREFETCH0(od->octo_enckey);
571
572     s = octeon_crypto_enable();
573
574     /* load AES Key */
575     CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
576     CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
577
578     if (od->octo_encklen == 16) {
579         CVMX_MT_AES_KEY(0x0, 2);
580         CVMX_MT_AES_KEY(0x0, 3);
581     } else if (od->octo_encklen == 24) {
582         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
583         CVMX_MT_AES_KEY(0x0, 3);
584     } else if (od->octo_encklen == 32) {
585         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
586         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
587     } else {
588         octeon_crypto_disable(s);
589         dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
590         return -EINVAL;
591     }
592     CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
593
594     CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
595     CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
596
597     while (crypt_off > 0) {
598         IOV_CONSUME(iov, data, data_i, data_l);
599         crypt_off -= 8;
600     }
601
602     while (crypt_len > 0) {
603         pdata = data;
604         CVMX_MT_AES_DEC_CBC0(*data);
605         IOV_CONSUME(iov, data, data_i, data_l);
606         CVMX_MT_AES_DEC_CBC1(*data);
607         CVMX_MF_AES_RESULT(*pdata, 0);
608         CVMX_MF_AES_RESULT(*data, 1);
609         IOV_CONSUME(iov, data, data_i, data_l);
610         crypt_len -= 16;
611     }
612
613     octeon_crypto_disable(s);
614     return 0;
615 }
616
617 /****************************************************************************/
618 /* MD5 */
619
620 int
621 octo_null_md5_encrypt(
622     struct octo_sess *od,
623     struct iovec *iov, size_t iovcnt, size_t iovlen,
624     int auth_off, int auth_len,
625     int crypt_off, int crypt_len,
626     int icv_off, uint8_t *ivp)
627 {
628     register int next = 0;
629     uint64_t *data;
630     uint64_t tmp1, tmp2;
631     int data_i, data_l, alen = auth_len;
632     register_t s;
633
634     dprintf("%s()\n", __func__);
635
636     if (__predict_false(od == NULL || iov==NULL || iovlen==0 ||
637             (auth_off & 0x7) || (auth_off + auth_len > iovlen))) {
638         dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
639                 "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
640                 "icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
641                 auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
642         return -EINVAL;
643     }
644
645     IOV_INIT(iov, data, data_i, data_l);
646
647     s = octeon_crypto_enable();
648
649     /* Load MD5 IV */
650     CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
651     CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
652
653     while (auth_off > 0) {
654         IOV_CONSUME(iov, data, data_i, data_l);
655         auth_off -= 8;
656     }
657
658     while (auth_len > 0) {
659         CVM_LOAD_MD5_UNIT(*data, next);
660         auth_len -= 8;
661         IOV_CONSUME(iov, data, data_i, data_l);
662     }
663
664     /* finish the hash */
665     CVMX_PREFETCH0(od->octo_hmouter);
666 #if 0
667     if (__predict_false(inplen)) {
668         uint64_t tmp = 0;
669         uint8_t *p = (uint8_t *) & tmp;
670         p[inplen] = 0x80;
671         do {
672             inplen--;
673             p[inplen] = ((uint8_t *) data)[inplen];
674         } while (inplen);
675         CVM_LOAD_MD5_UNIT(tmp, next);
676     } else {
677         CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
678     }
679 #else
680     CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
681 #endif
682
683     /* Finish Inner hash */
684     while (next != 7) {
685         CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
686     }
687     CVMX_ES64(tmp1, ((alen + 64) << 3));
688     CVM_LOAD_MD5_UNIT(tmp1, next);
689
690     /* Get the inner hash of HMAC */
691     CVMX_MF_HSH_IV(tmp1, 0);
692     CVMX_MF_HSH_IV(tmp2, 1);
693
694     /* Initialize hash unit */
695     CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
696     CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
697
698     CVMX_MT_HSH_DAT(tmp1, 0);
699     CVMX_MT_HSH_DAT(tmp2, 1);
700     CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
701     CVMX_MT_HSH_DATZ(3);
702     CVMX_MT_HSH_DATZ(4);
703     CVMX_MT_HSH_DATZ(5);
704     CVMX_MT_HSH_DATZ(6);
705     CVMX_ES64(tmp1, ((64 + 16) << 3));
706     CVMX_MT_HSH_STARTMD5(tmp1);
707
708     /* save the HMAC */
709     IOV_INIT(iov, data, data_i, data_l);
710     while (icv_off > 0) {
711         IOV_CONSUME(iov, data, data_i, data_l);
712         icv_off -= 8;
713     }
714     CVMX_MF_HSH_IV(*data, 0);
715     IOV_CONSUME(iov, data, data_i, data_l);
716     CVMX_MF_HSH_IV(tmp1, 1);
717     *(uint32_t *)data = (uint32_t) (tmp1 >> 32);
718
719     octeon_crypto_disable(s);
720     return 0;
721 }
722
723 /****************************************************************************/
724 /* SHA1 */
725
726 int
727 octo_null_sha1_encrypt(
728     struct octo_sess *od,
729     struct iovec *iov, size_t iovcnt, size_t iovlen,
730     int auth_off, int auth_len,
731     int crypt_off, int crypt_len,
732     int icv_off, uint8_t *ivp)
733 {
734     register int next = 0;
735     uint64_t *data;
736     uint64_t tmp1, tmp2, tmp3;
737     int data_i, data_l, alen = auth_len;
738     register_t s;
739
740     dprintf("%s()\n", __func__);
741
742     if (__predict_false(od == NULL || iov==NULL || iovlen==0 ||
743             (auth_off & 0x7) || (auth_off + auth_len > iovlen))) {
744         dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
745                 "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
746                 "icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
747                 auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
748         return -EINVAL;
749     }
750
751     IOV_INIT(iov, data, data_i, data_l);
752
753     s = octeon_crypto_enable();
754
755     /* Load SHA1 IV */
756     CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
757     CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
758     CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
759
760     while (auth_off > 0) {
761         IOV_CONSUME(iov, data, data_i, data_l);
762         auth_off -= 8;
763     }
764
765     while (auth_len > 0) {
766         CVM_LOAD_SHA_UNIT(*data, next);
767         auth_len -= 8;
768         IOV_CONSUME(iov, data, data_i, data_l);
769     }
770
771     /* finish the hash */
772     CVMX_PREFETCH0(od->octo_hmouter);
773 #if 0
774     if (__predict_false(inplen)) {
775         uint64_t tmp = 0;
776         uint8_t *p = (uint8_t *) & tmp;
777         p[inplen] = 0x80;
778         do {
779             inplen--;
780             p[inplen] = ((uint8_t *) data)[inplen];
781         } while (inplen);
782         CVM_LOAD_MD5_UNIT(tmp, next);
783     } else {
784         CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
785     }
786 #else
787     CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
788 #endif
789
790     /* Finish Inner hash */
791     while (next != 7) {
792         CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
793     }
794         CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
795
796     /* Get the inner hash of HMAC */
797     CVMX_MF_HSH_IV(tmp1, 0);
798     CVMX_MF_HSH_IV(tmp2, 1);
799     tmp3 = 0;
800     CVMX_MF_HSH_IV(tmp3, 2);
801
802     /* Initialize hash unit */
803     CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
804     CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
805     CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
806
807     CVMX_MT_HSH_DAT(tmp1, 0);
808     CVMX_MT_HSH_DAT(tmp2, 1);
809     tmp3 |= 0x0000000080000000;
810     CVMX_MT_HSH_DAT(tmp3, 2);
811     CVMX_MT_HSH_DATZ(3);
812     CVMX_MT_HSH_DATZ(4);
813     CVMX_MT_HSH_DATZ(5);
814     CVMX_MT_HSH_DATZ(6);
815     CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
816
817     /* save the HMAC */
818     IOV_INIT(iov, data, data_i, data_l);
819     while (icv_off > 0) {
820         IOV_CONSUME(iov, data, data_i, data_l);
821         icv_off -= 8;
822     }
823     CVMX_MF_HSH_IV(*data, 0);
824     IOV_CONSUME(iov, data, data_i, data_l);
825     CVMX_MF_HSH_IV(tmp1, 1);
826     *(uint32_t *)data = (uint32_t) (tmp1 >> 32);
827
828     octeon_crypto_disable(s);
829     return 0;
830 }
831
832 /****************************************************************************/
833 /* DES MD5 */
834
835 int
836 octo_des_cbc_md5_encrypt(
837     struct octo_sess *od,
838     struct iovec *iov, size_t iovcnt, size_t iovlen,
839     int auth_off, int auth_len,
840     int crypt_off, int crypt_len,
841     int icv_off, uint8_t *ivp)
842 {
843     register int next = 0;
844     union {
845         uint32_t data32[2];
846         uint64_t data64[1];
847     } mydata;
848     uint64_t *data = &mydata.data64[0];
849     uint32_t *data32;
850     uint64_t tmp1, tmp2;
851     int data_i, data_l, alen = auth_len;
852     register_t s;
853
854     dprintf("%s()\n", __func__);
855
856     if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
857             (crypt_off & 0x3) || (crypt_off + crypt_len > iovlen) ||
858             (crypt_len  & 0x7) ||
859             (auth_len  & 0x7) ||
860             (auth_off & 0x3) || (auth_off + auth_len > iovlen))) {
861         dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
862                 "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
863                 "icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
864                 auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
865         return -EINVAL;
866     }
867
868     IOV_INIT(iov, data32, data_i, data_l);
869
870     CVMX_PREFETCH0(ivp);
871     CVMX_PREFETCH0(od->octo_enckey);
872
873     s = octeon_crypto_enable();
874
875     /* load 3DES Key */
876     CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
877     if (od->octo_encklen == 24) {
878         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
879         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
880     } else if (od->octo_encklen == 8) {
881         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
882         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
883     } else {
884         octeon_crypto_disable(s);
885         dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
886         return -EINVAL;
887     }
888
889     CVMX_MT_3DES_IV(* (uint64_t *) ivp);
890
891     /* Load MD5 IV */
892     CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
893     CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
894
895     while (crypt_off > 0 && auth_off > 0) {
896         IOV_CONSUME(iov, data32, data_i, data_l);
897         crypt_off -= 4;
898         auth_off -= 4;
899     }
900
901     while (crypt_len > 0 || auth_len > 0) {
902         uint32_t *first = data32;
903         mydata.data32[0] = *first;
904         IOV_CONSUME(iov, data32, data_i, data_l);
905         mydata.data32[1] = *data32;
906         if (crypt_off <= 0) {
907             if (crypt_len > 0) {
908                 CVMX_MT_3DES_ENC_CBC(*data);
909                 CVMX_MF_3DES_RESULT(*data);
910                 crypt_len -= 8;
911             }
912         } else
913             crypt_off -= 8;
914         if (auth_off <= 0) {
915             if (auth_len > 0) {
916                 CVM_LOAD_MD5_UNIT(*data, next);
917                 auth_len -= 8;
918             }
919         } else
920             auth_off -= 8;
921         *first = mydata.data32[0];
922         *data32 = mydata.data32[1];
923         IOV_CONSUME(iov, data32, data_i, data_l);
924     }
925
926     /* finish the hash */
927     CVMX_PREFETCH0(od->octo_hmouter);
928 #if 0
929     if (__predict_false(inplen)) {
930         uint64_t tmp = 0;
931         uint8_t *p = (uint8_t *) & tmp;
932         p[inplen] = 0x80;
933         do {
934             inplen--;
935             p[inplen] = ((uint8_t *) data)[inplen];
936         } while (inplen);
937         CVM_LOAD_MD5_UNIT(tmp, next);
938     } else {
939         CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
940     }
941 #else
942     CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
943 #endif
944
945     /* Finish Inner hash */
946     while (next != 7) {
947         CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
948     }
949     CVMX_ES64(tmp1, ((alen + 64) << 3));
950     CVM_LOAD_MD5_UNIT(tmp1, next);
951
952     /* Get the inner hash of HMAC */
953     CVMX_MF_HSH_IV(tmp1, 0);
954     CVMX_MF_HSH_IV(tmp2, 1);
955
956     /* Initialize hash unit */
957     CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
958     CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
959
960     CVMX_MT_HSH_DAT(tmp1, 0);
961     CVMX_MT_HSH_DAT(tmp2, 1);
962     CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
963     CVMX_MT_HSH_DATZ(3);
964     CVMX_MT_HSH_DATZ(4);
965     CVMX_MT_HSH_DATZ(5);
966     CVMX_MT_HSH_DATZ(6);
967     CVMX_ES64(tmp1, ((64 + 16) << 3));
968     CVMX_MT_HSH_STARTMD5(tmp1);
969
970     /* save the HMAC */
971     IOV_INIT(iov, data32, data_i, data_l);
972     while (icv_off > 0) {
973         IOV_CONSUME(iov, data32, data_i, data_l);
974         icv_off -= 4;
975     }
976     CVMX_MF_HSH_IV(tmp1, 0);
977     *data32 = (uint32_t) (tmp1 >> 32);
978     IOV_CONSUME(iov, data32, data_i, data_l);
979     *data32 = (uint32_t) tmp1;
980     IOV_CONSUME(iov, data32, data_i, data_l);
981     CVMX_MF_HSH_IV(tmp1, 1);
982     *data32 = (uint32_t) (tmp1 >> 32);
983
984     octeon_crypto_disable(s);
985     return 0;
986 }
987
988 int
989 octo_des_cbc_md5_decrypt(
990     struct octo_sess *od,
991     struct iovec *iov, size_t iovcnt, size_t iovlen,
992     int auth_off, int auth_len,
993     int crypt_off, int crypt_len,
994     int icv_off, uint8_t *ivp)
995 {
996     register int next = 0;
997     union {
998         uint32_t data32[2];
999         uint64_t data64[1];
1000     } mydata;
1001     uint64_t *data = &mydata.data64[0];
1002     uint32_t *data32;
1003     uint64_t tmp1, tmp2;
1004     int data_i, data_l, alen = auth_len;
1005     register_t s;
1006
1007     dprintf("%s()\n", __func__);
1008
1009     if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
1010             (crypt_off & 0x3) || (crypt_off + crypt_len > iovlen) ||
1011             (crypt_len  & 0x7) ||
1012             (auth_len  & 0x7) ||
1013             (auth_off & 0x3) || (auth_off + auth_len > iovlen))) {
1014         dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
1015                 "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
1016                 "icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
1017                 auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
1018         return -EINVAL;
1019     }
1020
1021     IOV_INIT(iov, data32, data_i, data_l);
1022
1023     CVMX_PREFETCH0(ivp);
1024     CVMX_PREFETCH0(od->octo_enckey);
1025
1026     s = octeon_crypto_enable();
1027
1028     /* load 3DES Key */
1029     CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
1030     if (od->octo_encklen == 24) {
1031         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
1032         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1033     } else if (od->octo_encklen == 8) {
1034         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
1035         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
1036     } else {
1037         octeon_crypto_disable(s);
1038         dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
1039         return -EINVAL;
1040     }
1041
1042     CVMX_MT_3DES_IV(* (uint64_t *) ivp);
1043
1044     /* Load MD5 IV */
1045     CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
1046     CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
1047
1048     while (crypt_off > 0 && auth_off > 0) {
1049         IOV_CONSUME(iov, data32, data_i, data_l);
1050         crypt_off -= 4;
1051         auth_off -= 4;
1052     }
1053
1054     while (crypt_len > 0 || auth_len > 0) {
1055         uint32_t *first = data32;
1056         mydata.data32[0] = *first;
1057         IOV_CONSUME(iov, data32, data_i, data_l);
1058         mydata.data32[1] = *data32;
1059         if (auth_off <= 0) {
1060             if (auth_len > 0) {
1061                 CVM_LOAD_MD5_UNIT(*data, next);
1062                 auth_len -= 8;
1063             }
1064         } else
1065             auth_off -= 8;
1066         if (crypt_off <= 0) {
1067             if (crypt_len > 0) {
1068                 CVMX_MT_3DES_DEC_CBC(*data);
1069                 CVMX_MF_3DES_RESULT(*data);
1070                 crypt_len -= 8;
1071             }
1072         } else
1073             crypt_off -= 8;
1074         *first = mydata.data32[0];
1075         *data32 = mydata.data32[1];
1076         IOV_CONSUME(iov, data32, data_i, data_l);
1077     }
1078
1079     /* finish the hash */
1080     CVMX_PREFETCH0(od->octo_hmouter);
1081 #if 0
1082     if (__predict_false(inplen)) {
1083         uint64_t tmp = 0;
1084         uint8_t *p = (uint8_t *) & tmp;
1085         p[inplen] = 0x80;
1086         do {
1087             inplen--;
1088             p[inplen] = ((uint8_t *) data)[inplen];
1089         } while (inplen);
1090         CVM_LOAD_MD5_UNIT(tmp, next);
1091     } else {
1092         CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
1093     }
1094 #else
1095     CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
1096 #endif
1097
1098     /* Finish Inner hash */
1099     while (next != 7) {
1100         CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
1101     }
1102     CVMX_ES64(tmp1, ((alen + 64) << 3));
1103     CVM_LOAD_MD5_UNIT(tmp1, next);
1104
1105     /* Get the inner hash of HMAC */
1106     CVMX_MF_HSH_IV(tmp1, 0);
1107     CVMX_MF_HSH_IV(tmp2, 1);
1108
1109     /* Initialize hash unit */
1110     CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
1111     CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
1112
1113     CVMX_MT_HSH_DAT(tmp1, 0);
1114     CVMX_MT_HSH_DAT(tmp2, 1);
1115     CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
1116     CVMX_MT_HSH_DATZ(3);
1117     CVMX_MT_HSH_DATZ(4);
1118     CVMX_MT_HSH_DATZ(5);
1119     CVMX_MT_HSH_DATZ(6);
1120     CVMX_ES64(tmp1, ((64 + 16) << 3));
1121     CVMX_MT_HSH_STARTMD5(tmp1);
1122
1123     /* save the HMAC */
1124     IOV_INIT(iov, data32, data_i, data_l);
1125     while (icv_off > 0) {
1126         IOV_CONSUME(iov, data32, data_i, data_l);
1127         icv_off -= 4;
1128     }
1129     CVMX_MF_HSH_IV(tmp1, 0);
1130     *data32 = (uint32_t) (tmp1 >> 32);
1131     IOV_CONSUME(iov, data32, data_i, data_l);
1132     *data32 = (uint32_t) tmp1;
1133     IOV_CONSUME(iov, data32, data_i, data_l);
1134     CVMX_MF_HSH_IV(tmp1, 1);
1135     *data32 = (uint32_t) (tmp1 >> 32);
1136
1137     octeon_crypto_disable(s);
1138     return 0;
1139 }
1140
1141 /****************************************************************************/
1142 /* DES SHA */
1143
1144 int
1145 octo_des_cbc_sha1_encrypt(
1146     struct octo_sess *od,
1147     struct iovec *iov, size_t iovcnt, size_t iovlen,
1148     int auth_off, int auth_len,
1149     int crypt_off, int crypt_len,
1150     int icv_off, uint8_t *ivp)
1151 {
1152     register int next = 0;
1153     union {
1154         uint32_t data32[2];
1155         uint64_t data64[1];
1156     } mydata;
1157     uint64_t *data = &mydata.data64[0];
1158     uint32_t *data32;
1159     uint64_t tmp1, tmp2, tmp3;
1160     int data_i, data_l, alen = auth_len;
1161     register_t s;
1162
1163     dprintf("%s()\n", __func__);
1164
1165     if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
1166             (crypt_off & 0x3) || (crypt_off + crypt_len > iovlen) ||
1167             (crypt_len  & 0x7) ||
1168             (auth_len  & 0x7) ||
1169             (auth_off & 0x3) || (auth_off + auth_len > iovlen))) {
1170         dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
1171                 "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
1172                 "icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
1173                 auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
1174         return -EINVAL;
1175     }
1176
1177     IOV_INIT(iov, data32, data_i, data_l);
1178
1179     CVMX_PREFETCH0(ivp);
1180     CVMX_PREFETCH0(od->octo_enckey);
1181
1182     s = octeon_crypto_enable();
1183
1184     /* load 3DES Key */
1185     CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
1186     if (od->octo_encklen == 24) {
1187         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
1188         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1189     } else if (od->octo_encklen == 8) {
1190         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
1191         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
1192     } else {
1193         octeon_crypto_disable(s);
1194         dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
1195         return -EINVAL;
1196     }
1197
1198     CVMX_MT_3DES_IV(* (uint64_t *) ivp);
1199
1200     /* Load SHA1 IV */
1201     CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
1202     CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
1203     CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
1204
1205     while (crypt_off > 0 && auth_off > 0) {
1206         IOV_CONSUME(iov, data32, data_i, data_l);
1207         crypt_off -= 4;
1208         auth_off -= 4;
1209     }
1210
1211     while (crypt_len > 0 || auth_len > 0) {
1212         uint32_t *first = data32;
1213         mydata.data32[0] = *first;
1214         IOV_CONSUME(iov, data32, data_i, data_l);
1215         mydata.data32[1] = *data32;
1216         if (crypt_off <= 0) {
1217             if (crypt_len > 0) {
1218                 CVMX_MT_3DES_ENC_CBC(*data);
1219                 CVMX_MF_3DES_RESULT(*data);
1220                 crypt_len -= 8;
1221             }
1222         } else
1223             crypt_off -= 8;
1224         if (auth_off <= 0) {
1225             if (auth_len > 0) {
1226                 CVM_LOAD_SHA_UNIT(*data, next);
1227                 auth_len -= 8;
1228             }
1229         } else
1230             auth_off -= 8;
1231         *first = mydata.data32[0];
1232         *data32 = mydata.data32[1];
1233         IOV_CONSUME(iov, data32, data_i, data_l);
1234     }
1235
1236     /* finish the hash */
1237     CVMX_PREFETCH0(od->octo_hmouter);
1238 #if 0
1239     if (__predict_false(inplen)) {
1240         uint64_t tmp = 0;
1241         uint8_t *p = (uint8_t *) & tmp;
1242         p[inplen] = 0x80;
1243         do {
1244             inplen--;
1245             p[inplen] = ((uint8_t *) data)[inplen];
1246         } while (inplen);
1247         CVM_LOAD_SHA_UNIT(tmp, next);
1248     } else {
1249         CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
1250     }
1251 #else
1252     CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
1253 #endif
1254
1255     /* Finish Inner hash */
1256     while (next != 7) {
1257         CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
1258     }
1259         CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
1260
1261     /* Get the inner hash of HMAC */
1262     CVMX_MF_HSH_IV(tmp1, 0);
1263     CVMX_MF_HSH_IV(tmp2, 1);
1264     tmp3 = 0;
1265     CVMX_MF_HSH_IV(tmp3, 2);
1266
1267     /* Initialize hash unit */
1268     CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
1269     CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
1270     CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
1271
1272     CVMX_MT_HSH_DAT(tmp1, 0);
1273     CVMX_MT_HSH_DAT(tmp2, 1);
1274     tmp3 |= 0x0000000080000000;
1275     CVMX_MT_HSH_DAT(tmp3, 2);
1276     CVMX_MT_HSH_DATZ(3);
1277     CVMX_MT_HSH_DATZ(4);
1278     CVMX_MT_HSH_DATZ(5);
1279     CVMX_MT_HSH_DATZ(6);
1280     CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
1281
1282     /* save the HMAC */
1283     IOV_INIT(iov, data32, data_i, data_l);
1284     while (icv_off > 0) {
1285         IOV_CONSUME(iov, data32, data_i, data_l);
1286         icv_off -= 4;
1287     }
1288     CVMX_MF_HSH_IV(tmp1, 0);
1289     *data32 = (uint32_t) (tmp1 >> 32);
1290     IOV_CONSUME(iov, data32, data_i, data_l);
1291     *data32 = (uint32_t) tmp1;
1292     IOV_CONSUME(iov, data32, data_i, data_l);
1293     CVMX_MF_HSH_IV(tmp1, 1);
1294     *data32 = (uint32_t) (tmp1 >> 32);
1295
1296     octeon_crypto_disable(s);
1297     return 0;
1298 }
1299
1300 int
1301 octo_des_cbc_sha1_decrypt(
1302     struct octo_sess *od,
1303     struct iovec *iov, size_t iovcnt, size_t iovlen,
1304     int auth_off, int auth_len,
1305     int crypt_off, int crypt_len,
1306     int icv_off, uint8_t *ivp)
1307 {
1308     register int next = 0;
1309     union {
1310         uint32_t data32[2];
1311         uint64_t data64[1];
1312     } mydata;
1313     uint64_t *data = &mydata.data64[0];
1314     uint32_t *data32;
1315     uint64_t tmp1, tmp2, tmp3;
1316     int data_i, data_l, alen = auth_len;
1317     register_t s;
1318
1319     dprintf("%s()\n", __func__);
1320
1321     if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
1322             (crypt_off & 0x3) || (crypt_off + crypt_len > iovlen) ||
1323             (crypt_len  & 0x7) ||
1324             (auth_len  & 0x7) ||
1325             (auth_off & 0x3) || (auth_off + auth_len > iovlen))) {
1326         dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
1327                 "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
1328                 "icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
1329                 auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
1330         return -EINVAL;
1331     }
1332
1333     IOV_INIT(iov, data32, data_i, data_l);
1334
1335     CVMX_PREFETCH0(ivp);
1336     CVMX_PREFETCH0(od->octo_enckey);
1337
1338     s = octeon_crypto_enable();
1339
1340     /* load 3DES Key */
1341     CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
1342     if (od->octo_encklen == 24) {
1343         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
1344         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1345     } else if (od->octo_encklen == 8) {
1346         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
1347         CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
1348     } else {
1349         octeon_crypto_disable(s);
1350         dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
1351         return -EINVAL;
1352     }
1353
1354     CVMX_MT_3DES_IV(* (uint64_t *) ivp);
1355
1356     /* Load SHA1 IV */
1357     CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
1358     CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
1359     CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
1360
1361     while (crypt_off > 0 && auth_off > 0) {
1362         IOV_CONSUME(iov, data32, data_i, data_l);
1363         crypt_off -= 4;
1364         auth_off -= 4;
1365     }
1366
1367     while (crypt_len > 0 || auth_len > 0) {
1368         uint32_t *first = data32;
1369         mydata.data32[0] = *first;
1370         IOV_CONSUME(iov, data32, data_i, data_l);
1371         mydata.data32[1] = *data32;
1372         if (auth_off <= 0) {
1373             if (auth_len > 0) {
1374                 CVM_LOAD_SHA_UNIT(*data, next);
1375                 auth_len -= 8;
1376             }
1377         } else
1378             auth_off -= 8;
1379         if (crypt_off <= 0) {
1380             if (crypt_len > 0) {
1381                 CVMX_MT_3DES_DEC_CBC(*data);
1382                 CVMX_MF_3DES_RESULT(*data);
1383                 crypt_len -= 8;
1384             }
1385         } else
1386             crypt_off -= 8;
1387         *first = mydata.data32[0];
1388         *data32 = mydata.data32[1];
1389         IOV_CONSUME(iov, data32, data_i, data_l);
1390     }
1391
1392     /* finish the hash */
1393     CVMX_PREFETCH0(od->octo_hmouter);
1394 #if 0
1395     if (__predict_false(inplen)) {
1396         uint64_t tmp = 0;
1397         uint8_t *p = (uint8_t *) & tmp;
1398         p[inplen] = 0x80;
1399         do {
1400             inplen--;
1401             p[inplen] = ((uint8_t *) data)[inplen];
1402         } while (inplen);
1403         CVM_LOAD_SHA_UNIT(tmp, next);
1404     } else {
1405         CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
1406     }
1407 #else
1408     CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
1409 #endif
1410
1411     /* Finish Inner hash */
1412     while (next != 7) {
1413         CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
1414     }
1415         CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
1416
1417     /* Get the inner hash of HMAC */
1418     CVMX_MF_HSH_IV(tmp1, 0);
1419     CVMX_MF_HSH_IV(tmp2, 1);
1420     tmp3 = 0;
1421     CVMX_MF_HSH_IV(tmp3, 2);
1422
1423     /* Initialize hash unit */
1424     CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
1425     CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
1426     CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
1427
1428     CVMX_MT_HSH_DAT(tmp1, 0);
1429     CVMX_MT_HSH_DAT(tmp2, 1);
1430     tmp3 |= 0x0000000080000000;
1431     CVMX_MT_HSH_DAT(tmp3, 2);
1432     CVMX_MT_HSH_DATZ(3);
1433     CVMX_MT_HSH_DATZ(4);
1434     CVMX_MT_HSH_DATZ(5);
1435     CVMX_MT_HSH_DATZ(6);
1436     CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
1437     /* save the HMAC */
1438     IOV_INIT(iov, data32, data_i, data_l);
1439     while (icv_off > 0) {
1440         IOV_CONSUME(iov, data32, data_i, data_l);
1441         icv_off -= 4;
1442     }
1443     CVMX_MF_HSH_IV(tmp1, 0);
1444     *data32 = (uint32_t) (tmp1 >> 32);
1445     IOV_CONSUME(iov, data32, data_i, data_l);
1446     *data32 = (uint32_t) tmp1;
1447     IOV_CONSUME(iov, data32, data_i, data_l);
1448     CVMX_MF_HSH_IV(tmp1, 1);
1449     *data32 = (uint32_t) (tmp1 >> 32);
1450
1451     octeon_crypto_disable(s);
1452     return 0;
1453 }
1454
1455 /****************************************************************************/
1456 /* AES MD5 */
1457
1458 int
1459 octo_aes_cbc_md5_encrypt(
1460     struct octo_sess *od,
1461     struct iovec *iov, size_t iovcnt, size_t iovlen,
1462     int auth_off, int auth_len,
1463     int crypt_off, int crypt_len,
1464     int icv_off, uint8_t *ivp)
1465 {
1466     register int next = 0;
1467     union {
1468         uint32_t data32[2];
1469         uint64_t data64[1];
1470     } mydata[2];
1471     uint64_t *pdata = &mydata[0].data64[0];
1472     uint64_t *data =  &mydata[1].data64[0];
1473     uint32_t *data32;
1474     uint64_t tmp1, tmp2;
1475     int data_i, data_l, alen = auth_len;
1476     register_t s;
1477
1478     dprintf("%s()\n", __func__);
1479
1480     if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
1481             (crypt_off & 0x3) || (crypt_off + crypt_len > iovlen) ||
1482             (crypt_len  & 0x7) ||
1483             (auth_len  & 0x7) ||
1484             (auth_off & 0x3) || (auth_off + auth_len > iovlen))) {
1485         dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
1486                 "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
1487                 "icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
1488                 auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
1489         return -EINVAL;
1490     }
1491
1492     IOV_INIT(iov, data32, data_i, data_l);
1493
1494     CVMX_PREFETCH0(ivp);
1495     CVMX_PREFETCH0(od->octo_enckey);
1496
1497     s = octeon_crypto_enable();
1498
1499     /* load AES Key */
1500     CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
1501     CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
1502
1503     if (od->octo_encklen == 16) {
1504         CVMX_MT_AES_KEY(0x0, 2);
1505         CVMX_MT_AES_KEY(0x0, 3);
1506     } else if (od->octo_encklen == 24) {
1507         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1508         CVMX_MT_AES_KEY(0x0, 3);
1509     } else if (od->octo_encklen == 32) {
1510         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1511         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
1512     } else {
1513         octeon_crypto_disable(s);
1514         dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
1515         return -EINVAL;
1516     }
1517     CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
1518
1519     CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
1520     CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
1521
1522     /* Load MD5 IV */
1523     CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
1524     CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
1525
1526     while (crypt_off > 0 && auth_off > 0) {
1527         IOV_CONSUME(iov, data32, data_i, data_l);
1528         crypt_off -= 4;
1529         auth_off -= 4;
1530     }
1531
1532     while (crypt_len > 0 || auth_len > 0) {
1533         uint32_t *pdata32[3];
1534
1535         pdata32[0] = data32;
1536         mydata[0].data32[0] = *data32;
1537         IOV_CONSUME(iov, data32, data_i, data_l);
1538
1539         pdata32[1] = data32;
1540         mydata[0].data32[1] = *data32;
1541         IOV_CONSUME(iov, data32, data_i, data_l);
1542
1543         pdata32[2] = data32;
1544         mydata[1].data32[0] = *data32;
1545         IOV_CONSUME(iov, data32, data_i, data_l);
1546
1547         mydata[1].data32[1] = *data32;
1548
1549
1550         if (crypt_off <= 0) {
1551             if (crypt_len > 0) {
1552                 CVMX_MT_AES_ENC_CBC0(*pdata);
1553                 CVMX_MT_AES_ENC_CBC1(*data);
1554                 CVMX_MF_AES_RESULT(*pdata, 0);
1555                 CVMX_MF_AES_RESULT(*data, 1);
1556                 crypt_len -= 16;
1557             }
1558         } else
1559             crypt_off -= 16;
1560
1561         if (auth_off <= 0) {
1562             if (auth_len > 0) {
1563                 CVM_LOAD_MD5_UNIT(*pdata, next);
1564                 CVM_LOAD_MD5_UNIT(*data, next);
1565                 auth_len -= 16;
1566             }
1567         } else
1568             auth_off -= 16;
1569
1570         *pdata32[0] = mydata[0].data32[0];
1571         *pdata32[1] = mydata[0].data32[1];
1572         *pdata32[2] = mydata[1].data32[0];
1573         *data32     = mydata[1].data32[1];
1574
1575         IOV_CONSUME(iov, data32, data_i, data_l);
1576     }
1577
1578     /* finish the hash */
1579     CVMX_PREFETCH0(od->octo_hmouter);
1580 #if 0
1581     if (__predict_false(inplen)) {
1582         uint64_t tmp = 0;
1583         uint8_t *p = (uint8_t *) & tmp;
1584         p[inplen] = 0x80;
1585         do {
1586             inplen--;
1587             p[inplen] = ((uint8_t *) data)[inplen];
1588         } while (inplen);
1589         CVM_LOAD_MD5_UNIT(tmp, next);
1590     } else {
1591         CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
1592     }
1593 #else
1594     CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
1595 #endif
1596
1597     /* Finish Inner hash */
1598     while (next != 7) {
1599         CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
1600     }
1601     CVMX_ES64(tmp1, ((alen + 64) << 3));
1602     CVM_LOAD_MD5_UNIT(tmp1, next);
1603
1604     /* Get the inner hash of HMAC */
1605     CVMX_MF_HSH_IV(tmp1, 0);
1606     CVMX_MF_HSH_IV(tmp2, 1);
1607
1608     /* Initialize hash unit */
1609     CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
1610     CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
1611
1612     CVMX_MT_HSH_DAT(tmp1, 0);
1613     CVMX_MT_HSH_DAT(tmp2, 1);
1614     CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
1615     CVMX_MT_HSH_DATZ(3);
1616     CVMX_MT_HSH_DATZ(4);
1617     CVMX_MT_HSH_DATZ(5);
1618     CVMX_MT_HSH_DATZ(6);
1619     CVMX_ES64(tmp1, ((64 + 16) << 3));
1620     CVMX_MT_HSH_STARTMD5(tmp1);
1621
1622     /* save the HMAC */
1623     IOV_INIT(iov, data32, data_i, data_l);
1624     while (icv_off > 0) {
1625         IOV_CONSUME(iov, data32, data_i, data_l);
1626         icv_off -= 4;
1627     }
1628     CVMX_MF_HSH_IV(tmp1, 0);
1629     *data32 = (uint32_t) (tmp1 >> 32);
1630     IOV_CONSUME(iov, data32, data_i, data_l);
1631     *data32 = (uint32_t) tmp1;
1632     IOV_CONSUME(iov, data32, data_i, data_l);
1633     CVMX_MF_HSH_IV(tmp1, 1);
1634     *data32 = (uint32_t) (tmp1 >> 32);
1635
1636     octeon_crypto_disable(s);
1637     return 0;
1638 }
1639
1640 int
1641 octo_aes_cbc_md5_decrypt(
1642     struct octo_sess *od,
1643     struct iovec *iov, size_t iovcnt, size_t iovlen,
1644     int auth_off, int auth_len,
1645     int crypt_off, int crypt_len,
1646     int icv_off, uint8_t *ivp)
1647 {
1648     register int next = 0;
1649     union {
1650         uint32_t data32[2];
1651         uint64_t data64[1];
1652     } mydata[2];
1653     uint64_t *pdata = &mydata[0].data64[0];
1654     uint64_t *data =  &mydata[1].data64[0];
1655     uint32_t *data32;
1656     uint64_t tmp1, tmp2;
1657     int data_i, data_l, alen = auth_len;
1658     register_t s;
1659
1660     dprintf("%s()\n", __func__);
1661
1662     if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
1663             (crypt_off & 0x3) || (crypt_off + crypt_len > iovlen) ||
1664             (crypt_len  & 0x7) ||
1665             (auth_len  & 0x7) ||
1666             (auth_off & 0x3) || (auth_off + auth_len > iovlen))) {
1667         dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
1668                 "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
1669                 "icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
1670                 auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
1671         return -EINVAL;
1672     }
1673
1674     IOV_INIT(iov, data32, data_i, data_l);
1675
1676     CVMX_PREFETCH0(ivp);
1677     CVMX_PREFETCH0(od->octo_enckey);
1678
1679     s = octeon_crypto_enable();
1680
1681     /* load AES Key */
1682     CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
1683     CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
1684
1685     if (od->octo_encklen == 16) {
1686         CVMX_MT_AES_KEY(0x0, 2);
1687         CVMX_MT_AES_KEY(0x0, 3);
1688     } else if (od->octo_encklen == 24) {
1689         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1690         CVMX_MT_AES_KEY(0x0, 3);
1691     } else if (od->octo_encklen == 32) {
1692         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1693         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
1694     } else {
1695         octeon_crypto_disable(s);
1696         dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
1697         return -EINVAL;
1698     }
1699     CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
1700
1701     CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
1702     CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
1703
1704     /* Load MD5 IV */
1705     CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
1706     CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
1707
1708     while (crypt_off > 0 && auth_off > 0) {
1709         IOV_CONSUME(iov, data32, data_i, data_l);
1710         crypt_off -= 4;
1711         auth_off -= 4;
1712     }
1713
1714     while (crypt_len > 0 || auth_len > 0) {
1715         uint32_t *pdata32[3];
1716
1717         pdata32[0] = data32;
1718         mydata[0].data32[0] = *data32;
1719         IOV_CONSUME(iov, data32, data_i, data_l);
1720         pdata32[1] = data32;
1721         mydata[0].data32[1] = *data32;
1722         IOV_CONSUME(iov, data32, data_i, data_l);
1723         pdata32[2] = data32;
1724         mydata[1].data32[0] = *data32;
1725         IOV_CONSUME(iov, data32, data_i, data_l);
1726         mydata[1].data32[1] = *data32;
1727
1728         if (auth_off <= 0) {
1729             if (auth_len > 0) {
1730                 CVM_LOAD_MD5_UNIT(*pdata, next);
1731                 CVM_LOAD_MD5_UNIT(*data, next);
1732                 auth_len -= 16;
1733             }
1734         } else
1735             auth_off -= 16;
1736
1737         if (crypt_off <= 0) {
1738             if (crypt_len > 0) {
1739                 CVMX_MT_AES_DEC_CBC0(*pdata);
1740                 CVMX_MT_AES_DEC_CBC1(*data);
1741                 CVMX_MF_AES_RESULT(*pdata, 0);
1742                 CVMX_MF_AES_RESULT(*data, 1);
1743                 crypt_len -= 16;
1744             }
1745         } else
1746             crypt_off -= 16;
1747
1748         *pdata32[0] = mydata[0].data32[0];
1749         *pdata32[1] = mydata[0].data32[1];
1750         *pdata32[2] = mydata[1].data32[0];
1751         *data32     = mydata[1].data32[1];
1752
1753         IOV_CONSUME(iov, data32, data_i, data_l);
1754     }
1755
1756     /* finish the hash */
1757     CVMX_PREFETCH0(od->octo_hmouter);
1758 #if 0
1759     if (__predict_false(inplen)) {
1760         uint64_t tmp = 0;
1761         uint8_t *p = (uint8_t *) & tmp;
1762         p[inplen] = 0x80;
1763         do {
1764             inplen--;
1765             p[inplen] = ((uint8_t *) data)[inplen];
1766         } while (inplen);
1767         CVM_LOAD_MD5_UNIT(tmp, next);
1768     } else {
1769         CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
1770     }
1771 #else
1772     CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
1773 #endif
1774
1775     /* Finish Inner hash */
1776     while (next != 7) {
1777         CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
1778     }
1779     CVMX_ES64(tmp1, ((alen + 64) << 3));
1780     CVM_LOAD_MD5_UNIT(tmp1, next);
1781
1782     /* Get the inner hash of HMAC */
1783     CVMX_MF_HSH_IV(tmp1, 0);
1784     CVMX_MF_HSH_IV(tmp2, 1);
1785
1786     /* Initialize hash unit */
1787     CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
1788     CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
1789
1790     CVMX_MT_HSH_DAT(tmp1, 0);
1791     CVMX_MT_HSH_DAT(tmp2, 1);
1792     CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
1793     CVMX_MT_HSH_DATZ(3);
1794     CVMX_MT_HSH_DATZ(4);
1795     CVMX_MT_HSH_DATZ(5);
1796     CVMX_MT_HSH_DATZ(6);
1797     CVMX_ES64(tmp1, ((64 + 16) << 3));
1798     CVMX_MT_HSH_STARTMD5(tmp1);
1799
1800     /* save the HMAC */
1801     IOV_INIT(iov, data32, data_i, data_l);
1802     while (icv_off > 0) {
1803         IOV_CONSUME(iov, data32, data_i, data_l);
1804         icv_off -= 4;
1805     }
1806     CVMX_MF_HSH_IV(tmp1, 0);
1807     *data32 = (uint32_t) (tmp1 >> 32);
1808     IOV_CONSUME(iov, data32, data_i, data_l);
1809     *data32 = (uint32_t) tmp1;
1810     IOV_CONSUME(iov, data32, data_i, data_l);
1811     CVMX_MF_HSH_IV(tmp1, 1);
1812     *data32 = (uint32_t) (tmp1 >> 32);
1813
1814     octeon_crypto_disable(s);
1815     return 0;
1816 }
1817
1818 /****************************************************************************/
1819 /* AES SHA1 */
1820
1821 int
1822 octo_aes_cbc_sha1_encrypt(
1823     struct octo_sess *od,
1824     struct iovec *iov, size_t iovcnt, size_t iovlen,
1825     int auth_off, int auth_len,
1826     int crypt_off, int crypt_len,
1827     int icv_off, uint8_t *ivp)
1828 {
1829     register int next = 0;
1830     union {
1831         uint32_t data32[2];
1832         uint64_t data64[1];
1833     } mydata[2];
1834     uint64_t *pdata = &mydata[0].data64[0];
1835     uint64_t *data =  &mydata[1].data64[0];
1836     uint32_t *data32;
1837     uint64_t tmp1, tmp2, tmp3;
1838     int data_i, data_l, alen = auth_len;
1839     register_t s;
1840
1841     dprintf("%s()\n", __func__);
1842
1843     if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
1844             (crypt_off & 0x3) || (crypt_off + crypt_len > iovlen) ||
1845             (crypt_len  & 0x7) ||
1846             (auth_len  & 0x7) ||
1847             (auth_off & 0x3) || (auth_off + auth_len > iovlen))) {
1848         dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
1849                 "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
1850                 "icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
1851                 auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
1852         return -EINVAL;
1853     }
1854
1855     IOV_INIT(iov, data32, data_i, data_l);
1856
1857     CVMX_PREFETCH0(ivp);
1858     CVMX_PREFETCH0(od->octo_enckey);
1859
1860     s = octeon_crypto_enable();
1861
1862     /* load AES Key */
1863     CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
1864     CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
1865
1866     if (od->octo_encklen == 16) {
1867         CVMX_MT_AES_KEY(0x0, 2);
1868         CVMX_MT_AES_KEY(0x0, 3);
1869     } else if (od->octo_encklen == 24) {
1870         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1871         CVMX_MT_AES_KEY(0x0, 3);
1872     } else if (od->octo_encklen == 32) {
1873         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1874         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
1875     } else {
1876         octeon_crypto_disable(s);
1877         dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
1878         return -EINVAL;
1879     }
1880     CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
1881
1882     CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
1883     CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
1884
1885     /* Load SHA IV */
1886     CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
1887     CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
1888     CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
1889
1890     while (crypt_off > 0 && auth_off > 0) {
1891         IOV_CONSUME(iov, data32, data_i, data_l);
1892         crypt_off -= 4;
1893         auth_off -= 4;
1894     }
1895
1896     while (crypt_len > 0 || auth_len > 0) {
1897         uint32_t *pdata32[3];
1898
1899         pdata32[0] = data32;
1900         mydata[0].data32[0] = *data32;
1901         IOV_CONSUME(iov, data32, data_i, data_l);
1902         pdata32[1] = data32;
1903         mydata[0].data32[1] = *data32;
1904         IOV_CONSUME(iov, data32, data_i, data_l);
1905         pdata32[2] = data32;
1906         mydata[1].data32[0] = *data32;
1907         IOV_CONSUME(iov, data32, data_i, data_l);
1908         mydata[1].data32[1] = *data32;
1909
1910
1911         if (crypt_off <= 0) {
1912             if (crypt_len > 0) {
1913                 CVMX_MT_AES_ENC_CBC0(*pdata);
1914                 CVMX_MT_AES_ENC_CBC1(*data);
1915                 CVMX_MF_AES_RESULT(*pdata, 0);
1916                 CVMX_MF_AES_RESULT(*data, 1);
1917                 crypt_len -= 16;
1918             }
1919         } else
1920             crypt_off -= 16;
1921
1922         if (auth_off <= 0) {
1923             if (auth_len > 0) {
1924                 CVM_LOAD_SHA_UNIT(*pdata, next);
1925                 CVM_LOAD_SHA_UNIT(*data, next);
1926                 auth_len -= 16;
1927             }
1928         } else
1929             auth_off -= 16;
1930
1931         *pdata32[0] = mydata[0].data32[0];
1932         *pdata32[1] = mydata[0].data32[1];
1933         *pdata32[2] = mydata[1].data32[0];
1934         *data32     = mydata[1].data32[1];
1935
1936         IOV_CONSUME(iov, data32, data_i, data_l);
1937     }
1938
1939     /* finish the hash */
1940     CVMX_PREFETCH0(od->octo_hmouter);
1941 #if 0
1942     if (__predict_false(inplen)) {
1943         uint64_t tmp = 0;
1944         uint8_t *p = (uint8_t *) & tmp;
1945         p[inplen] = 0x80;
1946         do {
1947             inplen--;
1948             p[inplen] = ((uint8_t *) data)[inplen];
1949         } while (inplen);
1950         CVM_LOAD_SHA_UNIT(tmp, next);
1951     } else {
1952         CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
1953     }
1954 #else
1955     CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
1956 #endif
1957
1958     /* Finish Inner hash */
1959     while (next != 7) {
1960         CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
1961     }
1962         CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
1963
1964     /* Get the inner hash of HMAC */
1965     CVMX_MF_HSH_IV(tmp1, 0);
1966     CVMX_MF_HSH_IV(tmp2, 1);
1967     tmp3 = 0;
1968     CVMX_MF_HSH_IV(tmp3, 2);
1969
1970     /* Initialize hash unit */
1971     CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
1972     CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
1973     CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
1974
1975     CVMX_MT_HSH_DAT(tmp1, 0);
1976     CVMX_MT_HSH_DAT(tmp2, 1);
1977     tmp3 |= 0x0000000080000000;
1978     CVMX_MT_HSH_DAT(tmp3, 2);
1979     CVMX_MT_HSH_DATZ(3);
1980     CVMX_MT_HSH_DATZ(4);
1981     CVMX_MT_HSH_DATZ(5);
1982     CVMX_MT_HSH_DATZ(6);
1983     CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
1984
1985     /* finish the hash */
1986     CVMX_PREFETCH0(od->octo_hmouter);
1987 #if 0
1988     if (__predict_false(inplen)) {
1989         uint64_t tmp = 0;
1990         uint8_t *p = (uint8_t *) & tmp;
1991         p[inplen] = 0x80;
1992         do {
1993             inplen--;
1994             p[inplen] = ((uint8_t *) data)[inplen];
1995         } while (inplen);
1996         CVM_LOAD_MD5_UNIT(tmp, next);
1997     } else {
1998         CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
1999     }
2000 #else
2001     CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
2002 #endif
2003
2004     /* save the HMAC */
2005     IOV_INIT(iov, data32, data_i, data_l);
2006     while (icv_off > 0) {
2007         IOV_CONSUME(iov, data32, data_i, data_l);
2008         icv_off -= 4;
2009     }
2010     CVMX_MF_HSH_IV(tmp1, 0);
2011     *data32 = (uint32_t) (tmp1 >> 32);
2012     IOV_CONSUME(iov, data32, data_i, data_l);
2013     *data32 = (uint32_t) tmp1;
2014     IOV_CONSUME(iov, data32, data_i, data_l);
2015     CVMX_MF_HSH_IV(tmp1, 1);
2016     *data32 = (uint32_t) (tmp1 >> 32);
2017
2018     octeon_crypto_disable(s);
2019     return 0;
2020 }
2021
2022 int
2023 octo_aes_cbc_sha1_decrypt(
2024     struct octo_sess *od,
2025     struct iovec *iov, size_t iovcnt, size_t iovlen,
2026     int auth_off, int auth_len,
2027     int crypt_off, int crypt_len,
2028     int icv_off, uint8_t *ivp)
2029 {
2030     register int next = 0;
2031     union {
2032         uint32_t data32[2];
2033         uint64_t data64[1];
2034     } mydata[2];
2035     uint64_t *pdata = &mydata[0].data64[0];
2036     uint64_t *data =  &mydata[1].data64[0];
2037     uint32_t *data32;
2038     uint64_t tmp1, tmp2, tmp3;
2039     int data_i, data_l, alen = auth_len;
2040     register_t s;
2041
2042     dprintf("%s()\n", __func__);
2043
2044     if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
2045             (crypt_off & 0x3) || (crypt_off + crypt_len > iovlen) ||
2046             (crypt_len  & 0x7) ||
2047             (auth_len  & 0x7) ||
2048             (auth_off & 0x3) || (auth_off + auth_len > iovlen))) {
2049         dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
2050                 "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
2051                 "icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
2052                 auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
2053         return -EINVAL;
2054     }
2055
2056     IOV_INIT(iov, data32, data_i, data_l);
2057
2058     CVMX_PREFETCH0(ivp);
2059     CVMX_PREFETCH0(od->octo_enckey);
2060
2061     s = octeon_crypto_enable();
2062
2063     /* load AES Key */
2064     CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
2065     CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
2066
2067     if (od->octo_encklen == 16) {
2068         CVMX_MT_AES_KEY(0x0, 2);
2069         CVMX_MT_AES_KEY(0x0, 3);
2070     } else if (od->octo_encklen == 24) {
2071         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
2072         CVMX_MT_AES_KEY(0x0, 3);
2073     } else if (od->octo_encklen == 32) {
2074         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
2075         CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
2076     } else {
2077         octeon_crypto_disable(s);
2078         dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
2079         return -EINVAL;
2080     }
2081     CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
2082
2083     CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
2084     CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
2085
2086     /* Load MD5 IV */
2087     CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
2088     CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
2089     CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
2090
2091     while (crypt_off > 0 && auth_off > 0) {
2092         IOV_CONSUME(iov, data32, data_i, data_l);
2093         crypt_off -= 4;
2094         auth_off -= 4;
2095     }
2096
2097     while (crypt_len > 0 || auth_len > 0) {
2098         uint32_t *pdata32[3];
2099
2100         pdata32[0] = data32;
2101         mydata[0].data32[0] = *data32;
2102         IOV_CONSUME(iov, data32, data_i, data_l);
2103         pdata32[1] = data32;
2104         mydata[0].data32[1] = *data32;
2105         IOV_CONSUME(iov, data32, data_i, data_l);
2106         pdata32[2] = data32;
2107         mydata[1].data32[0] = *data32;
2108         IOV_CONSUME(iov, data32, data_i, data_l);
2109         mydata[1].data32[1] = *data32;
2110
2111         if (auth_off <= 0) {
2112             if (auth_len > 0) {
2113                 CVM_LOAD_SHA_UNIT(*pdata, next);
2114                 CVM_LOAD_SHA_UNIT(*data, next);
2115                 auth_len -= 16;
2116             }
2117         } else
2118             auth_off -= 16;
2119
2120         if (crypt_off <= 0) {
2121             if (crypt_len > 0) {
2122                 CVMX_MT_AES_DEC_CBC0(*pdata);
2123                 CVMX_MT_AES_DEC_CBC1(*data);
2124                 CVMX_MF_AES_RESULT(*pdata, 0);
2125                 CVMX_MF_AES_RESULT(*data, 1);
2126                 crypt_len -= 16;
2127             }
2128         } else
2129             crypt_off -= 16;
2130
2131         *pdata32[0] = mydata[0].data32[0];
2132         *pdata32[1] = mydata[0].data32[1];
2133         *pdata32[2] = mydata[1].data32[0];
2134         *data32     = mydata[1].data32[1];
2135
2136         IOV_CONSUME(iov, data32, data_i, data_l);
2137     }
2138
2139     /* finish the hash */
2140     CVMX_PREFETCH0(od->octo_hmouter);
2141 #if 0
2142     if (__predict_false(inplen)) {
2143         uint64_t tmp = 0;
2144         uint8_t *p = (uint8_t *) & tmp;
2145         p[inplen] = 0x80;
2146         do {
2147             inplen--;
2148             p[inplen] = ((uint8_t *) data)[inplen];
2149         } while (inplen);
2150         CVM_LOAD_SHA_UNIT(tmp, next);
2151     } else {
2152         CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
2153     }
2154 #else
2155     CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
2156 #endif
2157
2158     /* Finish Inner hash */
2159     while (next != 7) {
2160         CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
2161     }
2162         CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
2163
2164     /* Get the inner hash of HMAC */
2165     CVMX_MF_HSH_IV(tmp1, 0);
2166     CVMX_MF_HSH_IV(tmp2, 1);
2167     tmp3 = 0;
2168     CVMX_MF_HSH_IV(tmp3, 2);
2169
2170     /* Initialize hash unit */
2171     CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
2172     CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
2173     CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
2174
2175     CVMX_MT_HSH_DAT(tmp1, 0);
2176     CVMX_MT_HSH_DAT(tmp2, 1);
2177     tmp3 |= 0x0000000080000000;
2178     CVMX_MT_HSH_DAT(tmp3, 2);
2179     CVMX_MT_HSH_DATZ(3);
2180     CVMX_MT_HSH_DATZ(4);
2181     CVMX_MT_HSH_DATZ(5);
2182     CVMX_MT_HSH_DATZ(6);
2183     CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
2184
2185     /* finish the hash */
2186     CVMX_PREFETCH0(od->octo_hmouter);
2187 #if 0
2188     if (__predict_false(inplen)) {
2189         uint64_t tmp = 0;
2190         uint8_t *p = (uint8_t *) & tmp;
2191         p[inplen] = 0x80;
2192         do {
2193             inplen--;
2194             p[inplen] = ((uint8_t *) data)[inplen];
2195         } while (inplen);
2196         CVM_LOAD_MD5_UNIT(tmp, next);
2197     } else {
2198         CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
2199     }
2200 #else
2201     CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
2202 #endif
2203
2204     /* save the HMAC */
2205     IOV_INIT(iov, data32, data_i, data_l);
2206     while (icv_off > 0) {
2207         IOV_CONSUME(iov, data32, data_i, data_l);
2208         icv_off -= 4;
2209     }
2210     CVMX_MF_HSH_IV(tmp1, 0);
2211     *data32 = (uint32_t) (tmp1 >> 32);
2212     IOV_CONSUME(iov, data32, data_i, data_l);
2213     *data32 = (uint32_t) tmp1;
2214     IOV_CONSUME(iov, data32, data_i, data_l);
2215     CVMX_MF_HSH_IV(tmp1, 1);
2216     *data32 = (uint32_t) (tmp1 >> 32);
2217
2218     octeon_crypto_disable(s);
2219     return 0;
2220 }
2221
2222 /****************************************************************************/