1210312Sjmallett/*
2210312Sjmallett * vim:sw=4 ts=8
3210312Sjmallett */
4210312Sjmallett/*
5210312Sjmallett * Copyright (c) 2009 David McCullough <david.mccullough@securecomputing.com>
6210312Sjmallett *
7210312Sjmallett * Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
8210312Sjmallett * reserved.
9210312Sjmallett *
10210312Sjmallett * Redistribution and use in source and binary forms, with or without
11210312Sjmallett * modification, are permitted provided that the following conditions are met:
12210312Sjmallett * 1. Redistributions of source code must retain the above copyright notice,
13210312Sjmallett * this list of conditions and the following disclaimer.
14210312Sjmallett * 2. Redistributions in binary form must reproduce the above copyright notice,
15210312Sjmallett * this list of conditions and the following disclaimer in the documentation
16210312Sjmallett * and/or other materials provided with the distribution.
17210312Sjmallett * 3. All advertising materials mentioning features or use of this software
18210312Sjmallett * must display the following acknowledgement:
19210312Sjmallett * This product includes software developed by Cavium Networks
20210312Sjmallett * 4. Cavium Networks' name may not be used to endorse or promote products
21210312Sjmallett * derived from this software without specific prior written permission.
22210312Sjmallett *
23210312Sjmallett * This Software, including technical data, may be subject to U.S. export
24210312Sjmallett * control laws, including the U.S. Export Administration Act and its
25210312Sjmallett * associated regulations, and may be subject to export or import regulations
26210312Sjmallett * in other countries. You warrant that You will comply strictly in all
27210312Sjmallett * respects with all such regulations and acknowledge that you have the
28210312Sjmallett * responsibility to obtain licenses to export, re-export or import the
29210312Sjmallett * Software.
30210312Sjmallett *
31210312Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" AND
32210312Sjmallett * WITH ALL FAULTS AND CAVIUM MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES,
33210312Sjmallett * EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE
34210312Sjmallett * SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
35210312Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
36210312Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
37210312Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
38210312Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
39210312Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
40210312Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
41210312Sjmallett*/
42210312Sjmallett/****************************************************************************/
43210312Sjmallett
44210312Sjmallett#include <sys/cdefs.h>
45210312Sjmallett__FBSDID("$FreeBSD$");
46210312Sjmallett
47210312Sjmallett#include <sys/param.h>
48210312Sjmallett#include <sys/systm.h>
49210312Sjmallett#include <sys/kernel.h>
50210312Sjmallett#include <sys/module.h>
51210312Sjmallett#include <sys/malloc.h>
52210312Sjmallett#include <sys/uio.h>
53210312Sjmallett
54210312Sjmallett#include <opencrypto/cryptodev.h>
55210312Sjmallett
56210312Sjmallett#include <contrib/octeon-sdk/cvmx.h>
57210312Sjmallett
58210312Sjmallett#include <mips/cavium/cryptocteon/cryptocteonvar.h>
59210312Sjmallett
60210312Sjmallett/****************************************************************************/
61210312Sjmallett
62210312Sjmallett#define	IOV_INIT(iov, ptr, idx, len)					\
63210312Sjmallett	do {								\
64210312Sjmallett	    (idx) = 0;							\
65210312Sjmallett	    (ptr) = (iov)[(idx)].iov_base;				\
66210312Sjmallett	    (len) = (iov)[(idx)].iov_len;				\
67210312Sjmallett	} while (0)
68210312Sjmallett
69210312Sjmallett/*
70210312Sjmallett * XXX
71210312Sjmallett * It would be better if this were an IOV_READ/IOV_WRITE macro instead so
72210312Sjmallett * that we could detect overflow before it happens rather than right after,
73210312Sjmallett * which is especially bad since there is usually no IOV_CONSUME after the
74210312Sjmallett * final read or write.
75210312Sjmallett */
76210312Sjmallett#define	IOV_CONSUME(iov, ptr, idx, len)					\
77210312Sjmallett	do {								\
78210312Sjmallett	    if ((len) > sizeof *(ptr)) {				\
79210312Sjmallett		(len) -= sizeof *(ptr);					\
80210312Sjmallett		(ptr)++;						\
81210312Sjmallett	    } else {							\
82210312Sjmallett		if ((len) != sizeof *(ptr))				\
83210312Sjmallett			panic("%s: went past end of iovec.", __func__);	\
84210312Sjmallett		(idx)++;						\
85210312Sjmallett		(ptr) = (iov)[(idx)].iov_base;				\
86210312Sjmallett		(len) = (iov)[(idx)].iov_len;				\
87210312Sjmallett	    }								\
88210312Sjmallett	} while (0)
89210312Sjmallett
90210312Sjmallett#define ESP_HEADER_LENGTH     8
91210312Sjmallett#define DES_CBC_IV_LENGTH     8
92210312Sjmallett#define AES_CBC_IV_LENGTH     16
93210312Sjmallett#define ESP_HMAC_LEN          12
94210312Sjmallett
95210312Sjmallett#define ESP_HEADER_LENGTH 8
96210312Sjmallett#define DES_CBC_IV_LENGTH 8
97210312Sjmallett
98210312Sjmallett/****************************************************************************/
99210312Sjmallett
100210312Sjmallett#define CVM_LOAD_SHA_UNIT(dat, next)  { \
101210312Sjmallett   if (next == 0) {                     \
102210312Sjmallett      next = 1;                         \
103210312Sjmallett      CVMX_MT_HSH_DAT (dat, 0);         \
104210312Sjmallett   } else if (next == 1) {              \
105210312Sjmallett      next = 2;                         \
106210312Sjmallett      CVMX_MT_HSH_DAT (dat, 1);         \
107210312Sjmallett   } else if (next == 2) {              \
108210312Sjmallett      next = 3;                    \
109210312Sjmallett      CVMX_MT_HSH_DAT (dat, 2);         \
110210312Sjmallett   } else if (next == 3) {              \
111210312Sjmallett      next = 4;                         \
112210312Sjmallett      CVMX_MT_HSH_DAT (dat, 3);         \
113210312Sjmallett   } else if (next == 4) {              \
114210312Sjmallett      next = 5;                           \
115210312Sjmallett      CVMX_MT_HSH_DAT (dat, 4);         \
116210312Sjmallett   } else if (next == 5) {              \
117210312Sjmallett      next = 6;                         \
118210312Sjmallett      CVMX_MT_HSH_DAT (dat, 5);         \
119210312Sjmallett   } else if (next == 6) {              \
120210312Sjmallett      next = 7;                         \
121210312Sjmallett      CVMX_MT_HSH_DAT (dat, 6);         \
122210312Sjmallett   } else {                             \
123210312Sjmallett     CVMX_MT_HSH_STARTSHA (dat);        \
124210312Sjmallett     next = 0;                          \
125210312Sjmallett   }                                    \
126210312Sjmallett}
127210312Sjmallett
128210312Sjmallett#define CVM_LOAD2_SHA_UNIT(dat1, dat2, next)  { \
129210312Sjmallett   if (next == 0) {                      \
130210312Sjmallett      CVMX_MT_HSH_DAT (dat1, 0);         \
131210312Sjmallett      CVMX_MT_HSH_DAT (dat2, 1);         \
132210312Sjmallett      next = 2;                          \
133210312Sjmallett   } else if (next == 1) {               \
134210312Sjmallett      CVMX_MT_HSH_DAT (dat1, 1);         \
135210312Sjmallett      CVMX_MT_HSH_DAT (dat2, 2);         \
136210312Sjmallett      next = 3;                          \
137210312Sjmallett   } else if (next == 2) {               \
138210312Sjmallett      CVMX_MT_HSH_DAT (dat1, 2);         \
139210312Sjmallett      CVMX_MT_HSH_DAT (dat2, 3);         \
140210312Sjmallett      next = 4;                          \
141210312Sjmallett   } else if (next == 3) {               \
142210312Sjmallett      CVMX_MT_HSH_DAT (dat1, 3);         \
143210312Sjmallett      CVMX_MT_HSH_DAT (dat2, 4);         \
144210312Sjmallett      next = 5;                          \
145210312Sjmallett   } else if (next == 4) {               \
146210312Sjmallett      CVMX_MT_HSH_DAT (dat1, 4);         \
147210312Sjmallett      CVMX_MT_HSH_DAT (dat2, 5);         \
148210312Sjmallett      next = 6;                          \
149210312Sjmallett   } else if (next == 5) {               \
150210312Sjmallett      CVMX_MT_HSH_DAT (dat1, 5);         \
151210312Sjmallett      CVMX_MT_HSH_DAT (dat2, 6);         \
152210312Sjmallett      next = 7;                          \
153210312Sjmallett   } else if (next == 6) {               \
154210312Sjmallett      CVMX_MT_HSH_DAT (dat1, 6);         \
155210312Sjmallett      CVMX_MT_HSH_STARTSHA (dat2);       \
156210312Sjmallett      next = 0;                          \
157210312Sjmallett   } else {                              \
158210312Sjmallett     CVMX_MT_HSH_STARTSHA (dat1);        \
159210312Sjmallett     CVMX_MT_HSH_DAT (dat2, 0);          \
160210312Sjmallett     next = 1;                           \
161210312Sjmallett   }                                     \
162210312Sjmallett}
163210312Sjmallett
164210312Sjmallett/****************************************************************************/
165210312Sjmallett
166210312Sjmallett#define CVM_LOAD_MD5_UNIT(dat, next)  { \
167210312Sjmallett   if (next == 0) {                     \
168210312Sjmallett      next = 1;                         \
169210312Sjmallett      CVMX_MT_HSH_DAT (dat, 0);         \
170210312Sjmallett   } else if (next == 1) {              \
171210312Sjmallett      next = 2;                         \
172210312Sjmallett      CVMX_MT_HSH_DAT (dat, 1);         \
173210312Sjmallett   } else if (next == 2) {              \
174210312Sjmallett      next = 3;                    \
175210312Sjmallett      CVMX_MT_HSH_DAT (dat, 2);         \
176210312Sjmallett   } else if (next == 3) {              \
177210312Sjmallett      next = 4;                         \
178210312Sjmallett      CVMX_MT_HSH_DAT (dat, 3);         \
179210312Sjmallett   } else if (next == 4) {              \
180210312Sjmallett      next = 5;                           \
181210312Sjmallett      CVMX_MT_HSH_DAT (dat, 4);         \
182210312Sjmallett   } else if (next == 5) {              \
183210312Sjmallett      next = 6;                         \
184210312Sjmallett      CVMX_MT_HSH_DAT (dat, 5);         \
185210312Sjmallett   } else if (next == 6) {              \
186210312Sjmallett      next = 7;                         \
187210312Sjmallett      CVMX_MT_HSH_DAT (dat, 6);         \
188210312Sjmallett   } else {                             \
189210312Sjmallett     CVMX_MT_HSH_STARTMD5 (dat);        \
190210312Sjmallett     next = 0;                          \
191210312Sjmallett   }                                    \
192210312Sjmallett}
193210312Sjmallett
194210312Sjmallett#define CVM_LOAD2_MD5_UNIT(dat1, dat2, next)  { \
195210312Sjmallett   if (next == 0) {                      \
196210312Sjmallett      CVMX_MT_HSH_DAT (dat1, 0);         \
197210312Sjmallett      CVMX_MT_HSH_DAT (dat2, 1);         \
198210312Sjmallett      next = 2;                          \
199210312Sjmallett   } else if (next == 1) {               \
200210312Sjmallett      CVMX_MT_HSH_DAT (dat1, 1);         \
201210312Sjmallett      CVMX_MT_HSH_DAT (dat2, 2);         \
202210312Sjmallett      next = 3;                          \
203210312Sjmallett   } else if (next == 2) {               \
204210312Sjmallett      CVMX_MT_HSH_DAT (dat1, 2);         \
205210312Sjmallett      CVMX_MT_HSH_DAT (dat2, 3);         \
206210312Sjmallett      next = 4;                          \
207210312Sjmallett   } else if (next == 3) {               \
208210312Sjmallett      CVMX_MT_HSH_DAT (dat1, 3);         \
209210312Sjmallett      CVMX_MT_HSH_DAT (dat2, 4);         \
210210312Sjmallett      next = 5;                          \
211210312Sjmallett   } else if (next == 4) {               \
212210312Sjmallett      CVMX_MT_HSH_DAT (dat1, 4);         \
213210312Sjmallett      CVMX_MT_HSH_DAT (dat2, 5);         \
214210312Sjmallett      next = 6;                          \
215210312Sjmallett   } else if (next == 5) {               \
216210312Sjmallett      CVMX_MT_HSH_DAT (dat1, 5);         \
217210312Sjmallett      CVMX_MT_HSH_DAT (dat2, 6);         \
218210312Sjmallett      next = 7;                          \
219210312Sjmallett   } else if (next == 6) {               \
220210312Sjmallett      CVMX_MT_HSH_DAT (dat1, 6);         \
221210312Sjmallett      CVMX_MT_HSH_STARTMD5 (dat2);       \
222210312Sjmallett      next = 0;                          \
223210312Sjmallett   } else {                              \
224210312Sjmallett     CVMX_MT_HSH_STARTMD5 (dat1);        \
225210312Sjmallett     CVMX_MT_HSH_DAT (dat2, 0);          \
226210312Sjmallett     next = 1;                           \
227210312Sjmallett   }                                     \
228210312Sjmallett}
229210312Sjmallett
230210312Sjmallett/****************************************************************************/
231210312Sjmallett
232210312Sjmallettvoid
233210312Sjmallettocto_calc_hash(uint8_t auth, unsigned char *key, uint64_t *inner, uint64_t *outer)
234210312Sjmallett{
235210312Sjmallett    uint8_t hash_key[64];
236210312Sjmallett    uint64_t *key1;
237210312Sjmallett    register uint64_t xor1 = 0x3636363636363636ULL;
238210312Sjmallett    register uint64_t xor2 = 0x5c5c5c5c5c5c5c5cULL;
239210312Sjmallett
240210312Sjmallett    dprintf("%s()\n", __func__);
241210312Sjmallett
242210312Sjmallett    memset(hash_key, 0, sizeof(hash_key));
243210312Sjmallett    memcpy(hash_key, (uint8_t *) key, (auth ? 20 : 16));
244210312Sjmallett    key1 = (uint64_t *) hash_key;
245210312Sjmallett    if (auth) {
246210312Sjmallett       CVMX_MT_HSH_IV(0x67452301EFCDAB89ULL, 0);
247210312Sjmallett       CVMX_MT_HSH_IV(0x98BADCFE10325476ULL, 1);
248210312Sjmallett       CVMX_MT_HSH_IV(0xC3D2E1F000000000ULL, 2);
249210312Sjmallett    } else {
250210312Sjmallett       CVMX_MT_HSH_IV(0x0123456789ABCDEFULL, 0);
251210312Sjmallett       CVMX_MT_HSH_IV(0xFEDCBA9876543210ULL, 1);
252210312Sjmallett    }
253210312Sjmallett
254210312Sjmallett    CVMX_MT_HSH_DAT((*key1 ^ xor1), 0);
255210312Sjmallett    key1++;
256210312Sjmallett    CVMX_MT_HSH_DAT((*key1 ^ xor1), 1);
257210312Sjmallett    key1++;
258210312Sjmallett    CVMX_MT_HSH_DAT((*key1 ^ xor1), 2);
259210312Sjmallett    key1++;
260210312Sjmallett    CVMX_MT_HSH_DAT((*key1 ^ xor1), 3);
261210312Sjmallett    key1++;
262210312Sjmallett    CVMX_MT_HSH_DAT((*key1 ^ xor1), 4);
263210312Sjmallett    key1++;
264210312Sjmallett    CVMX_MT_HSH_DAT((*key1 ^ xor1), 5);
265210312Sjmallett    key1++;
266210312Sjmallett    CVMX_MT_HSH_DAT((*key1 ^ xor1), 6);
267210312Sjmallett    key1++;
268210312Sjmallett    if (auth)
269210312Sjmallett		CVMX_MT_HSH_STARTSHA((*key1 ^ xor1));
270210312Sjmallett    else
271210312Sjmallett		CVMX_MT_HSH_STARTMD5((*key1 ^ xor1));
272210312Sjmallett
273210312Sjmallett    CVMX_MF_HSH_IV(inner[0], 0);
274210312Sjmallett    CVMX_MF_HSH_IV(inner[1], 1);
275210312Sjmallett    if (auth) {
276210312Sjmallett		inner[2] = 0;
277210312Sjmallett		CVMX_MF_HSH_IV(((uint64_t *) inner)[2], 2);
278210312Sjmallett    }
279210312Sjmallett
280210312Sjmallett    memset(hash_key, 0, sizeof(hash_key));
281210312Sjmallett    memcpy(hash_key, (uint8_t *) key, (auth ? 20 : 16));
282210312Sjmallett    key1 = (uint64_t *) hash_key;
283210312Sjmallett    if (auth) {
284210312Sjmallett      CVMX_MT_HSH_IV(0x67452301EFCDAB89ULL, 0);
285210312Sjmallett      CVMX_MT_HSH_IV(0x98BADCFE10325476ULL, 1);
286210312Sjmallett      CVMX_MT_HSH_IV(0xC3D2E1F000000000ULL, 2);
287210312Sjmallett    } else {
288210312Sjmallett      CVMX_MT_HSH_IV(0x0123456789ABCDEFULL, 0);
289210312Sjmallett      CVMX_MT_HSH_IV(0xFEDCBA9876543210ULL, 1);
290210312Sjmallett    }
291210312Sjmallett
292210312Sjmallett    CVMX_MT_HSH_DAT((*key1 ^ xor2), 0);
293210312Sjmallett    key1++;
294210312Sjmallett    CVMX_MT_HSH_DAT((*key1 ^ xor2), 1);
295210312Sjmallett    key1++;
296210312Sjmallett    CVMX_MT_HSH_DAT((*key1 ^ xor2), 2);
297210312Sjmallett    key1++;
298210312Sjmallett    CVMX_MT_HSH_DAT((*key1 ^ xor2), 3);
299210312Sjmallett    key1++;
300210312Sjmallett    CVMX_MT_HSH_DAT((*key1 ^ xor2), 4);
301210312Sjmallett    key1++;
302210312Sjmallett    CVMX_MT_HSH_DAT((*key1 ^ xor2), 5);
303210312Sjmallett    key1++;
304210312Sjmallett    CVMX_MT_HSH_DAT((*key1 ^ xor2), 6);
305210312Sjmallett    key1++;
306210312Sjmallett    if (auth)
307210312Sjmallett       CVMX_MT_HSH_STARTSHA((*key1 ^ xor2));
308210312Sjmallett    else
309210312Sjmallett       CVMX_MT_HSH_STARTMD5((*key1 ^ xor2));
310210312Sjmallett
311210312Sjmallett    CVMX_MF_HSH_IV(outer[0], 0);
312210312Sjmallett    CVMX_MF_HSH_IV(outer[1], 1);
313210312Sjmallett    if (auth) {
314210312Sjmallett      outer[2] = 0;
315210312Sjmallett      CVMX_MF_HSH_IV(outer[2], 2);
316210312Sjmallett    }
317210312Sjmallett    return;
318210312Sjmallett}
319210312Sjmallett
320210312Sjmallett/****************************************************************************/
321210312Sjmallett/* DES functions */
322210312Sjmallett
323210312Sjmallettint
324210312Sjmallettocto_des_cbc_encrypt(
325210312Sjmallett    struct octo_sess *od,
326210312Sjmallett    struct iovec *iov, size_t iovcnt, size_t iovlen,
327210312Sjmallett    int auth_off, int auth_len,
328210312Sjmallett    int crypt_off, int crypt_len,
329210312Sjmallett    int icv_off, uint8_t *ivp)
330210312Sjmallett{
331210312Sjmallett    uint64_t *data;
332210312Sjmallett    int data_i, data_l;
333210312Sjmallett
334210312Sjmallett    dprintf("%s()\n", __func__);
335210312Sjmallett
336210312Sjmallett    if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
337210312Sjmallett	    (crypt_off & 0x7) || (crypt_off + crypt_len > iovlen))) {
338217620Sgonzo	dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
339210312Sjmallett		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
340210312Sjmallett		"icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
341210312Sjmallett		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
342210312Sjmallett	return -EINVAL;
343210312Sjmallett    }
344210312Sjmallett
345210312Sjmallett    IOV_INIT(iov, data, data_i, data_l);
346210312Sjmallett
347210312Sjmallett    CVMX_PREFETCH0(ivp);
348210312Sjmallett    CVMX_PREFETCH0(od->octo_enckey);
349210312Sjmallett
350210312Sjmallett
351210312Sjmallett    /* load 3DES Key */
352210312Sjmallett    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
353210312Sjmallett    if (od->octo_encklen == 24) {
354210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
355210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
356210312Sjmallett    } else if (od->octo_encklen == 8) {
357210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
358210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
359210312Sjmallett    } else {
360210312Sjmallett	dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
361210312Sjmallett	return -EINVAL;
362210312Sjmallett    }
363210312Sjmallett
364210312Sjmallett    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
365210312Sjmallett
366210312Sjmallett    while (crypt_off > 0) {
367210312Sjmallett	IOV_CONSUME(iov, data, data_i, data_l);
368210312Sjmallett	crypt_off -= 8;
369210312Sjmallett    }
370210312Sjmallett
371210312Sjmallett    while (crypt_len > 0) {
372210312Sjmallett	CVMX_MT_3DES_ENC_CBC(*data);
373210312Sjmallett	CVMX_MF_3DES_RESULT(*data);
374210312Sjmallett	IOV_CONSUME(iov, data, data_i, data_l);
375210312Sjmallett	crypt_len -= 8;
376210312Sjmallett    }
377210312Sjmallett
378210312Sjmallett    return 0;
379210312Sjmallett}
380210312Sjmallett
381210312Sjmallett
382210312Sjmallettint
383210312Sjmallettocto_des_cbc_decrypt(
384210312Sjmallett    struct octo_sess *od,
385210312Sjmallett    struct iovec *iov, size_t iovcnt, size_t iovlen,
386210312Sjmallett    int auth_off, int auth_len,
387210312Sjmallett    int crypt_off, int crypt_len,
388210312Sjmallett    int icv_off, uint8_t *ivp)
389210312Sjmallett{
390210312Sjmallett    uint64_t *data;
391210312Sjmallett    int data_i, data_l;
392210312Sjmallett
393210312Sjmallett    dprintf("%s()\n", __func__);
394210312Sjmallett
395210312Sjmallett    if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
396210312Sjmallett	    (crypt_off & 0x7) || (crypt_off + crypt_len > iovlen))) {
397217620Sgonzo	dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
398210312Sjmallett		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
399210312Sjmallett		"icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
400210312Sjmallett		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
401210312Sjmallett	return -EINVAL;
402210312Sjmallett    }
403210312Sjmallett
404210312Sjmallett    IOV_INIT(iov, data, data_i, data_l);
405210312Sjmallett
406210312Sjmallett    CVMX_PREFETCH0(ivp);
407210312Sjmallett    CVMX_PREFETCH0(od->octo_enckey);
408210312Sjmallett
409210312Sjmallett    /* load 3DES Key */
410210312Sjmallett    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
411210312Sjmallett    if (od->octo_encklen == 24) {
412210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
413210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
414210312Sjmallett    } else if (od->octo_encklen == 8) {
415210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
416210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
417210312Sjmallett    } else {
418210312Sjmallett	dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
419210312Sjmallett	return -EINVAL;
420210312Sjmallett    }
421210312Sjmallett
422210312Sjmallett    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
423210312Sjmallett
424210312Sjmallett    while (crypt_off > 0) {
425210312Sjmallett	IOV_CONSUME(iov, data, data_i, data_l);
426210312Sjmallett	crypt_off -= 8;
427210312Sjmallett    }
428210312Sjmallett
429210312Sjmallett    while (crypt_len > 0) {
430210312Sjmallett	CVMX_MT_3DES_DEC_CBC(*data);
431210312Sjmallett	CVMX_MF_3DES_RESULT(*data);
432210312Sjmallett	IOV_CONSUME(iov, data, data_i, data_l);
433210312Sjmallett	crypt_len -= 8;
434210312Sjmallett    }
435210312Sjmallett
436210312Sjmallett    return 0;
437210312Sjmallett}
438210312Sjmallett
439210312Sjmallett/****************************************************************************/
440210312Sjmallett/* AES functions */
441210312Sjmallett
442210312Sjmallettint
443210312Sjmallettocto_aes_cbc_encrypt(
444210312Sjmallett    struct octo_sess *od,
445210312Sjmallett    struct iovec *iov, size_t iovcnt, size_t iovlen,
446210312Sjmallett    int auth_off, int auth_len,
447210312Sjmallett    int crypt_off, int crypt_len,
448210312Sjmallett    int icv_off, uint8_t *ivp)
449210312Sjmallett{
450210312Sjmallett    uint64_t *data, *pdata;
451210312Sjmallett    int data_i, data_l;
452210312Sjmallett
453210312Sjmallett    dprintf("%s()\n", __func__);
454210312Sjmallett
455210312Sjmallett    if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
456210312Sjmallett	    (crypt_off & 0x7) || (crypt_off + crypt_len > iovlen))) {
457217620Sgonzo	dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
458210312Sjmallett		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
459210312Sjmallett		"icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
460210312Sjmallett		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
461210312Sjmallett	return -EINVAL;
462210312Sjmallett    }
463210312Sjmallett
464210312Sjmallett    IOV_INIT(iov, data, data_i, data_l);
465210312Sjmallett
466210312Sjmallett    CVMX_PREFETCH0(ivp);
467210312Sjmallett    CVMX_PREFETCH0(od->octo_enckey);
468210312Sjmallett
469210312Sjmallett    /* load AES Key */
470210312Sjmallett    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
471210312Sjmallett    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
472210312Sjmallett
473210312Sjmallett    if (od->octo_encklen == 16) {
474210312Sjmallett	CVMX_MT_AES_KEY(0x0, 2);
475210312Sjmallett	CVMX_MT_AES_KEY(0x0, 3);
476210312Sjmallett    } else if (od->octo_encklen == 24) {
477210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
478210312Sjmallett	CVMX_MT_AES_KEY(0x0, 3);
479210312Sjmallett    } else if (od->octo_encklen == 32) {
480210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
481210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
482210312Sjmallett    } else {
483210312Sjmallett	dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
484210312Sjmallett	return -EINVAL;
485210312Sjmallett    }
486210312Sjmallett    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
487210312Sjmallett
488210312Sjmallett    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
489210312Sjmallett    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
490210312Sjmallett
491210312Sjmallett    while (crypt_off > 0) {
492210312Sjmallett	IOV_CONSUME(iov, data, data_i, data_l);
493210312Sjmallett	crypt_off -= 8;
494210312Sjmallett    }
495210312Sjmallett
496210312Sjmallett    while (crypt_len > 0) {
497210312Sjmallett	pdata = data;
498210312Sjmallett	CVMX_MT_AES_ENC_CBC0(*data);
499210312Sjmallett	IOV_CONSUME(iov, data, data_i, data_l);
500210312Sjmallett	CVMX_MT_AES_ENC_CBC1(*data);
501210312Sjmallett	CVMX_MF_AES_RESULT(*pdata, 0);
502210312Sjmallett	CVMX_MF_AES_RESULT(*data, 1);
503210312Sjmallett	IOV_CONSUME(iov, data, data_i, data_l);
504210312Sjmallett	crypt_len -= 16;
505210312Sjmallett    }
506210312Sjmallett
507210312Sjmallett    return 0;
508210312Sjmallett}
509210312Sjmallett
510210312Sjmallett
511210312Sjmallettint
512210312Sjmallettocto_aes_cbc_decrypt(
513210312Sjmallett    struct octo_sess *od,
514210312Sjmallett    struct iovec *iov, size_t iovcnt, size_t iovlen,
515210312Sjmallett    int auth_off, int auth_len,
516210312Sjmallett    int crypt_off, int crypt_len,
517210312Sjmallett    int icv_off, uint8_t *ivp)
518210312Sjmallett{
519210312Sjmallett    uint64_t *data, *pdata;
520210312Sjmallett    int data_i, data_l;
521210312Sjmallett
522210312Sjmallett    dprintf("%s()\n", __func__);
523210312Sjmallett
524210312Sjmallett    if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
525210312Sjmallett	    (crypt_off & 0x7) || (crypt_off + crypt_len > iovlen))) {
526217620Sgonzo	dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
527210312Sjmallett		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
528210312Sjmallett		"icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
529210312Sjmallett		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
530210312Sjmallett	return -EINVAL;
531210312Sjmallett    }
532210312Sjmallett
533210312Sjmallett    IOV_INIT(iov, data, data_i, data_l);
534210312Sjmallett
535210312Sjmallett    CVMX_PREFETCH0(ivp);
536210312Sjmallett    CVMX_PREFETCH0(od->octo_enckey);
537210312Sjmallett
538210312Sjmallett    /* load AES Key */
539210312Sjmallett    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
540210312Sjmallett    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
541210312Sjmallett
542210312Sjmallett    if (od->octo_encklen == 16) {
543210312Sjmallett	CVMX_MT_AES_KEY(0x0, 2);
544210312Sjmallett	CVMX_MT_AES_KEY(0x0, 3);
545210312Sjmallett    } else if (od->octo_encklen == 24) {
546210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
547210312Sjmallett	CVMX_MT_AES_KEY(0x0, 3);
548210312Sjmallett    } else if (od->octo_encklen == 32) {
549210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
550210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
551210312Sjmallett    } else {
552210312Sjmallett	dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
553210312Sjmallett	return -EINVAL;
554210312Sjmallett    }
555210312Sjmallett    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
556210312Sjmallett
557210312Sjmallett    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
558210312Sjmallett    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
559210312Sjmallett
560210312Sjmallett    while (crypt_off > 0) {
561210312Sjmallett	IOV_CONSUME(iov, data, data_i, data_l);
562210312Sjmallett	crypt_off -= 8;
563210312Sjmallett    }
564210312Sjmallett
565210312Sjmallett    while (crypt_len > 0) {
566210312Sjmallett	pdata = data;
567210312Sjmallett	CVMX_MT_AES_DEC_CBC0(*data);
568210312Sjmallett	IOV_CONSUME(iov, data, data_i, data_l);
569210312Sjmallett	CVMX_MT_AES_DEC_CBC1(*data);
570210312Sjmallett	CVMX_MF_AES_RESULT(*pdata, 0);
571210312Sjmallett	CVMX_MF_AES_RESULT(*data, 1);
572210312Sjmallett	IOV_CONSUME(iov, data, data_i, data_l);
573210312Sjmallett	crypt_len -= 16;
574210312Sjmallett    }
575210312Sjmallett
576210312Sjmallett    return 0;
577210312Sjmallett}
578210312Sjmallett
579210312Sjmallett/****************************************************************************/
580210312Sjmallett/* MD5 */
581210312Sjmallett
582210312Sjmallettint
583210312Sjmallettocto_null_md5_encrypt(
584210312Sjmallett    struct octo_sess *od,
585210312Sjmallett    struct iovec *iov, size_t iovcnt, size_t iovlen,
586210312Sjmallett    int auth_off, int auth_len,
587210312Sjmallett    int crypt_off, int crypt_len,
588210312Sjmallett    int icv_off, uint8_t *ivp)
589210312Sjmallett{
590210312Sjmallett    register int next = 0;
591210312Sjmallett    uint64_t *data;
592210312Sjmallett    uint64_t tmp1, tmp2;
593210312Sjmallett    int data_i, data_l, alen = auth_len;
594210312Sjmallett
595210312Sjmallett    dprintf("%s()\n", __func__);
596210312Sjmallett
597210312Sjmallett    if (__predict_false(od == NULL || iov==NULL || iovlen==0 ||
598210312Sjmallett	    (auth_off & 0x7) || (auth_off + auth_len > iovlen))) {
599217620Sgonzo	dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
600210312Sjmallett		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
601210312Sjmallett		"icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
602210312Sjmallett		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
603210312Sjmallett	return -EINVAL;
604210312Sjmallett    }
605210312Sjmallett
606210312Sjmallett    IOV_INIT(iov, data, data_i, data_l);
607210312Sjmallett
608210312Sjmallett    /* Load MD5 IV */
609210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
610210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
611210312Sjmallett
612210312Sjmallett    while (auth_off > 0) {
613210312Sjmallett	IOV_CONSUME(iov, data, data_i, data_l);
614210312Sjmallett	auth_off -= 8;
615210312Sjmallett    }
616210312Sjmallett
617210312Sjmallett    while (auth_len > 0) {
618210312Sjmallett	CVM_LOAD_MD5_UNIT(*data, next);
619210312Sjmallett	auth_len -= 8;
620210312Sjmallett	IOV_CONSUME(iov, data, data_i, data_l);
621210312Sjmallett    }
622210312Sjmallett
623210312Sjmallett    /* finish the hash */
624210312Sjmallett    CVMX_PREFETCH0(od->octo_hmouter);
625210312Sjmallett#if 0
626210312Sjmallett    if (__predict_false(inplen)) {
627210312Sjmallett	uint64_t tmp = 0;
628210312Sjmallett	uint8_t *p = (uint8_t *) & tmp;
629210312Sjmallett	p[inplen] = 0x80;
630210312Sjmallett	do {
631210312Sjmallett	    inplen--;
632210312Sjmallett	    p[inplen] = ((uint8_t *) data)[inplen];
633210312Sjmallett	} while (inplen);
634210312Sjmallett	CVM_LOAD_MD5_UNIT(tmp, next);
635210312Sjmallett    } else {
636210312Sjmallett	CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
637210312Sjmallett    }
638210312Sjmallett#else
639210312Sjmallett    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
640210312Sjmallett#endif
641210312Sjmallett
642210312Sjmallett    /* Finish Inner hash */
643210312Sjmallett    while (next != 7) {
644210312Sjmallett	CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
645210312Sjmallett    }
646210312Sjmallett    CVMX_ES64(tmp1, ((alen + 64) << 3));
647210312Sjmallett    CVM_LOAD_MD5_UNIT(tmp1, next);
648210312Sjmallett
649210312Sjmallett    /* Get the inner hash of HMAC */
650210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
651210312Sjmallett    CVMX_MF_HSH_IV(tmp2, 1);
652210312Sjmallett
653210312Sjmallett    /* Initialize hash unit */
654210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
655210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
656210312Sjmallett
657210312Sjmallett    CVMX_MT_HSH_DAT(tmp1, 0);
658210312Sjmallett    CVMX_MT_HSH_DAT(tmp2, 1);
659210312Sjmallett    CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
660210312Sjmallett    CVMX_MT_HSH_DATZ(3);
661210312Sjmallett    CVMX_MT_HSH_DATZ(4);
662210312Sjmallett    CVMX_MT_HSH_DATZ(5);
663210312Sjmallett    CVMX_MT_HSH_DATZ(6);
664210312Sjmallett    CVMX_ES64(tmp1, ((64 + 16) << 3));
665210312Sjmallett    CVMX_MT_HSH_STARTMD5(tmp1);
666210312Sjmallett
667210312Sjmallett    /* save the HMAC */
668210312Sjmallett    IOV_INIT(iov, data, data_i, data_l);
669210312Sjmallett    while (icv_off > 0) {
670210312Sjmallett	IOV_CONSUME(iov, data, data_i, data_l);
671210312Sjmallett	icv_off -= 8;
672210312Sjmallett    }
673210312Sjmallett    CVMX_MF_HSH_IV(*data, 0);
674210312Sjmallett    IOV_CONSUME(iov, data, data_i, data_l);
675210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 1);
676210312Sjmallett    *(uint32_t *)data = (uint32_t) (tmp1 >> 32);
677210312Sjmallett
678210312Sjmallett    return 0;
679210312Sjmallett}
680210312Sjmallett
681210312Sjmallett/****************************************************************************/
682210312Sjmallett/* SHA1 */
683210312Sjmallett
684210312Sjmallettint
685210312Sjmallettocto_null_sha1_encrypt(
686210312Sjmallett    struct octo_sess *od,
687210312Sjmallett    struct iovec *iov, size_t iovcnt, size_t iovlen,
688210312Sjmallett    int auth_off, int auth_len,
689210312Sjmallett    int crypt_off, int crypt_len,
690210312Sjmallett    int icv_off, uint8_t *ivp)
691210312Sjmallett{
692210312Sjmallett    register int next = 0;
693210312Sjmallett    uint64_t *data;
694210312Sjmallett    uint64_t tmp1, tmp2, tmp3;
695210312Sjmallett    int data_i, data_l, alen = auth_len;
696210312Sjmallett
697210312Sjmallett    dprintf("%s()\n", __func__);
698210312Sjmallett
699210312Sjmallett    if (__predict_false(od == NULL || iov==NULL || iovlen==0 ||
700210312Sjmallett	    (auth_off & 0x7) || (auth_off + auth_len > iovlen))) {
701217620Sgonzo	dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
702210312Sjmallett		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
703210312Sjmallett		"icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
704210312Sjmallett		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
705210312Sjmallett	return -EINVAL;
706210312Sjmallett    }
707210312Sjmallett
708210312Sjmallett    IOV_INIT(iov, data, data_i, data_l);
709210312Sjmallett
710210312Sjmallett    /* Load SHA1 IV */
711210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
712210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
713210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
714210312Sjmallett
715210312Sjmallett    while (auth_off > 0) {
716210312Sjmallett	IOV_CONSUME(iov, data, data_i, data_l);
717210312Sjmallett	auth_off -= 8;
718210312Sjmallett    }
719210312Sjmallett
720210312Sjmallett    while (auth_len > 0) {
721210312Sjmallett	CVM_LOAD_SHA_UNIT(*data, next);
722210312Sjmallett	auth_len -= 8;
723210312Sjmallett	IOV_CONSUME(iov, data, data_i, data_l);
724210312Sjmallett    }
725210312Sjmallett
726210312Sjmallett    /* finish the hash */
727210312Sjmallett    CVMX_PREFETCH0(od->octo_hmouter);
728210312Sjmallett#if 0
729210312Sjmallett    if (__predict_false(inplen)) {
730210312Sjmallett	uint64_t tmp = 0;
731210312Sjmallett	uint8_t *p = (uint8_t *) & tmp;
732210312Sjmallett	p[inplen] = 0x80;
733210312Sjmallett	do {
734210312Sjmallett	    inplen--;
735210312Sjmallett	    p[inplen] = ((uint8_t *) data)[inplen];
736210312Sjmallett	} while (inplen);
737210312Sjmallett	CVM_LOAD_MD5_UNIT(tmp, next);
738210312Sjmallett    } else {
739210312Sjmallett	CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
740210312Sjmallett    }
741210312Sjmallett#else
742210312Sjmallett    CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
743210312Sjmallett#endif
744210312Sjmallett
745210312Sjmallett    /* Finish Inner hash */
746210312Sjmallett    while (next != 7) {
747210312Sjmallett	CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
748210312Sjmallett    }
749210312Sjmallett	CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
750210312Sjmallett
751210312Sjmallett    /* Get the inner hash of HMAC */
752210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
753210312Sjmallett    CVMX_MF_HSH_IV(tmp2, 1);
754210312Sjmallett    tmp3 = 0;
755210312Sjmallett    CVMX_MF_HSH_IV(tmp3, 2);
756210312Sjmallett
757210312Sjmallett    /* Initialize hash unit */
758210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
759210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
760210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
761210312Sjmallett
762210312Sjmallett    CVMX_MT_HSH_DAT(tmp1, 0);
763210312Sjmallett    CVMX_MT_HSH_DAT(tmp2, 1);
764210312Sjmallett    tmp3 |= 0x0000000080000000;
765210312Sjmallett    CVMX_MT_HSH_DAT(tmp3, 2);
766210312Sjmallett    CVMX_MT_HSH_DATZ(3);
767210312Sjmallett    CVMX_MT_HSH_DATZ(4);
768210312Sjmallett    CVMX_MT_HSH_DATZ(5);
769210312Sjmallett    CVMX_MT_HSH_DATZ(6);
770210312Sjmallett    CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
771210312Sjmallett
772210312Sjmallett    /* save the HMAC */
773210312Sjmallett    IOV_INIT(iov, data, data_i, data_l);
774210312Sjmallett    while (icv_off > 0) {
775210312Sjmallett	IOV_CONSUME(iov, data, data_i, data_l);
776210312Sjmallett	icv_off -= 8;
777210312Sjmallett    }
778210312Sjmallett    CVMX_MF_HSH_IV(*data, 0);
779210312Sjmallett    IOV_CONSUME(iov, data, data_i, data_l);
780210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 1);
781210312Sjmallett    *(uint32_t *)data = (uint32_t) (tmp1 >> 32);
782210312Sjmallett
783210312Sjmallett    return 0;
784210312Sjmallett}
785210312Sjmallett
786210312Sjmallett/****************************************************************************/
787210312Sjmallett/* DES MD5 */
788210312Sjmallett
789210312Sjmallettint
790210312Sjmallettocto_des_cbc_md5_encrypt(
791210312Sjmallett    struct octo_sess *od,
792210312Sjmallett    struct iovec *iov, size_t iovcnt, size_t iovlen,
793210312Sjmallett    int auth_off, int auth_len,
794210312Sjmallett    int crypt_off, int crypt_len,
795210312Sjmallett    int icv_off, uint8_t *ivp)
796210312Sjmallett{
797210312Sjmallett    register int next = 0;
798210312Sjmallett    union {
799210312Sjmallett	uint32_t data32[2];
800210312Sjmallett	uint64_t data64[1];
801210312Sjmallett    } mydata;
802210312Sjmallett    uint64_t *data = &mydata.data64[0];
803210312Sjmallett    uint32_t *data32;
804210312Sjmallett    uint64_t tmp1, tmp2;
805210312Sjmallett    int data_i, data_l, alen = auth_len;
806210312Sjmallett
807210312Sjmallett    dprintf("%s()\n", __func__);
808210312Sjmallett
809210312Sjmallett    if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
810210312Sjmallett	    (crypt_off & 0x3) || (crypt_off + crypt_len > iovlen) ||
811210312Sjmallett	    (crypt_len  & 0x7) ||
812210312Sjmallett	    (auth_len  & 0x7) ||
813210312Sjmallett	    (auth_off & 0x3) || (auth_off + auth_len > iovlen))) {
814217620Sgonzo	dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
815210312Sjmallett		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
816210312Sjmallett		"icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
817210312Sjmallett		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
818210312Sjmallett	return -EINVAL;
819210312Sjmallett    }
820210312Sjmallett
821210312Sjmallett    IOV_INIT(iov, data32, data_i, data_l);
822210312Sjmallett
823210312Sjmallett    CVMX_PREFETCH0(ivp);
824210312Sjmallett    CVMX_PREFETCH0(od->octo_enckey);
825210312Sjmallett
826210312Sjmallett    /* load 3DES Key */
827210312Sjmallett    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
828210312Sjmallett    if (od->octo_encklen == 24) {
829210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
830210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
831210312Sjmallett    } else if (od->octo_encklen == 8) {
832210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
833210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
834210312Sjmallett    } else {
835210312Sjmallett	dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
836210312Sjmallett	return -EINVAL;
837210312Sjmallett    }
838210312Sjmallett
839210312Sjmallett    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
840210312Sjmallett
841210312Sjmallett    /* Load MD5 IV */
842210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
843210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
844210312Sjmallett
845210312Sjmallett    while (crypt_off > 0 && auth_off > 0) {
846210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
847210312Sjmallett	crypt_off -= 4;
848210312Sjmallett	auth_off -= 4;
849210312Sjmallett    }
850210312Sjmallett
851210312Sjmallett    while (crypt_len > 0 || auth_len > 0) {
852210312Sjmallett    	uint32_t *first = data32;
853210312Sjmallett	mydata.data32[0] = *first;
854210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
855210312Sjmallett	mydata.data32[1] = *data32;
856210312Sjmallett    	if (crypt_off <= 0) {
857210312Sjmallett	    if (crypt_len > 0) {
858210312Sjmallett		CVMX_MT_3DES_ENC_CBC(*data);
859210312Sjmallett		CVMX_MF_3DES_RESULT(*data);
860210312Sjmallett		crypt_len -= 8;
861210312Sjmallett	    }
862210312Sjmallett	} else
863210312Sjmallett	    crypt_off -= 8;
864210312Sjmallett    	if (auth_off <= 0) {
865210312Sjmallett	    if (auth_len > 0) {
866210312Sjmallett		CVM_LOAD_MD5_UNIT(*data, next);
867210312Sjmallett		auth_len -= 8;
868210312Sjmallett	    }
869210312Sjmallett	} else
870210312Sjmallett	    auth_off -= 8;
871210312Sjmallett	*first = mydata.data32[0];
872210312Sjmallett	*data32 = mydata.data32[1];
873210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
874210312Sjmallett    }
875210312Sjmallett
876210312Sjmallett    /* finish the hash */
877210312Sjmallett    CVMX_PREFETCH0(od->octo_hmouter);
878210312Sjmallett#if 0
879210312Sjmallett    if (__predict_false(inplen)) {
880210312Sjmallett	uint64_t tmp = 0;
881210312Sjmallett	uint8_t *p = (uint8_t *) & tmp;
882210312Sjmallett	p[inplen] = 0x80;
883210312Sjmallett	do {
884210312Sjmallett	    inplen--;
885210312Sjmallett	    p[inplen] = ((uint8_t *) data)[inplen];
886210312Sjmallett	} while (inplen);
887210312Sjmallett	CVM_LOAD_MD5_UNIT(tmp, next);
888210312Sjmallett    } else {
889210312Sjmallett	CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
890210312Sjmallett    }
891210312Sjmallett#else
892210312Sjmallett    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
893210312Sjmallett#endif
894210312Sjmallett
895210312Sjmallett    /* Finish Inner hash */
896210312Sjmallett    while (next != 7) {
897210312Sjmallett	CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
898210312Sjmallett    }
899210312Sjmallett    CVMX_ES64(tmp1, ((alen + 64) << 3));
900210312Sjmallett    CVM_LOAD_MD5_UNIT(tmp1, next);
901210312Sjmallett
902210312Sjmallett    /* Get the inner hash of HMAC */
903210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
904210312Sjmallett    CVMX_MF_HSH_IV(tmp2, 1);
905210312Sjmallett
906210312Sjmallett    /* Initialize hash unit */
907210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
908210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
909210312Sjmallett
910210312Sjmallett    CVMX_MT_HSH_DAT(tmp1, 0);
911210312Sjmallett    CVMX_MT_HSH_DAT(tmp2, 1);
912210312Sjmallett    CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
913210312Sjmallett    CVMX_MT_HSH_DATZ(3);
914210312Sjmallett    CVMX_MT_HSH_DATZ(4);
915210312Sjmallett    CVMX_MT_HSH_DATZ(5);
916210312Sjmallett    CVMX_MT_HSH_DATZ(6);
917210312Sjmallett    CVMX_ES64(tmp1, ((64 + 16) << 3));
918210312Sjmallett    CVMX_MT_HSH_STARTMD5(tmp1);
919210312Sjmallett
920210312Sjmallett    /* save the HMAC */
921210312Sjmallett    IOV_INIT(iov, data32, data_i, data_l);
922210312Sjmallett    while (icv_off > 0) {
923210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
924210312Sjmallett	icv_off -= 4;
925210312Sjmallett    }
926210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
927210312Sjmallett    *data32 = (uint32_t) (tmp1 >> 32);
928210312Sjmallett    IOV_CONSUME(iov, data32, data_i, data_l);
929210312Sjmallett    *data32 = (uint32_t) tmp1;
930210312Sjmallett    IOV_CONSUME(iov, data32, data_i, data_l);
931210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 1);
932210312Sjmallett    *data32 = (uint32_t) (tmp1 >> 32);
933210312Sjmallett
934210312Sjmallett    return 0;
935210312Sjmallett}
936210312Sjmallett
937210312Sjmallettint
938210312Sjmallettocto_des_cbc_md5_decrypt(
939210312Sjmallett    struct octo_sess *od,
940210312Sjmallett    struct iovec *iov, size_t iovcnt, size_t iovlen,
941210312Sjmallett    int auth_off, int auth_len,
942210312Sjmallett    int crypt_off, int crypt_len,
943210312Sjmallett    int icv_off, uint8_t *ivp)
944210312Sjmallett{
945210312Sjmallett    register int next = 0;
946210312Sjmallett    union {
947210312Sjmallett	uint32_t data32[2];
948210312Sjmallett	uint64_t data64[1];
949210312Sjmallett    } mydata;
950210312Sjmallett    uint64_t *data = &mydata.data64[0];
951210312Sjmallett    uint32_t *data32;
952210312Sjmallett    uint64_t tmp1, tmp2;
953210312Sjmallett    int data_i, data_l, alen = auth_len;
954210312Sjmallett
955210312Sjmallett    dprintf("%s()\n", __func__);
956210312Sjmallett
957210312Sjmallett    if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
958210312Sjmallett	    (crypt_off & 0x3) || (crypt_off + crypt_len > iovlen) ||
959210312Sjmallett	    (crypt_len  & 0x7) ||
960210312Sjmallett	    (auth_len  & 0x7) ||
961210312Sjmallett	    (auth_off & 0x3) || (auth_off + auth_len > iovlen))) {
962217620Sgonzo	dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
963210312Sjmallett		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
964210312Sjmallett		"icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
965210312Sjmallett		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
966210312Sjmallett	return -EINVAL;
967210312Sjmallett    }
968210312Sjmallett
969210312Sjmallett    IOV_INIT(iov, data32, data_i, data_l);
970210312Sjmallett
971210312Sjmallett    CVMX_PREFETCH0(ivp);
972210312Sjmallett    CVMX_PREFETCH0(od->octo_enckey);
973210312Sjmallett
974210312Sjmallett    /* load 3DES Key */
975210312Sjmallett    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
976210312Sjmallett    if (od->octo_encklen == 24) {
977210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
978210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
979210312Sjmallett    } else if (od->octo_encklen == 8) {
980210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
981210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
982210312Sjmallett    } else {
983210312Sjmallett	dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
984210312Sjmallett	return -EINVAL;
985210312Sjmallett    }
986210312Sjmallett
987210312Sjmallett    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
988210312Sjmallett
989210312Sjmallett    /* Load MD5 IV */
990210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
991210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
992210312Sjmallett
993210312Sjmallett    while (crypt_off > 0 && auth_off > 0) {
994210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
995210312Sjmallett	crypt_off -= 4;
996210312Sjmallett	auth_off -= 4;
997210312Sjmallett    }
998210312Sjmallett
999210312Sjmallett    while (crypt_len > 0 || auth_len > 0) {
1000210312Sjmallett    	uint32_t *first = data32;
1001210312Sjmallett	mydata.data32[0] = *first;
1002210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1003210312Sjmallett	mydata.data32[1] = *data32;
1004210312Sjmallett    	if (auth_off <= 0) {
1005210312Sjmallett	    if (auth_len > 0) {
1006210312Sjmallett		CVM_LOAD_MD5_UNIT(*data, next);
1007210312Sjmallett		auth_len -= 8;
1008210312Sjmallett	    }
1009210312Sjmallett	} else
1010210312Sjmallett	    auth_off -= 8;
1011210312Sjmallett    	if (crypt_off <= 0) {
1012210312Sjmallett	    if (crypt_len > 0) {
1013210312Sjmallett		CVMX_MT_3DES_DEC_CBC(*data);
1014210312Sjmallett		CVMX_MF_3DES_RESULT(*data);
1015210312Sjmallett		crypt_len -= 8;
1016210312Sjmallett	    }
1017210312Sjmallett	} else
1018210312Sjmallett	    crypt_off -= 8;
1019210312Sjmallett	*first = mydata.data32[0];
1020210312Sjmallett	*data32 = mydata.data32[1];
1021210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1022210312Sjmallett    }
1023210312Sjmallett
1024210312Sjmallett    /* finish the hash */
1025210312Sjmallett    CVMX_PREFETCH0(od->octo_hmouter);
1026210312Sjmallett#if 0
1027210312Sjmallett    if (__predict_false(inplen)) {
1028210312Sjmallett	uint64_t tmp = 0;
1029210312Sjmallett	uint8_t *p = (uint8_t *) & tmp;
1030210312Sjmallett	p[inplen] = 0x80;
1031210312Sjmallett	do {
1032210312Sjmallett	    inplen--;
1033210312Sjmallett	    p[inplen] = ((uint8_t *) data)[inplen];
1034210312Sjmallett	} while (inplen);
1035210312Sjmallett	CVM_LOAD_MD5_UNIT(tmp, next);
1036210312Sjmallett    } else {
1037210312Sjmallett	CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
1038210312Sjmallett    }
1039210312Sjmallett#else
1040210312Sjmallett    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
1041210312Sjmallett#endif
1042210312Sjmallett
1043210312Sjmallett    /* Finish Inner hash */
1044210312Sjmallett    while (next != 7) {
1045210312Sjmallett	CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
1046210312Sjmallett    }
1047210312Sjmallett    CVMX_ES64(tmp1, ((alen + 64) << 3));
1048210312Sjmallett    CVM_LOAD_MD5_UNIT(tmp1, next);
1049210312Sjmallett
1050210312Sjmallett    /* Get the inner hash of HMAC */
1051210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
1052210312Sjmallett    CVMX_MF_HSH_IV(tmp2, 1);
1053210312Sjmallett
1054210312Sjmallett    /* Initialize hash unit */
1055210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
1056210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
1057210312Sjmallett
1058210312Sjmallett    CVMX_MT_HSH_DAT(tmp1, 0);
1059210312Sjmallett    CVMX_MT_HSH_DAT(tmp2, 1);
1060210312Sjmallett    CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
1061210312Sjmallett    CVMX_MT_HSH_DATZ(3);
1062210312Sjmallett    CVMX_MT_HSH_DATZ(4);
1063210312Sjmallett    CVMX_MT_HSH_DATZ(5);
1064210312Sjmallett    CVMX_MT_HSH_DATZ(6);
1065210312Sjmallett    CVMX_ES64(tmp1, ((64 + 16) << 3));
1066210312Sjmallett    CVMX_MT_HSH_STARTMD5(tmp1);
1067210312Sjmallett
1068210312Sjmallett    /* save the HMAC */
1069210312Sjmallett    IOV_INIT(iov, data32, data_i, data_l);
1070210312Sjmallett    while (icv_off > 0) {
1071210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1072210312Sjmallett	icv_off -= 4;
1073210312Sjmallett    }
1074210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
1075210312Sjmallett    *data32 = (uint32_t) (tmp1 >> 32);
1076210312Sjmallett    IOV_CONSUME(iov, data32, data_i, data_l);
1077210312Sjmallett    *data32 = (uint32_t) tmp1;
1078210312Sjmallett    IOV_CONSUME(iov, data32, data_i, data_l);
1079210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 1);
1080210312Sjmallett    *data32 = (uint32_t) (tmp1 >> 32);
1081210312Sjmallett
1082210312Sjmallett    return 0;
1083210312Sjmallett}
1084210312Sjmallett
1085210312Sjmallett/****************************************************************************/
1086210312Sjmallett/* DES SHA */
1087210312Sjmallett
1088210312Sjmallettint
1089210312Sjmallettocto_des_cbc_sha1_encrypt(
1090210312Sjmallett    struct octo_sess *od,
1091210312Sjmallett    struct iovec *iov, size_t iovcnt, size_t iovlen,
1092210312Sjmallett    int auth_off, int auth_len,
1093210312Sjmallett    int crypt_off, int crypt_len,
1094210312Sjmallett    int icv_off, uint8_t *ivp)
1095210312Sjmallett{
1096210312Sjmallett    register int next = 0;
1097210312Sjmallett    union {
1098210312Sjmallett	uint32_t data32[2];
1099210312Sjmallett	uint64_t data64[1];
1100210312Sjmallett    } mydata;
1101210312Sjmallett    uint64_t *data = &mydata.data64[0];
1102210312Sjmallett    uint32_t *data32;
1103210312Sjmallett    uint64_t tmp1, tmp2, tmp3;
1104210312Sjmallett    int data_i, data_l, alen = auth_len;
1105210312Sjmallett
1106210312Sjmallett    dprintf("%s()\n", __func__);
1107210312Sjmallett
1108210312Sjmallett    if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
1109210312Sjmallett	    (crypt_off & 0x3) || (crypt_off + crypt_len > iovlen) ||
1110210312Sjmallett	    (crypt_len  & 0x7) ||
1111210312Sjmallett	    (auth_len  & 0x7) ||
1112210312Sjmallett	    (auth_off & 0x3) || (auth_off + auth_len > iovlen))) {
1113217620Sgonzo	dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
1114210312Sjmallett		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
1115210312Sjmallett		"icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
1116210312Sjmallett		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
1117210312Sjmallett	return -EINVAL;
1118210312Sjmallett    }
1119210312Sjmallett
1120210312Sjmallett    IOV_INIT(iov, data32, data_i, data_l);
1121210312Sjmallett
1122210312Sjmallett    CVMX_PREFETCH0(ivp);
1123210312Sjmallett    CVMX_PREFETCH0(od->octo_enckey);
1124210312Sjmallett
1125210312Sjmallett    /* load 3DES Key */
1126210312Sjmallett    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
1127210312Sjmallett    if (od->octo_encklen == 24) {
1128210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
1129210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1130210312Sjmallett    } else if (od->octo_encklen == 8) {
1131210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
1132210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
1133210312Sjmallett    } else {
1134210312Sjmallett	dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
1135210312Sjmallett	return -EINVAL;
1136210312Sjmallett    }
1137210312Sjmallett
1138210312Sjmallett    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
1139210312Sjmallett
1140210312Sjmallett    /* Load SHA1 IV */
1141210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
1142210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
1143210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
1144210312Sjmallett
1145210312Sjmallett    while (crypt_off > 0 && auth_off > 0) {
1146210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1147210312Sjmallett	crypt_off -= 4;
1148210312Sjmallett	auth_off -= 4;
1149210312Sjmallett    }
1150210312Sjmallett
1151210312Sjmallett    while (crypt_len > 0 || auth_len > 0) {
1152210312Sjmallett    	uint32_t *first = data32;
1153210312Sjmallett	mydata.data32[0] = *first;
1154210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1155210312Sjmallett	mydata.data32[1] = *data32;
1156210312Sjmallett    	if (crypt_off <= 0) {
1157210312Sjmallett	    if (crypt_len > 0) {
1158210312Sjmallett		CVMX_MT_3DES_ENC_CBC(*data);
1159210312Sjmallett		CVMX_MF_3DES_RESULT(*data);
1160210312Sjmallett		crypt_len -= 8;
1161210312Sjmallett	    }
1162210312Sjmallett	} else
1163210312Sjmallett	    crypt_off -= 8;
1164210312Sjmallett    	if (auth_off <= 0) {
1165210312Sjmallett	    if (auth_len > 0) {
1166210312Sjmallett		CVM_LOAD_SHA_UNIT(*data, next);
1167210312Sjmallett		auth_len -= 8;
1168210312Sjmallett	    }
1169210312Sjmallett	} else
1170210312Sjmallett	    auth_off -= 8;
1171210312Sjmallett	*first = mydata.data32[0];
1172210312Sjmallett	*data32 = mydata.data32[1];
1173210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1174210312Sjmallett    }
1175210312Sjmallett
1176210312Sjmallett    /* finish the hash */
1177210312Sjmallett    CVMX_PREFETCH0(od->octo_hmouter);
1178210312Sjmallett#if 0
1179210312Sjmallett    if (__predict_false(inplen)) {
1180210312Sjmallett	uint64_t tmp = 0;
1181210312Sjmallett	uint8_t *p = (uint8_t *) & tmp;
1182210312Sjmallett	p[inplen] = 0x80;
1183210312Sjmallett	do {
1184210312Sjmallett	    inplen--;
1185210312Sjmallett	    p[inplen] = ((uint8_t *) data)[inplen];
1186210312Sjmallett	} while (inplen);
1187210312Sjmallett	CVM_LOAD_SHA_UNIT(tmp, next);
1188210312Sjmallett    } else {
1189210312Sjmallett	CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
1190210312Sjmallett    }
1191210312Sjmallett#else
1192210312Sjmallett    CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
1193210312Sjmallett#endif
1194210312Sjmallett
1195210312Sjmallett    /* Finish Inner hash */
1196210312Sjmallett    while (next != 7) {
1197210312Sjmallett	CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
1198210312Sjmallett    }
1199210312Sjmallett	CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
1200210312Sjmallett
1201210312Sjmallett    /* Get the inner hash of HMAC */
1202210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
1203210312Sjmallett    CVMX_MF_HSH_IV(tmp2, 1);
1204210312Sjmallett    tmp3 = 0;
1205210312Sjmallett    CVMX_MF_HSH_IV(tmp3, 2);
1206210312Sjmallett
1207210312Sjmallett    /* Initialize hash unit */
1208210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
1209210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
1210210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
1211210312Sjmallett
1212210312Sjmallett    CVMX_MT_HSH_DAT(tmp1, 0);
1213210312Sjmallett    CVMX_MT_HSH_DAT(tmp2, 1);
1214210312Sjmallett    tmp3 |= 0x0000000080000000;
1215210312Sjmallett    CVMX_MT_HSH_DAT(tmp3, 2);
1216210312Sjmallett    CVMX_MT_HSH_DATZ(3);
1217210312Sjmallett    CVMX_MT_HSH_DATZ(4);
1218210312Sjmallett    CVMX_MT_HSH_DATZ(5);
1219210312Sjmallett    CVMX_MT_HSH_DATZ(6);
1220210312Sjmallett    CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
1221210312Sjmallett
1222210312Sjmallett    /* save the HMAC */
1223210312Sjmallett    IOV_INIT(iov, data32, data_i, data_l);
1224210312Sjmallett    while (icv_off > 0) {
1225210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1226210312Sjmallett	icv_off -= 4;
1227210312Sjmallett    }
1228210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
1229210312Sjmallett    *data32 = (uint32_t) (tmp1 >> 32);
1230210312Sjmallett    IOV_CONSUME(iov, data32, data_i, data_l);
1231210312Sjmallett    *data32 = (uint32_t) tmp1;
1232210312Sjmallett    IOV_CONSUME(iov, data32, data_i, data_l);
1233210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 1);
1234210312Sjmallett    *data32 = (uint32_t) (tmp1 >> 32);
1235210312Sjmallett
1236210312Sjmallett    return 0;
1237210312Sjmallett}
1238210312Sjmallett
1239210312Sjmallettint
1240210312Sjmallettocto_des_cbc_sha1_decrypt(
1241210312Sjmallett    struct octo_sess *od,
1242210312Sjmallett    struct iovec *iov, size_t iovcnt, size_t iovlen,
1243210312Sjmallett    int auth_off, int auth_len,
1244210312Sjmallett    int crypt_off, int crypt_len,
1245210312Sjmallett    int icv_off, uint8_t *ivp)
1246210312Sjmallett{
1247210312Sjmallett    register int next = 0;
1248210312Sjmallett    union {
1249210312Sjmallett	uint32_t data32[2];
1250210312Sjmallett	uint64_t data64[1];
1251210312Sjmallett    } mydata;
1252210312Sjmallett    uint64_t *data = &mydata.data64[0];
1253210312Sjmallett    uint32_t *data32;
1254210312Sjmallett    uint64_t tmp1, tmp2, tmp3;
1255210312Sjmallett    int data_i, data_l, alen = auth_len;
1256210312Sjmallett
1257210312Sjmallett    dprintf("%s()\n", __func__);
1258210312Sjmallett
1259210312Sjmallett    if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
1260210312Sjmallett	    (crypt_off & 0x3) || (crypt_off + crypt_len > iovlen) ||
1261210312Sjmallett	    (crypt_len  & 0x7) ||
1262210312Sjmallett	    (auth_len  & 0x7) ||
1263210312Sjmallett	    (auth_off & 0x3) || (auth_off + auth_len > iovlen))) {
1264217620Sgonzo	dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
1265210312Sjmallett		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
1266210312Sjmallett		"icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
1267210312Sjmallett		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
1268210312Sjmallett	return -EINVAL;
1269210312Sjmallett    }
1270210312Sjmallett
1271210312Sjmallett    IOV_INIT(iov, data32, data_i, data_l);
1272210312Sjmallett
1273210312Sjmallett    CVMX_PREFETCH0(ivp);
1274210312Sjmallett    CVMX_PREFETCH0(od->octo_enckey);
1275210312Sjmallett
1276210312Sjmallett    /* load 3DES Key */
1277210312Sjmallett    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
1278210312Sjmallett    if (od->octo_encklen == 24) {
1279210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
1280210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1281210312Sjmallett    } else if (od->octo_encklen == 8) {
1282210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
1283210312Sjmallett	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
1284210312Sjmallett    } else {
1285210312Sjmallett	dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
1286210312Sjmallett	return -EINVAL;
1287210312Sjmallett    }
1288210312Sjmallett
1289210312Sjmallett    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
1290210312Sjmallett
1291210312Sjmallett    /* Load SHA1 IV */
1292210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
1293210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
1294210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
1295210312Sjmallett
1296210312Sjmallett    while (crypt_off > 0 && auth_off > 0) {
1297210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1298210312Sjmallett	crypt_off -= 4;
1299210312Sjmallett	auth_off -= 4;
1300210312Sjmallett    }
1301210312Sjmallett
1302210312Sjmallett    while (crypt_len > 0 || auth_len > 0) {
1303210312Sjmallett    	uint32_t *first = data32;
1304210312Sjmallett	mydata.data32[0] = *first;
1305210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1306210312Sjmallett	mydata.data32[1] = *data32;
1307210312Sjmallett    	if (auth_off <= 0) {
1308210312Sjmallett	    if (auth_len > 0) {
1309210312Sjmallett		CVM_LOAD_SHA_UNIT(*data, next);
1310210312Sjmallett		auth_len -= 8;
1311210312Sjmallett	    }
1312210312Sjmallett	} else
1313210312Sjmallett	    auth_off -= 8;
1314210312Sjmallett    	if (crypt_off <= 0) {
1315210312Sjmallett	    if (crypt_len > 0) {
1316210312Sjmallett		CVMX_MT_3DES_DEC_CBC(*data);
1317210312Sjmallett		CVMX_MF_3DES_RESULT(*data);
1318210312Sjmallett		crypt_len -= 8;
1319210312Sjmallett	    }
1320210312Sjmallett	} else
1321210312Sjmallett	    crypt_off -= 8;
1322210312Sjmallett	*first = mydata.data32[0];
1323210312Sjmallett	*data32 = mydata.data32[1];
1324210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1325210312Sjmallett    }
1326210312Sjmallett
1327210312Sjmallett    /* finish the hash */
1328210312Sjmallett    CVMX_PREFETCH0(od->octo_hmouter);
1329210312Sjmallett#if 0
1330210312Sjmallett    if (__predict_false(inplen)) {
1331210312Sjmallett	uint64_t tmp = 0;
1332210312Sjmallett	uint8_t *p = (uint8_t *) & tmp;
1333210312Sjmallett	p[inplen] = 0x80;
1334210312Sjmallett	do {
1335210312Sjmallett	    inplen--;
1336210312Sjmallett	    p[inplen] = ((uint8_t *) data)[inplen];
1337210312Sjmallett	} while (inplen);
1338210312Sjmallett	CVM_LOAD_SHA_UNIT(tmp, next);
1339210312Sjmallett    } else {
1340210312Sjmallett	CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
1341210312Sjmallett    }
1342210312Sjmallett#else
1343210312Sjmallett    CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
1344210312Sjmallett#endif
1345210312Sjmallett
1346210312Sjmallett    /* Finish Inner hash */
1347210312Sjmallett    while (next != 7) {
1348210312Sjmallett	CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
1349210312Sjmallett    }
1350210312Sjmallett	CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
1351210312Sjmallett
1352210312Sjmallett    /* Get the inner hash of HMAC */
1353210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
1354210312Sjmallett    CVMX_MF_HSH_IV(tmp2, 1);
1355210312Sjmallett    tmp3 = 0;
1356210312Sjmallett    CVMX_MF_HSH_IV(tmp3, 2);
1357210312Sjmallett
1358210312Sjmallett    /* Initialize hash unit */
1359210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
1360210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
1361210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
1362210312Sjmallett
1363210312Sjmallett    CVMX_MT_HSH_DAT(tmp1, 0);
1364210312Sjmallett    CVMX_MT_HSH_DAT(tmp2, 1);
1365210312Sjmallett    tmp3 |= 0x0000000080000000;
1366210312Sjmallett    CVMX_MT_HSH_DAT(tmp3, 2);
1367210312Sjmallett    CVMX_MT_HSH_DATZ(3);
1368210312Sjmallett    CVMX_MT_HSH_DATZ(4);
1369210312Sjmallett    CVMX_MT_HSH_DATZ(5);
1370210312Sjmallett    CVMX_MT_HSH_DATZ(6);
1371210312Sjmallett    CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
1372210312Sjmallett    /* save the HMAC */
1373210312Sjmallett    IOV_INIT(iov, data32, data_i, data_l);
1374210312Sjmallett    while (icv_off > 0) {
1375210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1376210312Sjmallett	icv_off -= 4;
1377210312Sjmallett    }
1378210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
1379210312Sjmallett    *data32 = (uint32_t) (tmp1 >> 32);
1380210312Sjmallett    IOV_CONSUME(iov, data32, data_i, data_l);
1381210312Sjmallett    *data32 = (uint32_t) tmp1;
1382210312Sjmallett    IOV_CONSUME(iov, data32, data_i, data_l);
1383210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 1);
1384210312Sjmallett    *data32 = (uint32_t) (tmp1 >> 32);
1385210312Sjmallett
1386210312Sjmallett    return 0;
1387210312Sjmallett}
1388210312Sjmallett
1389210312Sjmallett/****************************************************************************/
1390210312Sjmallett/* AES MD5 */
1391210312Sjmallett
1392210312Sjmallettint
1393210312Sjmallettocto_aes_cbc_md5_encrypt(
1394210312Sjmallett    struct octo_sess *od,
1395210312Sjmallett    struct iovec *iov, size_t iovcnt, size_t iovlen,
1396210312Sjmallett    int auth_off, int auth_len,
1397210312Sjmallett    int crypt_off, int crypt_len,
1398210312Sjmallett    int icv_off, uint8_t *ivp)
1399210312Sjmallett{
1400210312Sjmallett    register int next = 0;
1401210312Sjmallett    union {
1402210312Sjmallett	uint32_t data32[2];
1403210312Sjmallett	uint64_t data64[1];
1404210312Sjmallett    } mydata[2];
1405210312Sjmallett    uint64_t *pdata = &mydata[0].data64[0];
1406210312Sjmallett    uint64_t *data =  &mydata[1].data64[0];
1407210312Sjmallett    uint32_t *data32;
1408210312Sjmallett    uint64_t tmp1, tmp2;
1409210312Sjmallett    int data_i, data_l, alen = auth_len;
1410210312Sjmallett
1411210312Sjmallett    dprintf("%s()\n", __func__);
1412210312Sjmallett
1413210312Sjmallett    if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
1414210312Sjmallett	    (crypt_off & 0x3) || (crypt_off + crypt_len > iovlen) ||
1415210312Sjmallett	    (crypt_len  & 0x7) ||
1416210312Sjmallett	    (auth_len  & 0x7) ||
1417210312Sjmallett	    (auth_off & 0x3) || (auth_off + auth_len > iovlen))) {
1418217620Sgonzo	dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
1419210312Sjmallett		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
1420210312Sjmallett		"icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
1421210312Sjmallett		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
1422210312Sjmallett	return -EINVAL;
1423210312Sjmallett    }
1424210312Sjmallett
1425210312Sjmallett    IOV_INIT(iov, data32, data_i, data_l);
1426210312Sjmallett
1427210312Sjmallett    CVMX_PREFETCH0(ivp);
1428210312Sjmallett    CVMX_PREFETCH0(od->octo_enckey);
1429210312Sjmallett
1430210312Sjmallett    /* load AES Key */
1431210312Sjmallett    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
1432210312Sjmallett    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
1433210312Sjmallett
1434210312Sjmallett    if (od->octo_encklen == 16) {
1435210312Sjmallett	CVMX_MT_AES_KEY(0x0, 2);
1436210312Sjmallett	CVMX_MT_AES_KEY(0x0, 3);
1437210312Sjmallett    } else if (od->octo_encklen == 24) {
1438210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1439210312Sjmallett	CVMX_MT_AES_KEY(0x0, 3);
1440210312Sjmallett    } else if (od->octo_encklen == 32) {
1441210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1442210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
1443210312Sjmallett    } else {
1444210312Sjmallett	dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
1445210312Sjmallett	return -EINVAL;
1446210312Sjmallett    }
1447210312Sjmallett    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
1448210312Sjmallett
1449210312Sjmallett    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
1450210312Sjmallett    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
1451210312Sjmallett
1452210312Sjmallett    /* Load MD5 IV */
1453210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
1454210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
1455210312Sjmallett
1456210312Sjmallett    while (crypt_off > 0 && auth_off > 0) {
1457210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1458210312Sjmallett	crypt_off -= 4;
1459210312Sjmallett	auth_off -= 4;
1460210312Sjmallett    }
1461210312Sjmallett
1462210312Sjmallett    while (crypt_len > 0 || auth_len > 0) {
1463210312Sjmallett    	uint32_t *pdata32[3];
1464210312Sjmallett
1465210312Sjmallett	pdata32[0] = data32;
1466210312Sjmallett	mydata[0].data32[0] = *data32;
1467210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1468210312Sjmallett
1469210312Sjmallett	pdata32[1] = data32;
1470210312Sjmallett	mydata[0].data32[1] = *data32;
1471210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1472210312Sjmallett
1473210312Sjmallett	pdata32[2] = data32;
1474210312Sjmallett	mydata[1].data32[0] = *data32;
1475210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1476210312Sjmallett
1477210312Sjmallett	mydata[1].data32[1] = *data32;
1478210312Sjmallett
1479210312Sjmallett
1480210312Sjmallett    	if (crypt_off <= 0) {
1481210312Sjmallett	    if (crypt_len > 0) {
1482210312Sjmallett		CVMX_MT_AES_ENC_CBC0(*pdata);
1483210312Sjmallett		CVMX_MT_AES_ENC_CBC1(*data);
1484210312Sjmallett		CVMX_MF_AES_RESULT(*pdata, 0);
1485210312Sjmallett		CVMX_MF_AES_RESULT(*data, 1);
1486210312Sjmallett		crypt_len -= 16;
1487210312Sjmallett	    }
1488210312Sjmallett	} else
1489210312Sjmallett	    crypt_off -= 16;
1490210312Sjmallett
1491210312Sjmallett    	if (auth_off <= 0) {
1492210312Sjmallett	    if (auth_len > 0) {
1493210312Sjmallett		CVM_LOAD_MD5_UNIT(*pdata, next);
1494210312Sjmallett		CVM_LOAD_MD5_UNIT(*data, next);
1495210312Sjmallett		auth_len -= 16;
1496210312Sjmallett	    }
1497210312Sjmallett	} else
1498210312Sjmallett	    auth_off -= 16;
1499210312Sjmallett
1500210312Sjmallett	*pdata32[0] = mydata[0].data32[0];
1501210312Sjmallett	*pdata32[1] = mydata[0].data32[1];
1502210312Sjmallett	*pdata32[2] = mydata[1].data32[0];
1503210312Sjmallett	*data32     = mydata[1].data32[1];
1504210312Sjmallett
1505210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1506210312Sjmallett    }
1507210312Sjmallett
1508210312Sjmallett    /* finish the hash */
1509210312Sjmallett    CVMX_PREFETCH0(od->octo_hmouter);
1510210312Sjmallett#if 0
1511210312Sjmallett    if (__predict_false(inplen)) {
1512210312Sjmallett	uint64_t tmp = 0;
1513210312Sjmallett	uint8_t *p = (uint8_t *) & tmp;
1514210312Sjmallett	p[inplen] = 0x80;
1515210312Sjmallett	do {
1516210312Sjmallett	    inplen--;
1517210312Sjmallett	    p[inplen] = ((uint8_t *) data)[inplen];
1518210312Sjmallett	} while (inplen);
1519210312Sjmallett	CVM_LOAD_MD5_UNIT(tmp, next);
1520210312Sjmallett    } else {
1521210312Sjmallett	CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
1522210312Sjmallett    }
1523210312Sjmallett#else
1524210312Sjmallett    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
1525210312Sjmallett#endif
1526210312Sjmallett
1527210312Sjmallett    /* Finish Inner hash */
1528210312Sjmallett    while (next != 7) {
1529210312Sjmallett	CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
1530210312Sjmallett    }
1531210312Sjmallett    CVMX_ES64(tmp1, ((alen + 64) << 3));
1532210312Sjmallett    CVM_LOAD_MD5_UNIT(tmp1, next);
1533210312Sjmallett
1534210312Sjmallett    /* Get the inner hash of HMAC */
1535210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
1536210312Sjmallett    CVMX_MF_HSH_IV(tmp2, 1);
1537210312Sjmallett
1538210312Sjmallett    /* Initialize hash unit */
1539210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
1540210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
1541210312Sjmallett
1542210312Sjmallett    CVMX_MT_HSH_DAT(tmp1, 0);
1543210312Sjmallett    CVMX_MT_HSH_DAT(tmp2, 1);
1544210312Sjmallett    CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
1545210312Sjmallett    CVMX_MT_HSH_DATZ(3);
1546210312Sjmallett    CVMX_MT_HSH_DATZ(4);
1547210312Sjmallett    CVMX_MT_HSH_DATZ(5);
1548210312Sjmallett    CVMX_MT_HSH_DATZ(6);
1549210312Sjmallett    CVMX_ES64(tmp1, ((64 + 16) << 3));
1550210312Sjmallett    CVMX_MT_HSH_STARTMD5(tmp1);
1551210312Sjmallett
1552210312Sjmallett    /* save the HMAC */
1553210312Sjmallett    IOV_INIT(iov, data32, data_i, data_l);
1554210312Sjmallett    while (icv_off > 0) {
1555210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1556210312Sjmallett	icv_off -= 4;
1557210312Sjmallett    }
1558210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
1559210312Sjmallett    *data32 = (uint32_t) (tmp1 >> 32);
1560210312Sjmallett    IOV_CONSUME(iov, data32, data_i, data_l);
1561210312Sjmallett    *data32 = (uint32_t) tmp1;
1562210312Sjmallett    IOV_CONSUME(iov, data32, data_i, data_l);
1563210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 1);
1564210312Sjmallett    *data32 = (uint32_t) (tmp1 >> 32);
1565210312Sjmallett
1566210312Sjmallett    return 0;
1567210312Sjmallett}
1568210312Sjmallett
1569210312Sjmallettint
1570210312Sjmallettocto_aes_cbc_md5_decrypt(
1571210312Sjmallett    struct octo_sess *od,
1572210312Sjmallett    struct iovec *iov, size_t iovcnt, size_t iovlen,
1573210312Sjmallett    int auth_off, int auth_len,
1574210312Sjmallett    int crypt_off, int crypt_len,
1575210312Sjmallett    int icv_off, uint8_t *ivp)
1576210312Sjmallett{
1577210312Sjmallett    register int next = 0;
1578210312Sjmallett    union {
1579210312Sjmallett	uint32_t data32[2];
1580210312Sjmallett	uint64_t data64[1];
1581210312Sjmallett    } mydata[2];
1582210312Sjmallett    uint64_t *pdata = &mydata[0].data64[0];
1583210312Sjmallett    uint64_t *data =  &mydata[1].data64[0];
1584210312Sjmallett    uint32_t *data32;
1585210312Sjmallett    uint64_t tmp1, tmp2;
1586210312Sjmallett    int data_i, data_l, alen = auth_len;
1587210312Sjmallett
1588210312Sjmallett    dprintf("%s()\n", __func__);
1589210312Sjmallett
1590210312Sjmallett    if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
1591210312Sjmallett	    (crypt_off & 0x3) || (crypt_off + crypt_len > iovlen) ||
1592210312Sjmallett	    (crypt_len  & 0x7) ||
1593210312Sjmallett	    (auth_len  & 0x7) ||
1594210312Sjmallett	    (auth_off & 0x3) || (auth_off + auth_len > iovlen))) {
1595217620Sgonzo	dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
1596210312Sjmallett		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
1597210312Sjmallett		"icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
1598210312Sjmallett		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
1599210312Sjmallett	return -EINVAL;
1600210312Sjmallett    }
1601210312Sjmallett
1602210312Sjmallett    IOV_INIT(iov, data32, data_i, data_l);
1603210312Sjmallett
1604210312Sjmallett    CVMX_PREFETCH0(ivp);
1605210312Sjmallett    CVMX_PREFETCH0(od->octo_enckey);
1606210312Sjmallett
1607210312Sjmallett    /* load AES Key */
1608210312Sjmallett    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
1609210312Sjmallett    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
1610210312Sjmallett
1611210312Sjmallett    if (od->octo_encklen == 16) {
1612210312Sjmallett	CVMX_MT_AES_KEY(0x0, 2);
1613210312Sjmallett	CVMX_MT_AES_KEY(0x0, 3);
1614210312Sjmallett    } else if (od->octo_encklen == 24) {
1615210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1616210312Sjmallett	CVMX_MT_AES_KEY(0x0, 3);
1617210312Sjmallett    } else if (od->octo_encklen == 32) {
1618210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1619210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
1620210312Sjmallett    } else {
1621210312Sjmallett	dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
1622210312Sjmallett	return -EINVAL;
1623210312Sjmallett    }
1624210312Sjmallett    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
1625210312Sjmallett
1626210312Sjmallett    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
1627210312Sjmallett    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
1628210312Sjmallett
1629210312Sjmallett    /* Load MD5 IV */
1630210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
1631210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
1632210312Sjmallett
1633210312Sjmallett    while (crypt_off > 0 && auth_off > 0) {
1634210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1635210312Sjmallett	crypt_off -= 4;
1636210312Sjmallett	auth_off -= 4;
1637210312Sjmallett    }
1638210312Sjmallett
1639210312Sjmallett    while (crypt_len > 0 || auth_len > 0) {
1640210312Sjmallett    	uint32_t *pdata32[3];
1641210312Sjmallett
1642210312Sjmallett	pdata32[0] = data32;
1643210312Sjmallett	mydata[0].data32[0] = *data32;
1644210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1645210312Sjmallett	pdata32[1] = data32;
1646210312Sjmallett	mydata[0].data32[1] = *data32;
1647210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1648210312Sjmallett	pdata32[2] = data32;
1649210312Sjmallett	mydata[1].data32[0] = *data32;
1650210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1651210312Sjmallett	mydata[1].data32[1] = *data32;
1652210312Sjmallett
1653210312Sjmallett    	if (auth_off <= 0) {
1654210312Sjmallett	    if (auth_len > 0) {
1655210312Sjmallett		CVM_LOAD_MD5_UNIT(*pdata, next);
1656210312Sjmallett		CVM_LOAD_MD5_UNIT(*data, next);
1657210312Sjmallett		auth_len -= 16;
1658210312Sjmallett	    }
1659210312Sjmallett	} else
1660210312Sjmallett	    auth_off -= 16;
1661210312Sjmallett
1662210312Sjmallett    	if (crypt_off <= 0) {
1663210312Sjmallett	    if (crypt_len > 0) {
1664210312Sjmallett		CVMX_MT_AES_DEC_CBC0(*pdata);
1665210312Sjmallett		CVMX_MT_AES_DEC_CBC1(*data);
1666210312Sjmallett		CVMX_MF_AES_RESULT(*pdata, 0);
1667210312Sjmallett		CVMX_MF_AES_RESULT(*data, 1);
1668210312Sjmallett		crypt_len -= 16;
1669210312Sjmallett	    }
1670210312Sjmallett	} else
1671210312Sjmallett	    crypt_off -= 16;
1672210312Sjmallett
1673210312Sjmallett	*pdata32[0] = mydata[0].data32[0];
1674210312Sjmallett	*pdata32[1] = mydata[0].data32[1];
1675210312Sjmallett	*pdata32[2] = mydata[1].data32[0];
1676210312Sjmallett	*data32     = mydata[1].data32[1];
1677210312Sjmallett
1678210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1679210312Sjmallett    }
1680210312Sjmallett
1681210312Sjmallett    /* finish the hash */
1682210312Sjmallett    CVMX_PREFETCH0(od->octo_hmouter);
1683210312Sjmallett#if 0
1684210312Sjmallett    if (__predict_false(inplen)) {
1685210312Sjmallett	uint64_t tmp = 0;
1686210312Sjmallett	uint8_t *p = (uint8_t *) & tmp;
1687210312Sjmallett	p[inplen] = 0x80;
1688210312Sjmallett	do {
1689210312Sjmallett	    inplen--;
1690210312Sjmallett	    p[inplen] = ((uint8_t *) data)[inplen];
1691210312Sjmallett	} while (inplen);
1692210312Sjmallett	CVM_LOAD_MD5_UNIT(tmp, next);
1693210312Sjmallett    } else {
1694210312Sjmallett	CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
1695210312Sjmallett    }
1696210312Sjmallett#else
1697210312Sjmallett    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
1698210312Sjmallett#endif
1699210312Sjmallett
1700210312Sjmallett    /* Finish Inner hash */
1701210312Sjmallett    while (next != 7) {
1702210312Sjmallett	CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
1703210312Sjmallett    }
1704210312Sjmallett    CVMX_ES64(tmp1, ((alen + 64) << 3));
1705210312Sjmallett    CVM_LOAD_MD5_UNIT(tmp1, next);
1706210312Sjmallett
1707210312Sjmallett    /* Get the inner hash of HMAC */
1708210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
1709210312Sjmallett    CVMX_MF_HSH_IV(tmp2, 1);
1710210312Sjmallett
1711210312Sjmallett    /* Initialize hash unit */
1712210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
1713210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
1714210312Sjmallett
1715210312Sjmallett    CVMX_MT_HSH_DAT(tmp1, 0);
1716210312Sjmallett    CVMX_MT_HSH_DAT(tmp2, 1);
1717210312Sjmallett    CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
1718210312Sjmallett    CVMX_MT_HSH_DATZ(3);
1719210312Sjmallett    CVMX_MT_HSH_DATZ(4);
1720210312Sjmallett    CVMX_MT_HSH_DATZ(5);
1721210312Sjmallett    CVMX_MT_HSH_DATZ(6);
1722210312Sjmallett    CVMX_ES64(tmp1, ((64 + 16) << 3));
1723210312Sjmallett    CVMX_MT_HSH_STARTMD5(tmp1);
1724210312Sjmallett
1725210312Sjmallett    /* save the HMAC */
1726210312Sjmallett    IOV_INIT(iov, data32, data_i, data_l);
1727210312Sjmallett    while (icv_off > 0) {
1728210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1729210312Sjmallett	icv_off -= 4;
1730210312Sjmallett    }
1731210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
1732210312Sjmallett    *data32 = (uint32_t) (tmp1 >> 32);
1733210312Sjmallett    IOV_CONSUME(iov, data32, data_i, data_l);
1734210312Sjmallett    *data32 = (uint32_t) tmp1;
1735210312Sjmallett    IOV_CONSUME(iov, data32, data_i, data_l);
1736210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 1);
1737210312Sjmallett    *data32 = (uint32_t) (tmp1 >> 32);
1738210312Sjmallett
1739210312Sjmallett    return 0;
1740210312Sjmallett}
1741210312Sjmallett
1742210312Sjmallett/****************************************************************************/
1743210312Sjmallett/* AES SHA1 */
1744210312Sjmallett
1745210312Sjmallettint
1746210312Sjmallettocto_aes_cbc_sha1_encrypt(
1747210312Sjmallett    struct octo_sess *od,
1748210312Sjmallett    struct iovec *iov, size_t iovcnt, size_t iovlen,
1749210312Sjmallett    int auth_off, int auth_len,
1750210312Sjmallett    int crypt_off, int crypt_len,
1751210312Sjmallett    int icv_off, uint8_t *ivp)
1752210312Sjmallett{
1753210312Sjmallett    register int next = 0;
1754210312Sjmallett    union {
1755210312Sjmallett	uint32_t data32[2];
1756210312Sjmallett	uint64_t data64[1];
1757210312Sjmallett    } mydata[2];
1758210312Sjmallett    uint64_t *pdata = &mydata[0].data64[0];
1759210312Sjmallett    uint64_t *data =  &mydata[1].data64[0];
1760210312Sjmallett    uint32_t *data32;
1761210312Sjmallett    uint64_t tmp1, tmp2, tmp3;
1762210312Sjmallett    int data_i, data_l, alen = auth_len;
1763210312Sjmallett
1764210312Sjmallett    dprintf("%s()\n", __func__);
1765210312Sjmallett
1766210312Sjmallett    if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
1767210312Sjmallett	    (crypt_off & 0x3) || (crypt_off + crypt_len > iovlen) ||
1768210312Sjmallett	    (crypt_len  & 0x7) ||
1769210312Sjmallett	    (auth_len  & 0x7) ||
1770210312Sjmallett	    (auth_off & 0x3) || (auth_off + auth_len > iovlen))) {
1771217620Sgonzo	dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
1772210312Sjmallett		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
1773210312Sjmallett		"icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
1774210312Sjmallett		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
1775210312Sjmallett	return -EINVAL;
1776210312Sjmallett    }
1777210312Sjmallett
1778210312Sjmallett    IOV_INIT(iov, data32, data_i, data_l);
1779210312Sjmallett
1780210312Sjmallett    CVMX_PREFETCH0(ivp);
1781210312Sjmallett    CVMX_PREFETCH0(od->octo_enckey);
1782210312Sjmallett
1783210312Sjmallett    /* load AES Key */
1784210312Sjmallett    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
1785210312Sjmallett    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
1786210312Sjmallett
1787210312Sjmallett    if (od->octo_encklen == 16) {
1788210312Sjmallett	CVMX_MT_AES_KEY(0x0, 2);
1789210312Sjmallett	CVMX_MT_AES_KEY(0x0, 3);
1790210312Sjmallett    } else if (od->octo_encklen == 24) {
1791210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1792210312Sjmallett	CVMX_MT_AES_KEY(0x0, 3);
1793210312Sjmallett    } else if (od->octo_encklen == 32) {
1794210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1795210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
1796210312Sjmallett    } else {
1797210312Sjmallett	dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
1798210312Sjmallett	return -EINVAL;
1799210312Sjmallett    }
1800210312Sjmallett    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
1801210312Sjmallett
1802210312Sjmallett    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
1803210312Sjmallett    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
1804210312Sjmallett
1805210312Sjmallett    /* Load SHA IV */
1806210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
1807210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
1808210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
1809210312Sjmallett
1810210312Sjmallett    while (crypt_off > 0 && auth_off > 0) {
1811210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1812210312Sjmallett	crypt_off -= 4;
1813210312Sjmallett	auth_off -= 4;
1814210312Sjmallett    }
1815210312Sjmallett
1816210312Sjmallett    while (crypt_len > 0 || auth_len > 0) {
1817210312Sjmallett    	uint32_t *pdata32[3];
1818210312Sjmallett
1819210312Sjmallett	pdata32[0] = data32;
1820210312Sjmallett	mydata[0].data32[0] = *data32;
1821210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1822210312Sjmallett	pdata32[1] = data32;
1823210312Sjmallett	mydata[0].data32[1] = *data32;
1824210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1825210312Sjmallett	pdata32[2] = data32;
1826210312Sjmallett	mydata[1].data32[0] = *data32;
1827210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1828210312Sjmallett	mydata[1].data32[1] = *data32;
1829210312Sjmallett
1830210312Sjmallett
1831210312Sjmallett    	if (crypt_off <= 0) {
1832210312Sjmallett	    if (crypt_len > 0) {
1833210312Sjmallett		CVMX_MT_AES_ENC_CBC0(*pdata);
1834210312Sjmallett		CVMX_MT_AES_ENC_CBC1(*data);
1835210312Sjmallett		CVMX_MF_AES_RESULT(*pdata, 0);
1836210312Sjmallett		CVMX_MF_AES_RESULT(*data, 1);
1837210312Sjmallett		crypt_len -= 16;
1838210312Sjmallett	    }
1839210312Sjmallett	} else
1840210312Sjmallett	    crypt_off -= 16;
1841210312Sjmallett
1842210312Sjmallett    	if (auth_off <= 0) {
1843210312Sjmallett	    if (auth_len > 0) {
1844210312Sjmallett		CVM_LOAD_SHA_UNIT(*pdata, next);
1845210312Sjmallett		CVM_LOAD_SHA_UNIT(*data, next);
1846210312Sjmallett		auth_len -= 16;
1847210312Sjmallett	    }
1848210312Sjmallett	} else
1849210312Sjmallett	    auth_off -= 16;
1850210312Sjmallett
1851210312Sjmallett	*pdata32[0] = mydata[0].data32[0];
1852210312Sjmallett	*pdata32[1] = mydata[0].data32[1];
1853210312Sjmallett	*pdata32[2] = mydata[1].data32[0];
1854210312Sjmallett	*data32     = mydata[1].data32[1];
1855210312Sjmallett
1856210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1857210312Sjmallett    }
1858210312Sjmallett
1859210312Sjmallett    /* finish the hash */
1860210312Sjmallett    CVMX_PREFETCH0(od->octo_hmouter);
1861210312Sjmallett#if 0
1862210312Sjmallett    if (__predict_false(inplen)) {
1863210312Sjmallett	uint64_t tmp = 0;
1864210312Sjmallett	uint8_t *p = (uint8_t *) & tmp;
1865210312Sjmallett	p[inplen] = 0x80;
1866210312Sjmallett	do {
1867210312Sjmallett	    inplen--;
1868210312Sjmallett	    p[inplen] = ((uint8_t *) data)[inplen];
1869210312Sjmallett	} while (inplen);
1870210312Sjmallett	CVM_LOAD_SHA_UNIT(tmp, next);
1871210312Sjmallett    } else {
1872210312Sjmallett	CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
1873210312Sjmallett    }
1874210312Sjmallett#else
1875210312Sjmallett    CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
1876210312Sjmallett#endif
1877210312Sjmallett
1878210312Sjmallett    /* Finish Inner hash */
1879210312Sjmallett    while (next != 7) {
1880210312Sjmallett	CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
1881210312Sjmallett    }
1882210312Sjmallett	CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
1883210312Sjmallett
1884210312Sjmallett    /* Get the inner hash of HMAC */
1885210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
1886210312Sjmallett    CVMX_MF_HSH_IV(tmp2, 1);
1887210312Sjmallett    tmp3 = 0;
1888210312Sjmallett    CVMX_MF_HSH_IV(tmp3, 2);
1889210312Sjmallett
1890210312Sjmallett    /* Initialize hash unit */
1891210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
1892210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
1893210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
1894210312Sjmallett
1895210312Sjmallett    CVMX_MT_HSH_DAT(tmp1, 0);
1896210312Sjmallett    CVMX_MT_HSH_DAT(tmp2, 1);
1897210312Sjmallett    tmp3 |= 0x0000000080000000;
1898210312Sjmallett    CVMX_MT_HSH_DAT(tmp3, 2);
1899210312Sjmallett    CVMX_MT_HSH_DATZ(3);
1900210312Sjmallett    CVMX_MT_HSH_DATZ(4);
1901210312Sjmallett    CVMX_MT_HSH_DATZ(5);
1902210312Sjmallett    CVMX_MT_HSH_DATZ(6);
1903210312Sjmallett    CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
1904210312Sjmallett
1905210312Sjmallett    /* finish the hash */
1906210312Sjmallett    CVMX_PREFETCH0(od->octo_hmouter);
1907210312Sjmallett#if 0
1908210312Sjmallett    if (__predict_false(inplen)) {
1909210312Sjmallett	uint64_t tmp = 0;
1910210312Sjmallett	uint8_t *p = (uint8_t *) & tmp;
1911210312Sjmallett	p[inplen] = 0x80;
1912210312Sjmallett	do {
1913210312Sjmallett	    inplen--;
1914210312Sjmallett	    p[inplen] = ((uint8_t *) data)[inplen];
1915210312Sjmallett	} while (inplen);
1916210312Sjmallett	CVM_LOAD_MD5_UNIT(tmp, next);
1917210312Sjmallett    } else {
1918210312Sjmallett	CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
1919210312Sjmallett    }
1920210312Sjmallett#else
1921210312Sjmallett    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
1922210312Sjmallett#endif
1923210312Sjmallett
1924210312Sjmallett    /* save the HMAC */
1925210312Sjmallett    IOV_INIT(iov, data32, data_i, data_l);
1926210312Sjmallett    while (icv_off > 0) {
1927210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
1928210312Sjmallett	icv_off -= 4;
1929210312Sjmallett    }
1930210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
1931210312Sjmallett    *data32 = (uint32_t) (tmp1 >> 32);
1932210312Sjmallett    IOV_CONSUME(iov, data32, data_i, data_l);
1933210312Sjmallett    *data32 = (uint32_t) tmp1;
1934210312Sjmallett    IOV_CONSUME(iov, data32, data_i, data_l);
1935210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 1);
1936210312Sjmallett    *data32 = (uint32_t) (tmp1 >> 32);
1937210312Sjmallett
1938210312Sjmallett    return 0;
1939210312Sjmallett}
1940210312Sjmallett
1941210312Sjmallettint
1942210312Sjmallettocto_aes_cbc_sha1_decrypt(
1943210312Sjmallett    struct octo_sess *od,
1944210312Sjmallett    struct iovec *iov, size_t iovcnt, size_t iovlen,
1945210312Sjmallett    int auth_off, int auth_len,
1946210312Sjmallett    int crypt_off, int crypt_len,
1947210312Sjmallett    int icv_off, uint8_t *ivp)
1948210312Sjmallett{
1949210312Sjmallett    register int next = 0;
1950210312Sjmallett    union {
1951210312Sjmallett	uint32_t data32[2];
1952210312Sjmallett	uint64_t data64[1];
1953210312Sjmallett    } mydata[2];
1954210312Sjmallett    uint64_t *pdata = &mydata[0].data64[0];
1955210312Sjmallett    uint64_t *data =  &mydata[1].data64[0];
1956210312Sjmallett    uint32_t *data32;
1957210312Sjmallett    uint64_t tmp1, tmp2, tmp3;
1958210312Sjmallett    int data_i, data_l, alen = auth_len;
1959210312Sjmallett
1960210312Sjmallett    dprintf("%s()\n", __func__);
1961210312Sjmallett
1962210312Sjmallett    if (__predict_false(od == NULL || iov==NULL || iovlen==0 || ivp==NULL ||
1963210312Sjmallett	    (crypt_off & 0x3) || (crypt_off + crypt_len > iovlen) ||
1964210312Sjmallett	    (crypt_len  & 0x7) ||
1965210312Sjmallett	    (auth_len  & 0x7) ||
1966210312Sjmallett	    (auth_off & 0x3) || (auth_off + auth_len > iovlen))) {
1967217620Sgonzo	dprintf("%s: Bad parameters od=%p iov=%p iovlen=%jd "
1968210312Sjmallett		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
1969210312Sjmallett		"icv_off=%d ivp=%p\n", __func__, od, iov, iovlen,
1970210312Sjmallett		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
1971210312Sjmallett	return -EINVAL;
1972210312Sjmallett    }
1973210312Sjmallett
1974210312Sjmallett    IOV_INIT(iov, data32, data_i, data_l);
1975210312Sjmallett
1976210312Sjmallett    CVMX_PREFETCH0(ivp);
1977210312Sjmallett    CVMX_PREFETCH0(od->octo_enckey);
1978210312Sjmallett
1979210312Sjmallett    /* load AES Key */
1980210312Sjmallett    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
1981210312Sjmallett    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
1982210312Sjmallett
1983210312Sjmallett    if (od->octo_encklen == 16) {
1984210312Sjmallett	CVMX_MT_AES_KEY(0x0, 2);
1985210312Sjmallett	CVMX_MT_AES_KEY(0x0, 3);
1986210312Sjmallett    } else if (od->octo_encklen == 24) {
1987210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1988210312Sjmallett	CVMX_MT_AES_KEY(0x0, 3);
1989210312Sjmallett    } else if (od->octo_encklen == 32) {
1990210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
1991210312Sjmallett	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
1992210312Sjmallett    } else {
1993210312Sjmallett	dprintf("%s: Bad key length %d\n", __func__, od->octo_encklen);
1994210312Sjmallett	return -EINVAL;
1995210312Sjmallett    }
1996210312Sjmallett    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
1997210312Sjmallett
1998210312Sjmallett    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
1999210312Sjmallett    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
2000210312Sjmallett
2001210312Sjmallett    /* Load MD5 IV */
2002210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
2003210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
2004210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
2005210312Sjmallett
2006210312Sjmallett    while (crypt_off > 0 && auth_off > 0) {
2007210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
2008210312Sjmallett	crypt_off -= 4;
2009210312Sjmallett	auth_off -= 4;
2010210312Sjmallett    }
2011210312Sjmallett
2012210312Sjmallett    while (crypt_len > 0 || auth_len > 0) {
2013210312Sjmallett    	uint32_t *pdata32[3];
2014210312Sjmallett
2015210312Sjmallett	pdata32[0] = data32;
2016210312Sjmallett	mydata[0].data32[0] = *data32;
2017210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
2018210312Sjmallett	pdata32[1] = data32;
2019210312Sjmallett	mydata[0].data32[1] = *data32;
2020210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
2021210312Sjmallett	pdata32[2] = data32;
2022210312Sjmallett	mydata[1].data32[0] = *data32;
2023210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
2024210312Sjmallett	mydata[1].data32[1] = *data32;
2025210312Sjmallett
2026210312Sjmallett    	if (auth_off <= 0) {
2027210312Sjmallett	    if (auth_len > 0) {
2028210312Sjmallett		CVM_LOAD_SHA_UNIT(*pdata, next);
2029210312Sjmallett		CVM_LOAD_SHA_UNIT(*data, next);
2030210312Sjmallett		auth_len -= 16;
2031210312Sjmallett	    }
2032210312Sjmallett	} else
2033210312Sjmallett	    auth_off -= 16;
2034210312Sjmallett
2035210312Sjmallett    	if (crypt_off <= 0) {
2036210312Sjmallett	    if (crypt_len > 0) {
2037210312Sjmallett		CVMX_MT_AES_DEC_CBC0(*pdata);
2038210312Sjmallett		CVMX_MT_AES_DEC_CBC1(*data);
2039210312Sjmallett		CVMX_MF_AES_RESULT(*pdata, 0);
2040210312Sjmallett		CVMX_MF_AES_RESULT(*data, 1);
2041210312Sjmallett		crypt_len -= 16;
2042210312Sjmallett	    }
2043210312Sjmallett	} else
2044210312Sjmallett	    crypt_off -= 16;
2045210312Sjmallett
2046210312Sjmallett	*pdata32[0] = mydata[0].data32[0];
2047210312Sjmallett	*pdata32[1] = mydata[0].data32[1];
2048210312Sjmallett	*pdata32[2] = mydata[1].data32[0];
2049210312Sjmallett	*data32     = mydata[1].data32[1];
2050210312Sjmallett
2051210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
2052210312Sjmallett    }
2053210312Sjmallett
2054210312Sjmallett    /* finish the hash */
2055210312Sjmallett    CVMX_PREFETCH0(od->octo_hmouter);
2056210312Sjmallett#if 0
2057210312Sjmallett    if (__predict_false(inplen)) {
2058210312Sjmallett	uint64_t tmp = 0;
2059210312Sjmallett	uint8_t *p = (uint8_t *) & tmp;
2060210312Sjmallett	p[inplen] = 0x80;
2061210312Sjmallett	do {
2062210312Sjmallett	    inplen--;
2063210312Sjmallett	    p[inplen] = ((uint8_t *) data)[inplen];
2064210312Sjmallett	} while (inplen);
2065210312Sjmallett	CVM_LOAD_SHA_UNIT(tmp, next);
2066210312Sjmallett    } else {
2067210312Sjmallett	CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
2068210312Sjmallett    }
2069210312Sjmallett#else
2070210312Sjmallett    CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
2071210312Sjmallett#endif
2072210312Sjmallett
2073210312Sjmallett    /* Finish Inner hash */
2074210312Sjmallett    while (next != 7) {
2075210312Sjmallett	CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
2076210312Sjmallett    }
2077210312Sjmallett	CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
2078210312Sjmallett
2079210312Sjmallett    /* Get the inner hash of HMAC */
2080210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
2081210312Sjmallett    CVMX_MF_HSH_IV(tmp2, 1);
2082210312Sjmallett    tmp3 = 0;
2083210312Sjmallett    CVMX_MF_HSH_IV(tmp3, 2);
2084210312Sjmallett
2085210312Sjmallett    /* Initialize hash unit */
2086210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
2087210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
2088210312Sjmallett    CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
2089210312Sjmallett
2090210312Sjmallett    CVMX_MT_HSH_DAT(tmp1, 0);
2091210312Sjmallett    CVMX_MT_HSH_DAT(tmp2, 1);
2092210312Sjmallett    tmp3 |= 0x0000000080000000;
2093210312Sjmallett    CVMX_MT_HSH_DAT(tmp3, 2);
2094210312Sjmallett    CVMX_MT_HSH_DATZ(3);
2095210312Sjmallett    CVMX_MT_HSH_DATZ(4);
2096210312Sjmallett    CVMX_MT_HSH_DATZ(5);
2097210312Sjmallett    CVMX_MT_HSH_DATZ(6);
2098210312Sjmallett    CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
2099210312Sjmallett
2100210312Sjmallett    /* finish the hash */
2101210312Sjmallett    CVMX_PREFETCH0(od->octo_hmouter);
2102210312Sjmallett#if 0
2103210312Sjmallett    if (__predict_false(inplen)) {
2104210312Sjmallett	uint64_t tmp = 0;
2105210312Sjmallett	uint8_t *p = (uint8_t *) & tmp;
2106210312Sjmallett	p[inplen] = 0x80;
2107210312Sjmallett	do {
2108210312Sjmallett	    inplen--;
2109210312Sjmallett	    p[inplen] = ((uint8_t *) data)[inplen];
2110210312Sjmallett	} while (inplen);
2111210312Sjmallett	CVM_LOAD_MD5_UNIT(tmp, next);
2112210312Sjmallett    } else {
2113210312Sjmallett	CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
2114210312Sjmallett    }
2115210312Sjmallett#else
2116210312Sjmallett    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
2117210312Sjmallett#endif
2118210312Sjmallett
2119210312Sjmallett    /* save the HMAC */
2120210312Sjmallett    IOV_INIT(iov, data32, data_i, data_l);
2121210312Sjmallett    while (icv_off > 0) {
2122210312Sjmallett	IOV_CONSUME(iov, data32, data_i, data_l);
2123210312Sjmallett	icv_off -= 4;
2124210312Sjmallett    }
2125210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 0);
2126210312Sjmallett    *data32 = (uint32_t) (tmp1 >> 32);
2127210312Sjmallett    IOV_CONSUME(iov, data32, data_i, data_l);
2128210312Sjmallett    *data32 = (uint32_t) tmp1;
2129210312Sjmallett    IOV_CONSUME(iov, data32, data_i, data_l);
2130210312Sjmallett    CVMX_MF_HSH_IV(tmp1, 1);
2131210312Sjmallett    *data32 = (uint32_t) (tmp1 >> 32);
2132210312Sjmallett
2133210312Sjmallett    return 0;
2134210312Sjmallett}
2135210312Sjmallett
2136210312Sjmallett/****************************************************************************/
2137