summaryrefslogtreecommitdiffstats
path: root/sys/opencrypto
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2002-10-04 20:31:23 +0000
committersam <sam@FreeBSD.org>2002-10-04 20:31:23 +0000
commit91416784e40204fddb837d3327a21b7fe803599b (patch)
tree031839b89be777f8989910a091b189457858c99d /sys/opencrypto
parent16827939fabe12f22c5b06ee3fdf29f6c10b1de2 (diff)
downloadFreeBSD-src-91416784e40204fddb837d3327a21b7fe803599b.zip
FreeBSD-src-91416784e40204fddb837d3327a21b7fe803599b.tar.gz
In-kernel crypto framework derived from openbsd. This facility provides
a consistent interface to h/w and s/w crypto algorithms for use by the kernel and (for h/w at least) by user-mode apps. Access for user-level code is through a /dev/crypto device that'll eventually be used by openssl to (potentially) accelerate many applications. Coming soon is an IPsec that makes use of this service to accelerate ESP, AH, and IPCOMP protocols. Included here is the "core" crypto support, /dev/crypto driver, various crypto algorithms that are not already present in the KAME crypto area, and support routines used by crypto device drivers. Obtained from: openbsd
Diffstat (limited to 'sys/opencrypto')
-rw-r--r--sys/opencrypto/cast.c243
-rw-r--r--sys/opencrypto/cast.h23
-rw-r--r--sys/opencrypto/castsb.h545
-rw-r--r--sys/opencrypto/criov.c137
-rw-r--r--sys/opencrypto/crmbuf.c118
-rw-r--r--sys/opencrypto/crypto.c936
-rw-r--r--sys/opencrypto/crypto_if.m128
-rw-r--r--sys/opencrypto/cryptodev.c798
-rw-r--r--sys/opencrypto/cryptodev.h347
-rw-r--r--sys/opencrypto/cryptosoft.c1025
-rw-r--r--sys/opencrypto/cryptosoft.h65
-rw-r--r--sys/opencrypto/deflate.c189
-rw-r--r--sys/opencrypto/deflate.h56
-rw-r--r--sys/opencrypto/rijndael.c1244
-rw-r--r--sys/opencrypto/rijndael.h52
-rw-r--r--sys/opencrypto/rmd160.c363
-rw-r--r--sys/opencrypto/rmd160.h41
-rw-r--r--sys/opencrypto/skipjack.c258
-rw-r--r--sys/opencrypto/skipjack.h19
-rw-r--r--sys/opencrypto/xform.c629
-rw-r--r--sys/opencrypto/xform.h101
21 files changed, 7317 insertions, 0 deletions
diff --git a/sys/opencrypto/cast.c b/sys/opencrypto/cast.c
new file mode 100644
index 0000000..6e0af0e
--- /dev/null
+++ b/sys/opencrypto/cast.c
@@ -0,0 +1,243 @@
+/* $FreeBSD$ */
+/* $OpenBSD: cast.c,v 1.2 2000/06/06 06:49:47 deraadt Exp $ */
+
+/*
+ * CAST-128 in C
+ * Written by Steve Reid <sreid@sea-to-sky.net>
+ * 100% Public Domain - no warranty
+ * Released 1997.10.11
+ */
+
+#include <sys/types.h>
+#include <opencrypto/cast.h>
+#include <opencrypto/castsb.h>
+
+/* Macros to access 8-bit bytes out of a 32-bit word */
+#define U_INT8_Ta(x) ( (u_int8_t) (x>>24) )
+#define U_INT8_Tb(x) ( (u_int8_t) ((x>>16)&255) )
+#define U_INT8_Tc(x) ( (u_int8_t) ((x>>8)&255) )
+#define U_INT8_Td(x) ( (u_int8_t) ((x)&255) )
+
+/* Circular left shift */
+#define ROL(x, n) ( ((x)<<(n)) | ((x)>>(32-(n))) )
+
+/* CAST-128 uses three different round functions */
+#define F1(l, r, i) \
+ t = ROL(key->xkey[i] + r, key->xkey[i+16]); \
+ l ^= ((cast_sbox1[U_INT8_Ta(t)] ^ cast_sbox2[U_INT8_Tb(t)]) - \
+ cast_sbox3[U_INT8_Tc(t)]) + cast_sbox4[U_INT8_Td(t)];
+#define F2(l, r, i) \
+ t = ROL(key->xkey[i] ^ r, key->xkey[i+16]); \
+ l ^= ((cast_sbox1[U_INT8_Ta(t)] - cast_sbox2[U_INT8_Tb(t)]) + \
+ cast_sbox3[U_INT8_Tc(t)]) ^ cast_sbox4[U_INT8_Td(t)];
+#define F3(l, r, i) \
+ t = ROL(key->xkey[i] - r, key->xkey[i+16]); \
+ l ^= ((cast_sbox1[U_INT8_Ta(t)] + cast_sbox2[U_INT8_Tb(t)]) ^ \
+ cast_sbox3[U_INT8_Tc(t)]) - cast_sbox4[U_INT8_Td(t)];
+
+
+/***** Encryption Function *****/
+
+void cast_encrypt(cast_key* key, u_int8_t* inblock, u_int8_t* outblock)
+{
+u_int32_t t, l, r;
+
+ /* Get inblock into l,r */
+ l = ((u_int32_t)inblock[0] << 24) | ((u_int32_t)inblock[1] << 16) |
+ ((u_int32_t)inblock[2] << 8) | (u_int32_t)inblock[3];
+ r = ((u_int32_t)inblock[4] << 24) | ((u_int32_t)inblock[5] << 16) |
+ ((u_int32_t)inblock[6] << 8) | (u_int32_t)inblock[7];
+ /* Do the work */
+ F1(l, r, 0);
+ F2(r, l, 1);
+ F3(l, r, 2);
+ F1(r, l, 3);
+ F2(l, r, 4);
+ F3(r, l, 5);
+ F1(l, r, 6);
+ F2(r, l, 7);
+ F3(l, r, 8);
+ F1(r, l, 9);
+ F2(l, r, 10);
+ F3(r, l, 11);
+ /* Only do full 16 rounds if key length > 80 bits */
+ if (key->rounds > 12) {
+ F1(l, r, 12);
+ F2(r, l, 13);
+ F3(l, r, 14);
+ F1(r, l, 15);
+ }
+ /* Put l,r into outblock */
+ outblock[0] = U_INT8_Ta(r);
+ outblock[1] = U_INT8_Tb(r);
+ outblock[2] = U_INT8_Tc(r);
+ outblock[3] = U_INT8_Td(r);
+ outblock[4] = U_INT8_Ta(l);
+ outblock[5] = U_INT8_Tb(l);
+ outblock[6] = U_INT8_Tc(l);
+ outblock[7] = U_INT8_Td(l);
+ /* Wipe clean */
+ t = l = r = 0;
+}
+
+
+/***** Decryption Function *****/
+
+void cast_decrypt(cast_key* key, u_int8_t* inblock, u_int8_t* outblock)
+{
+u_int32_t t, l, r;
+
+ /* Get inblock into l,r */
+ r = ((u_int32_t)inblock[0] << 24) | ((u_int32_t)inblock[1] << 16) |
+ ((u_int32_t)inblock[2] << 8) | (u_int32_t)inblock[3];
+ l = ((u_int32_t)inblock[4] << 24) | ((u_int32_t)inblock[5] << 16) |
+ ((u_int32_t)inblock[6] << 8) | (u_int32_t)inblock[7];
+ /* Do the work */
+ /* Only do full 16 rounds if key length > 80 bits */
+ if (key->rounds > 12) {
+ F1(r, l, 15);
+ F3(l, r, 14);
+ F2(r, l, 13);
+ F1(l, r, 12);
+ }
+ F3(r, l, 11);
+ F2(l, r, 10);
+ F1(r, l, 9);
+ F3(l, r, 8);
+ F2(r, l, 7);
+ F1(l, r, 6);
+ F3(r, l, 5);
+ F2(l, r, 4);
+ F1(r, l, 3);
+ F3(l, r, 2);
+ F2(r, l, 1);
+ F1(l, r, 0);
+ /* Put l,r into outblock */
+ outblock[0] = U_INT8_Ta(l);
+ outblock[1] = U_INT8_Tb(l);
+ outblock[2] = U_INT8_Tc(l);
+ outblock[3] = U_INT8_Td(l);
+ outblock[4] = U_INT8_Ta(r);
+ outblock[5] = U_INT8_Tb(r);
+ outblock[6] = U_INT8_Tc(r);
+ outblock[7] = U_INT8_Td(r);
+ /* Wipe clean */
+ t = l = r = 0;
+}
+
+
+/***** Key Schedual *****/
+
+void cast_setkey(cast_key* key, u_int8_t* rawkey, int keybytes)
+{
+u_int32_t t[4], z[4], x[4];
+int i;
+
+ /* Set number of rounds to 12 or 16, depending on key length */
+ key->rounds = (keybytes <= 10 ? 12 : 16);
+
+ /* Copy key to workspace x */
+ for (i = 0; i < 4; i++) {
+ x[i] = 0;
+ if ((i*4+0) < keybytes) x[i] = (u_int32_t)rawkey[i*4+0] << 24;
+ if ((i*4+1) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+1] << 16;
+ if ((i*4+2) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+2] << 8;
+ if ((i*4+3) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+3];
+ }
+ /* Generate 32 subkeys, four at a time */
+ for (i = 0; i < 32; i+=4) {
+ switch (i & 4) {
+ case 0:
+ t[0] = z[0] = x[0] ^ cast_sbox5[U_INT8_Tb(x[3])] ^
+ cast_sbox6[U_INT8_Td(x[3])] ^ cast_sbox7[U_INT8_Ta(x[3])] ^
+ cast_sbox8[U_INT8_Tc(x[3])] ^ cast_sbox7[U_INT8_Ta(x[2])];
+ t[1] = z[1] = x[2] ^ cast_sbox5[U_INT8_Ta(z[0])] ^
+ cast_sbox6[U_INT8_Tc(z[0])] ^ cast_sbox7[U_INT8_Tb(z[0])] ^
+ cast_sbox8[U_INT8_Td(z[0])] ^ cast_sbox8[U_INT8_Tc(x[2])];
+ t[2] = z[2] = x[3] ^ cast_sbox5[U_INT8_Td(z[1])] ^
+ cast_sbox6[U_INT8_Tc(z[1])] ^ cast_sbox7[U_INT8_Tb(z[1])] ^
+ cast_sbox8[U_INT8_Ta(z[1])] ^ cast_sbox5[U_INT8_Tb(x[2])];
+ t[3] = z[3] = x[1] ^ cast_sbox5[U_INT8_Tc(z[2])] ^
+ cast_sbox6[U_INT8_Tb(z[2])] ^ cast_sbox7[U_INT8_Td(z[2])] ^
+ cast_sbox8[U_INT8_Ta(z[2])] ^ cast_sbox6[U_INT8_Td(x[2])];
+ break;
+ case 4:
+ t[0] = x[0] = z[2] ^ cast_sbox5[U_INT8_Tb(z[1])] ^
+ cast_sbox6[U_INT8_Td(z[1])] ^ cast_sbox7[U_INT8_Ta(z[1])] ^
+ cast_sbox8[U_INT8_Tc(z[1])] ^ cast_sbox7[U_INT8_Ta(z[0])];
+ t[1] = x[1] = z[0] ^ cast_sbox5[U_INT8_Ta(x[0])] ^
+ cast_sbox6[U_INT8_Tc(x[0])] ^ cast_sbox7[U_INT8_Tb(x[0])] ^
+ cast_sbox8[U_INT8_Td(x[0])] ^ cast_sbox8[U_INT8_Tc(z[0])];
+ t[2] = x[2] = z[1] ^ cast_sbox5[U_INT8_Td(x[1])] ^
+ cast_sbox6[U_INT8_Tc(x[1])] ^ cast_sbox7[U_INT8_Tb(x[1])] ^
+ cast_sbox8[U_INT8_Ta(x[1])] ^ cast_sbox5[U_INT8_Tb(z[0])];
+ t[3] = x[3] = z[3] ^ cast_sbox5[U_INT8_Tc(x[2])] ^
+ cast_sbox6[U_INT8_Tb(x[2])] ^ cast_sbox7[U_INT8_Td(x[2])] ^
+ cast_sbox8[U_INT8_Ta(x[2])] ^ cast_sbox6[U_INT8_Td(z[0])];
+ break;
+ }
+ switch (i & 12) {
+ case 0:
+ case 12:
+ key->xkey[i+0] = cast_sbox5[U_INT8_Ta(t[2])] ^ cast_sbox6[U_INT8_Tb(t[2])] ^
+ cast_sbox7[U_INT8_Td(t[1])] ^ cast_sbox8[U_INT8_Tc(t[1])];
+ key->xkey[i+1] = cast_sbox5[U_INT8_Tc(t[2])] ^ cast_sbox6[U_INT8_Td(t[2])] ^
+ cast_sbox7[U_INT8_Tb(t[1])] ^ cast_sbox8[U_INT8_Ta(t[1])];
+ key->xkey[i+2] = cast_sbox5[U_INT8_Ta(t[3])] ^ cast_sbox6[U_INT8_Tb(t[3])] ^
+ cast_sbox7[U_INT8_Td(t[0])] ^ cast_sbox8[U_INT8_Tc(t[0])];
+ key->xkey[i+3] = cast_sbox5[U_INT8_Tc(t[3])] ^ cast_sbox6[U_INT8_Td(t[3])] ^
+ cast_sbox7[U_INT8_Tb(t[0])] ^ cast_sbox8[U_INT8_Ta(t[0])];
+ break;
+ case 4:
+ case 8:
+ key->xkey[i+0] = cast_sbox5[U_INT8_Td(t[0])] ^ cast_sbox6[U_INT8_Tc(t[0])] ^
+ cast_sbox7[U_INT8_Ta(t[3])] ^ cast_sbox8[U_INT8_Tb(t[3])];
+ key->xkey[i+1] = cast_sbox5[U_INT8_Tb(t[0])] ^ cast_sbox6[U_INT8_Ta(t[0])] ^
+ cast_sbox7[U_INT8_Tc(t[3])] ^ cast_sbox8[U_INT8_Td(t[3])];
+ key->xkey[i+2] = cast_sbox5[U_INT8_Td(t[1])] ^ cast_sbox6[U_INT8_Tc(t[1])] ^
+ cast_sbox7[U_INT8_Ta(t[2])] ^ cast_sbox8[U_INT8_Tb(t[2])];
+ key->xkey[i+3] = cast_sbox5[U_INT8_Tb(t[1])] ^ cast_sbox6[U_INT8_Ta(t[1])] ^
+ cast_sbox7[U_INT8_Tc(t[2])] ^ cast_sbox8[U_INT8_Td(t[2])];
+ break;
+ }
+ switch (i & 12) {
+ case 0:
+ key->xkey[i+0] ^= cast_sbox5[U_INT8_Tc(z[0])];
+ key->xkey[i+1] ^= cast_sbox6[U_INT8_Tc(z[1])];
+ key->xkey[i+2] ^= cast_sbox7[U_INT8_Tb(z[2])];
+ key->xkey[i+3] ^= cast_sbox8[U_INT8_Ta(z[3])];
+ break;
+ case 4:
+ key->xkey[i+0] ^= cast_sbox5[U_INT8_Ta(x[2])];
+ key->xkey[i+1] ^= cast_sbox6[U_INT8_Tb(x[3])];
+ key->xkey[i+2] ^= cast_sbox7[U_INT8_Td(x[0])];
+ key->xkey[i+3] ^= cast_sbox8[U_INT8_Td(x[1])];
+ break;
+ case 8:
+ key->xkey[i+0] ^= cast_sbox5[U_INT8_Tb(z[2])];
+ key->xkey[i+1] ^= cast_sbox6[U_INT8_Ta(z[3])];
+ key->xkey[i+2] ^= cast_sbox7[U_INT8_Tc(z[0])];
+ key->xkey[i+3] ^= cast_sbox8[U_INT8_Tc(z[1])];
+ break;
+ case 12:
+ key->xkey[i+0] ^= cast_sbox5[U_INT8_Td(x[0])];
+ key->xkey[i+1] ^= cast_sbox6[U_INT8_Td(x[1])];
+ key->xkey[i+2] ^= cast_sbox7[U_INT8_Ta(x[2])];
+ key->xkey[i+3] ^= cast_sbox8[U_INT8_Tb(x[3])];
+ break;
+ }
+ if (i >= 16) {
+ key->xkey[i+0] &= 31;
+ key->xkey[i+1] &= 31;
+ key->xkey[i+2] &= 31;
+ key->xkey[i+3] &= 31;
+ }
+ }
+ /* Wipe clean */
+ for (i = 0; i < 4; i++) {
+ t[i] = x[i] = z[i] = 0;
+ }
+}
+
+/* Made in Canada */
+
diff --git a/sys/opencrypto/cast.h b/sys/opencrypto/cast.h
new file mode 100644
index 0000000..06aaf9d
--- /dev/null
+++ b/sys/opencrypto/cast.h
@@ -0,0 +1,23 @@
+/* $FreeBSD$ */
+/* $OpenBSD: cast.h,v 1.2 2002/03/14 01:26:51 millert Exp $ */
+
+/*
+ * CAST-128 in C
+ * Written by Steve Reid <sreid@sea-to-sky.net>
+ * 100% Public Domain - no warranty
+ * Released 1997.10.11
+ */
+
+#ifndef _CAST_H_
+#define _CAST_H_
+
+typedef struct {
+ u_int32_t xkey[32]; /* Key, after expansion */
+ int rounds; /* Number of rounds to use, 12 or 16 */
+} cast_key;
+
+void cast_setkey(cast_key * key, u_int8_t * rawkey, int keybytes);
+void cast_encrypt(cast_key * key, u_int8_t * inblock, u_int8_t * outblock);
+void cast_decrypt(cast_key * key, u_int8_t * inblock, u_int8_t * outblock);
+
+#endif /* ifndef _CAST_H_ */
diff --git a/sys/opencrypto/castsb.h b/sys/opencrypto/castsb.h
new file mode 100644
index 0000000..739d06e
--- /dev/null
+++ b/sys/opencrypto/castsb.h
@@ -0,0 +1,545 @@
+/* $FreeBSD$ */
+/* $OpenBSD: castsb.h,v 1.1 2000/02/28 23:13:04 deraadt Exp $ */
+/*
+ * CAST-128 in C
+ * Written by Steve Reid <sreid@sea-to-sky.net>
+ * 100% Public Domain - no warranty
+ * Released 1997.10.11
+ */
+
+static const u_int32_t cast_sbox1[256] = {
+ 0x30FB40D4, 0x9FA0FF0B, 0x6BECCD2F, 0x3F258C7A,
+ 0x1E213F2F, 0x9C004DD3, 0x6003E540, 0xCF9FC949,
+ 0xBFD4AF27, 0x88BBBDB5, 0xE2034090, 0x98D09675,
+ 0x6E63A0E0, 0x15C361D2, 0xC2E7661D, 0x22D4FF8E,
+ 0x28683B6F, 0xC07FD059, 0xFF2379C8, 0x775F50E2,
+ 0x43C340D3, 0xDF2F8656, 0x887CA41A, 0xA2D2BD2D,
+ 0xA1C9E0D6, 0x346C4819, 0x61B76D87, 0x22540F2F,
+ 0x2ABE32E1, 0xAA54166B, 0x22568E3A, 0xA2D341D0,
+ 0x66DB40C8, 0xA784392F, 0x004DFF2F, 0x2DB9D2DE,
+ 0x97943FAC, 0x4A97C1D8, 0x527644B7, 0xB5F437A7,
+ 0xB82CBAEF, 0xD751D159, 0x6FF7F0ED, 0x5A097A1F,
+ 0x827B68D0, 0x90ECF52E, 0x22B0C054, 0xBC8E5935,
+ 0x4B6D2F7F, 0x50BB64A2, 0xD2664910, 0xBEE5812D,
+ 0xB7332290, 0xE93B159F, 0xB48EE411, 0x4BFF345D,
+ 0xFD45C240, 0xAD31973F, 0xC4F6D02E, 0x55FC8165,
+ 0xD5B1CAAD, 0xA1AC2DAE, 0xA2D4B76D, 0xC19B0C50,
+ 0x882240F2, 0x0C6E4F38, 0xA4E4BFD7, 0x4F5BA272,
+ 0x564C1D2F, 0xC59C5319, 0xB949E354, 0xB04669FE,
+ 0xB1B6AB8A, 0xC71358DD, 0x6385C545, 0x110F935D,
+ 0x57538AD5, 0x6A390493, 0xE63D37E0, 0x2A54F6B3,
+ 0x3A787D5F, 0x6276A0B5, 0x19A6FCDF, 0x7A42206A,
+ 0x29F9D4D5, 0xF61B1891, 0xBB72275E, 0xAA508167,
+ 0x38901091, 0xC6B505EB, 0x84C7CB8C, 0x2AD75A0F,
+ 0x874A1427, 0xA2D1936B, 0x2AD286AF, 0xAA56D291,
+ 0xD7894360, 0x425C750D, 0x93B39E26, 0x187184C9,
+ 0x6C00B32D, 0x73E2BB14, 0xA0BEBC3C, 0x54623779,
+ 0x64459EAB, 0x3F328B82, 0x7718CF82, 0x59A2CEA6,
+ 0x04EE002E, 0x89FE78E6, 0x3FAB0950, 0x325FF6C2,
+ 0x81383F05, 0x6963C5C8, 0x76CB5AD6, 0xD49974C9,
+ 0xCA180DCF, 0x380782D5, 0xC7FA5CF6, 0x8AC31511,
+ 0x35E79E13, 0x47DA91D0, 0xF40F9086, 0xA7E2419E,
+ 0x31366241, 0x051EF495, 0xAA573B04, 0x4A805D8D,
+ 0x548300D0, 0x00322A3C, 0xBF64CDDF, 0xBA57A68E,
+ 0x75C6372B, 0x50AFD341, 0xA7C13275, 0x915A0BF5,
+ 0x6B54BFAB, 0x2B0B1426, 0xAB4CC9D7, 0x449CCD82,
+ 0xF7FBF265, 0xAB85C5F3, 0x1B55DB94, 0xAAD4E324,
+ 0xCFA4BD3F, 0x2DEAA3E2, 0x9E204D02, 0xC8BD25AC,
+ 0xEADF55B3, 0xD5BD9E98, 0xE31231B2, 0x2AD5AD6C,
+ 0x954329DE, 0xADBE4528, 0xD8710F69, 0xAA51C90F,
+ 0xAA786BF6, 0x22513F1E, 0xAA51A79B, 0x2AD344CC,
+ 0x7B5A41F0, 0xD37CFBAD, 0x1B069505, 0x41ECE491,
+ 0xB4C332E6, 0x032268D4, 0xC9600ACC, 0xCE387E6D,
+ 0xBF6BB16C, 0x6A70FB78, 0x0D03D9C9, 0xD4DF39DE,
+ 0xE01063DA, 0x4736F464, 0x5AD328D8, 0xB347CC96,
+ 0x75BB0FC3, 0x98511BFB, 0x4FFBCC35, 0xB58BCF6A,
+ 0xE11F0ABC, 0xBFC5FE4A, 0xA70AEC10, 0xAC39570A,
+ 0x3F04442F, 0x6188B153, 0xE0397A2E, 0x5727CB79,
+ 0x9CEB418F, 0x1CACD68D, 0x2AD37C96, 0x0175CB9D,
+ 0xC69DFF09, 0xC75B65F0, 0xD9DB40D8, 0xEC0E7779,
+ 0x4744EAD4, 0xB11C3274, 0xDD24CB9E, 0x7E1C54BD,
+ 0xF01144F9, 0xD2240EB1, 0x9675B3FD, 0xA3AC3755,
+ 0xD47C27AF, 0x51C85F4D, 0x56907596, 0xA5BB15E6,
+ 0x580304F0, 0xCA042CF1, 0x011A37EA, 0x8DBFAADB,
+ 0x35BA3E4A, 0x3526FFA0, 0xC37B4D09, 0xBC306ED9,
+ 0x98A52666, 0x5648F725, 0xFF5E569D, 0x0CED63D0,
+ 0x7C63B2CF, 0x700B45E1, 0xD5EA50F1, 0x85A92872,
+ 0xAF1FBDA7, 0xD4234870, 0xA7870BF3, 0x2D3B4D79,
+ 0x42E04198, 0x0CD0EDE7, 0x26470DB8, 0xF881814C,
+ 0x474D6AD7, 0x7C0C5E5C, 0xD1231959, 0x381B7298,
+ 0xF5D2F4DB, 0xAB838653, 0x6E2F1E23, 0x83719C9E,
+ 0xBD91E046, 0x9A56456E, 0xDC39200C, 0x20C8C571,
+ 0x962BDA1C, 0xE1E696FF, 0xB141AB08, 0x7CCA89B9,
+ 0x1A69E783, 0x02CC4843, 0xA2F7C579, 0x429EF47D,
+ 0x427B169C, 0x5AC9F049, 0xDD8F0F00, 0x5C8165BF
+};
+
+static const u_int32_t cast_sbox2[256] = {
+ 0x1F201094, 0xEF0BA75B, 0x69E3CF7E, 0x393F4380,
+ 0xFE61CF7A, 0xEEC5207A, 0x55889C94, 0x72FC0651,
+ 0xADA7EF79, 0x4E1D7235, 0xD55A63CE, 0xDE0436BA,
+ 0x99C430EF, 0x5F0C0794, 0x18DCDB7D, 0xA1D6EFF3,
+ 0xA0B52F7B, 0x59E83605, 0xEE15B094, 0xE9FFD909,
+ 0xDC440086, 0xEF944459, 0xBA83CCB3, 0xE0C3CDFB,
+ 0xD1DA4181, 0x3B092AB1, 0xF997F1C1, 0xA5E6CF7B,
+ 0x01420DDB, 0xE4E7EF5B, 0x25A1FF41, 0xE180F806,
+ 0x1FC41080, 0x179BEE7A, 0xD37AC6A9, 0xFE5830A4,
+ 0x98DE8B7F, 0x77E83F4E, 0x79929269, 0x24FA9F7B,
+ 0xE113C85B, 0xACC40083, 0xD7503525, 0xF7EA615F,
+ 0x62143154, 0x0D554B63, 0x5D681121, 0xC866C359,
+ 0x3D63CF73, 0xCEE234C0, 0xD4D87E87, 0x5C672B21,
+ 0x071F6181, 0x39F7627F, 0x361E3084, 0xE4EB573B,
+ 0x602F64A4, 0xD63ACD9C, 0x1BBC4635, 0x9E81032D,
+ 0x2701F50C, 0x99847AB4, 0xA0E3DF79, 0xBA6CF38C,
+ 0x10843094, 0x2537A95E, 0xF46F6FFE, 0xA1FF3B1F,
+ 0x208CFB6A, 0x8F458C74, 0xD9E0A227, 0x4EC73A34,
+ 0xFC884F69, 0x3E4DE8DF, 0xEF0E0088, 0x3559648D,
+ 0x8A45388C, 0x1D804366, 0x721D9BFD, 0xA58684BB,
+ 0xE8256333, 0x844E8212, 0x128D8098, 0xFED33FB4,
+ 0xCE280AE1, 0x27E19BA5, 0xD5A6C252, 0xE49754BD,
+ 0xC5D655DD, 0xEB667064, 0x77840B4D, 0xA1B6A801,
+ 0x84DB26A9, 0xE0B56714, 0x21F043B7, 0xE5D05860,
+ 0x54F03084, 0x066FF472, 0xA31AA153, 0xDADC4755,
+ 0xB5625DBF, 0x68561BE6, 0x83CA6B94, 0x2D6ED23B,
+ 0xECCF01DB, 0xA6D3D0BA, 0xB6803D5C, 0xAF77A709,
+ 0x33B4A34C, 0x397BC8D6, 0x5EE22B95, 0x5F0E5304,
+ 0x81ED6F61, 0x20E74364, 0xB45E1378, 0xDE18639B,
+ 0x881CA122, 0xB96726D1, 0x8049A7E8, 0x22B7DA7B,
+ 0x5E552D25, 0x5272D237, 0x79D2951C, 0xC60D894C,
+ 0x488CB402, 0x1BA4FE5B, 0xA4B09F6B, 0x1CA815CF,
+ 0xA20C3005, 0x8871DF63, 0xB9DE2FCB, 0x0CC6C9E9,
+ 0x0BEEFF53, 0xE3214517, 0xB4542835, 0x9F63293C,
+ 0xEE41E729, 0x6E1D2D7C, 0x50045286, 0x1E6685F3,
+ 0xF33401C6, 0x30A22C95, 0x31A70850, 0x60930F13,
+ 0x73F98417, 0xA1269859, 0xEC645C44, 0x52C877A9,
+ 0xCDFF33A6, 0xA02B1741, 0x7CBAD9A2, 0x2180036F,
+ 0x50D99C08, 0xCB3F4861, 0xC26BD765, 0x64A3F6AB,
+ 0x80342676, 0x25A75E7B, 0xE4E6D1FC, 0x20C710E6,
+ 0xCDF0B680, 0x17844D3B, 0x31EEF84D, 0x7E0824E4,
+ 0x2CCB49EB, 0x846A3BAE, 0x8FF77888, 0xEE5D60F6,
+ 0x7AF75673, 0x2FDD5CDB, 0xA11631C1, 0x30F66F43,
+ 0xB3FAEC54, 0x157FD7FA, 0xEF8579CC, 0xD152DE58,
+ 0xDB2FFD5E, 0x8F32CE19, 0x306AF97A, 0x02F03EF8,
+ 0x99319AD5, 0xC242FA0F, 0xA7E3EBB0, 0xC68E4906,
+ 0xB8DA230C, 0x80823028, 0xDCDEF3C8, 0xD35FB171,
+ 0x088A1BC8, 0xBEC0C560, 0x61A3C9E8, 0xBCA8F54D,
+ 0xC72FEFFA, 0x22822E99, 0x82C570B4, 0xD8D94E89,
+ 0x8B1C34BC, 0x301E16E6, 0x273BE979, 0xB0FFEAA6,
+ 0x61D9B8C6, 0x00B24869, 0xB7FFCE3F, 0x08DC283B,
+ 0x43DAF65A, 0xF7E19798, 0x7619B72F, 0x8F1C9BA4,
+ 0xDC8637A0, 0x16A7D3B1, 0x9FC393B7, 0xA7136EEB,
+ 0xC6BCC63E, 0x1A513742, 0xEF6828BC, 0x520365D6,
+ 0x2D6A77AB, 0x3527ED4B, 0x821FD216, 0x095C6E2E,
+ 0xDB92F2FB, 0x5EEA29CB, 0x145892F5, 0x91584F7F,
+ 0x5483697B, 0x2667A8CC, 0x85196048, 0x8C4BACEA,
+ 0x833860D4, 0x0D23E0F9, 0x6C387E8A, 0x0AE6D249,
+ 0xB284600C, 0xD835731D, 0xDCB1C647, 0xAC4C56EA,
+ 0x3EBD81B3, 0x230EABB0, 0x6438BC87, 0xF0B5B1FA,
+ 0x8F5EA2B3, 0xFC184642, 0x0A036B7A, 0x4FB089BD,
+ 0x649DA589, 0xA345415E, 0x5C038323, 0x3E5D3BB9,
+ 0x43D79572, 0x7E6DD07C, 0x06DFDF1E, 0x6C6CC4EF,
+ 0x7160A539, 0x73BFBE70, 0x83877605, 0x4523ECF1
+};
+
+static const u_int32_t cast_sbox3[256] = {
+ 0x8DEFC240, 0x25FA5D9F, 0xEB903DBF, 0xE810C907,
+ 0x47607FFF, 0x369FE44B, 0x8C1FC644, 0xAECECA90,
+ 0xBEB1F9BF, 0xEEFBCAEA, 0xE8CF1950, 0x51DF07AE,
+ 0x920E8806, 0xF0AD0548, 0xE13C8D83, 0x927010D5,
+ 0x11107D9F, 0x07647DB9, 0xB2E3E4D4, 0x3D4F285E,
+ 0xB9AFA820, 0xFADE82E0, 0xA067268B, 0x8272792E,
+ 0x553FB2C0, 0x489AE22B, 0xD4EF9794, 0x125E3FBC,
+ 0x21FFFCEE, 0x825B1BFD, 0x9255C5ED, 0x1257A240,
+ 0x4E1A8302, 0xBAE07FFF, 0x528246E7, 0x8E57140E,
+ 0x3373F7BF, 0x8C9F8188, 0xA6FC4EE8, 0xC982B5A5,
+ 0xA8C01DB7, 0x579FC264, 0x67094F31, 0xF2BD3F5F,
+ 0x40FFF7C1, 0x1FB78DFC, 0x8E6BD2C1, 0x437BE59B,
+ 0x99B03DBF, 0xB5DBC64B, 0x638DC0E6, 0x55819D99,
+ 0xA197C81C, 0x4A012D6E, 0xC5884A28, 0xCCC36F71,
+ 0xB843C213, 0x6C0743F1, 0x8309893C, 0x0FEDDD5F,
+ 0x2F7FE850, 0xD7C07F7E, 0x02507FBF, 0x5AFB9A04,
+ 0xA747D2D0, 0x1651192E, 0xAF70BF3E, 0x58C31380,
+ 0x5F98302E, 0x727CC3C4, 0x0A0FB402, 0x0F7FEF82,
+ 0x8C96FDAD, 0x5D2C2AAE, 0x8EE99A49, 0x50DA88B8,
+ 0x8427F4A0, 0x1EAC5790, 0x796FB449, 0x8252DC15,
+ 0xEFBD7D9B, 0xA672597D, 0xADA840D8, 0x45F54504,
+ 0xFA5D7403, 0xE83EC305, 0x4F91751A, 0x925669C2,
+ 0x23EFE941, 0xA903F12E, 0x60270DF2, 0x0276E4B6,
+ 0x94FD6574, 0x927985B2, 0x8276DBCB, 0x02778176,
+ 0xF8AF918D, 0x4E48F79E, 0x8F616DDF, 0xE29D840E,
+ 0x842F7D83, 0x340CE5C8, 0x96BBB682, 0x93B4B148,
+ 0xEF303CAB, 0x984FAF28, 0x779FAF9B, 0x92DC560D,
+ 0x224D1E20, 0x8437AA88, 0x7D29DC96, 0x2756D3DC,
+ 0x8B907CEE, 0xB51FD240, 0xE7C07CE3, 0xE566B4A1,
+ 0xC3E9615E, 0x3CF8209D, 0x6094D1E3, 0xCD9CA341,
+ 0x5C76460E, 0x00EA983B, 0xD4D67881, 0xFD47572C,
+ 0xF76CEDD9, 0xBDA8229C, 0x127DADAA, 0x438A074E,
+ 0x1F97C090, 0x081BDB8A, 0x93A07EBE, 0xB938CA15,
+ 0x97B03CFF, 0x3DC2C0F8, 0x8D1AB2EC, 0x64380E51,
+ 0x68CC7BFB, 0xD90F2788, 0x12490181, 0x5DE5FFD4,
+ 0xDD7EF86A, 0x76A2E214, 0xB9A40368, 0x925D958F,
+ 0x4B39FFFA, 0xBA39AEE9, 0xA4FFD30B, 0xFAF7933B,
+ 0x6D498623, 0x193CBCFA, 0x27627545, 0x825CF47A,
+ 0x61BD8BA0, 0xD11E42D1, 0xCEAD04F4, 0x127EA392,
+ 0x10428DB7, 0x8272A972, 0x9270C4A8, 0x127DE50B,
+ 0x285BA1C8, 0x3C62F44F, 0x35C0EAA5, 0xE805D231,
+ 0x428929FB, 0xB4FCDF82, 0x4FB66A53, 0x0E7DC15B,
+ 0x1F081FAB, 0x108618AE, 0xFCFD086D, 0xF9FF2889,
+ 0x694BCC11, 0x236A5CAE, 0x12DECA4D, 0x2C3F8CC5,
+ 0xD2D02DFE, 0xF8EF5896, 0xE4CF52DA, 0x95155B67,
+ 0x494A488C, 0xB9B6A80C, 0x5C8F82BC, 0x89D36B45,
+ 0x3A609437, 0xEC00C9A9, 0x44715253, 0x0A874B49,
+ 0xD773BC40, 0x7C34671C, 0x02717EF6, 0x4FEB5536,
+ 0xA2D02FFF, 0xD2BF60C4, 0xD43F03C0, 0x50B4EF6D,
+ 0x07478CD1, 0x006E1888, 0xA2E53F55, 0xB9E6D4BC,
+ 0xA2048016, 0x97573833, 0xD7207D67, 0xDE0F8F3D,
+ 0x72F87B33, 0xABCC4F33, 0x7688C55D, 0x7B00A6B0,
+ 0x947B0001, 0x570075D2, 0xF9BB88F8, 0x8942019E,
+ 0x4264A5FF, 0x856302E0, 0x72DBD92B, 0xEE971B69,
+ 0x6EA22FDE, 0x5F08AE2B, 0xAF7A616D, 0xE5C98767,
+ 0xCF1FEBD2, 0x61EFC8C2, 0xF1AC2571, 0xCC8239C2,
+ 0x67214CB8, 0xB1E583D1, 0xB7DC3E62, 0x7F10BDCE,
+ 0xF90A5C38, 0x0FF0443D, 0x606E6DC6, 0x60543A49,
+ 0x5727C148, 0x2BE98A1D, 0x8AB41738, 0x20E1BE24,
+ 0xAF96DA0F, 0x68458425, 0x99833BE5, 0x600D457D,
+ 0x282F9350, 0x8334B362, 0xD91D1120, 0x2B6D8DA0,
+ 0x642B1E31, 0x9C305A00, 0x52BCE688, 0x1B03588A,
+ 0xF7BAEFD5, 0x4142ED9C, 0xA4315C11, 0x83323EC5,
+ 0xDFEF4636, 0xA133C501, 0xE9D3531C, 0xEE353783
+};
+
+static const u_int32_t cast_sbox4[256] = {
+ 0x9DB30420, 0x1FB6E9DE, 0xA7BE7BEF, 0xD273A298,
+ 0x4A4F7BDB, 0x64AD8C57, 0x85510443, 0xFA020ED1,
+ 0x7E287AFF, 0xE60FB663, 0x095F35A1, 0x79EBF120,
+ 0xFD059D43, 0x6497B7B1, 0xF3641F63, 0x241E4ADF,
+ 0x28147F5F, 0x4FA2B8CD, 0xC9430040, 0x0CC32220,
+ 0xFDD30B30, 0xC0A5374F, 0x1D2D00D9, 0x24147B15,
+ 0xEE4D111A, 0x0FCA5167, 0x71FF904C, 0x2D195FFE,
+ 0x1A05645F, 0x0C13FEFE, 0x081B08CA, 0x05170121,
+ 0x80530100, 0xE83E5EFE, 0xAC9AF4F8, 0x7FE72701,
+ 0xD2B8EE5F, 0x06DF4261, 0xBB9E9B8A, 0x7293EA25,
+ 0xCE84FFDF, 0xF5718801, 0x3DD64B04, 0xA26F263B,
+ 0x7ED48400, 0x547EEBE6, 0x446D4CA0, 0x6CF3D6F5,
+ 0x2649ABDF, 0xAEA0C7F5, 0x36338CC1, 0x503F7E93,
+ 0xD3772061, 0x11B638E1, 0x72500E03, 0xF80EB2BB,
+ 0xABE0502E, 0xEC8D77DE, 0x57971E81, 0xE14F6746,
+ 0xC9335400, 0x6920318F, 0x081DBB99, 0xFFC304A5,
+ 0x4D351805, 0x7F3D5CE3, 0xA6C866C6, 0x5D5BCCA9,
+ 0xDAEC6FEA, 0x9F926F91, 0x9F46222F, 0x3991467D,
+ 0xA5BF6D8E, 0x1143C44F, 0x43958302, 0xD0214EEB,
+ 0x022083B8, 0x3FB6180C, 0x18F8931E, 0x281658E6,
+ 0x26486E3E, 0x8BD78A70, 0x7477E4C1, 0xB506E07C,
+ 0xF32D0A25, 0x79098B02, 0xE4EABB81, 0x28123B23,
+ 0x69DEAD38, 0x1574CA16, 0xDF871B62, 0x211C40B7,
+ 0xA51A9EF9, 0x0014377B, 0x041E8AC8, 0x09114003,
+ 0xBD59E4D2, 0xE3D156D5, 0x4FE876D5, 0x2F91A340,
+ 0x557BE8DE, 0x00EAE4A7, 0x0CE5C2EC, 0x4DB4BBA6,
+ 0xE756BDFF, 0xDD3369AC, 0xEC17B035, 0x06572327,
+ 0x99AFC8B0, 0x56C8C391, 0x6B65811C, 0x5E146119,
+ 0x6E85CB75, 0xBE07C002, 0xC2325577, 0x893FF4EC,
+ 0x5BBFC92D, 0xD0EC3B25, 0xB7801AB7, 0x8D6D3B24,
+ 0x20C763EF, 0xC366A5FC, 0x9C382880, 0x0ACE3205,
+ 0xAAC9548A, 0xECA1D7C7, 0x041AFA32, 0x1D16625A,
+ 0x6701902C, 0x9B757A54, 0x31D477F7, 0x9126B031,
+ 0x36CC6FDB, 0xC70B8B46, 0xD9E66A48, 0x56E55A79,
+ 0x026A4CEB, 0x52437EFF, 0x2F8F76B4, 0x0DF980A5,
+ 0x8674CDE3, 0xEDDA04EB, 0x17A9BE04, 0x2C18F4DF,
+ 0xB7747F9D, 0xAB2AF7B4, 0xEFC34D20, 0x2E096B7C,
+ 0x1741A254, 0xE5B6A035, 0x213D42F6, 0x2C1C7C26,
+ 0x61C2F50F, 0x6552DAF9, 0xD2C231F8, 0x25130F69,
+ 0xD8167FA2, 0x0418F2C8, 0x001A96A6, 0x0D1526AB,
+ 0x63315C21, 0x5E0A72EC, 0x49BAFEFD, 0x187908D9,
+ 0x8D0DBD86, 0x311170A7, 0x3E9B640C, 0xCC3E10D7,
+ 0xD5CAD3B6, 0x0CAEC388, 0xF73001E1, 0x6C728AFF,
+ 0x71EAE2A1, 0x1F9AF36E, 0xCFCBD12F, 0xC1DE8417,
+ 0xAC07BE6B, 0xCB44A1D8, 0x8B9B0F56, 0x013988C3,
+ 0xB1C52FCA, 0xB4BE31CD, 0xD8782806, 0x12A3A4E2,
+ 0x6F7DE532, 0x58FD7EB6, 0xD01EE900, 0x24ADFFC2,
+ 0xF4990FC5, 0x9711AAC5, 0x001D7B95, 0x82E5E7D2,
+ 0x109873F6, 0x00613096, 0xC32D9521, 0xADA121FF,
+ 0x29908415, 0x7FBB977F, 0xAF9EB3DB, 0x29C9ED2A,
+ 0x5CE2A465, 0xA730F32C, 0xD0AA3FE8, 0x8A5CC091,
+ 0xD49E2CE7, 0x0CE454A9, 0xD60ACD86, 0x015F1919,
+ 0x77079103, 0xDEA03AF6, 0x78A8565E, 0xDEE356DF,
+ 0x21F05CBE, 0x8B75E387, 0xB3C50651, 0xB8A5C3EF,
+ 0xD8EEB6D2, 0xE523BE77, 0xC2154529, 0x2F69EFDF,
+ 0xAFE67AFB, 0xF470C4B2, 0xF3E0EB5B, 0xD6CC9876,
+ 0x39E4460C, 0x1FDA8538, 0x1987832F, 0xCA007367,
+ 0xA99144F8, 0x296B299E, 0x492FC295, 0x9266BEAB,
+ 0xB5676E69, 0x9BD3DDDA, 0xDF7E052F, 0xDB25701C,
+ 0x1B5E51EE, 0xF65324E6, 0x6AFCE36C, 0x0316CC04,
+ 0x8644213E, 0xB7DC59D0, 0x7965291F, 0xCCD6FD43,
+ 0x41823979, 0x932BCDF6, 0xB657C34D, 0x4EDFD282,
+ 0x7AE5290C, 0x3CB9536B, 0x851E20FE, 0x9833557E,
+ 0x13ECF0B0, 0xD3FFB372, 0x3F85C5C1, 0x0AEF7ED2
+};
+
+static const u_int32_t cast_sbox5[256] = {
+ 0x7EC90C04, 0x2C6E74B9, 0x9B0E66DF, 0xA6337911,
+ 0xB86A7FFF, 0x1DD358F5, 0x44DD9D44, 0x1731167F,
+ 0x08FBF1FA, 0xE7F511CC, 0xD2051B00, 0x735ABA00,
+ 0x2AB722D8, 0x386381CB, 0xACF6243A, 0x69BEFD7A,
+ 0xE6A2E77F, 0xF0C720CD, 0xC4494816, 0xCCF5C180,
+ 0x38851640, 0x15B0A848, 0xE68B18CB, 0x4CAADEFF,
+ 0x5F480A01, 0x0412B2AA, 0x259814FC, 0x41D0EFE2,
+ 0x4E40B48D, 0x248EB6FB, 0x8DBA1CFE, 0x41A99B02,
+ 0x1A550A04, 0xBA8F65CB, 0x7251F4E7, 0x95A51725,
+ 0xC106ECD7, 0x97A5980A, 0xC539B9AA, 0x4D79FE6A,
+ 0xF2F3F763, 0x68AF8040, 0xED0C9E56, 0x11B4958B,
+ 0xE1EB5A88, 0x8709E6B0, 0xD7E07156, 0x4E29FEA7,
+ 0x6366E52D, 0x02D1C000, 0xC4AC8E05, 0x9377F571,
+ 0x0C05372A, 0x578535F2, 0x2261BE02, 0xD642A0C9,
+ 0xDF13A280, 0x74B55BD2, 0x682199C0, 0xD421E5EC,
+ 0x53FB3CE8, 0xC8ADEDB3, 0x28A87FC9, 0x3D959981,
+ 0x5C1FF900, 0xFE38D399, 0x0C4EFF0B, 0x062407EA,
+ 0xAA2F4FB1, 0x4FB96976, 0x90C79505, 0xB0A8A774,
+ 0xEF55A1FF, 0xE59CA2C2, 0xA6B62D27, 0xE66A4263,
+ 0xDF65001F, 0x0EC50966, 0xDFDD55BC, 0x29DE0655,
+ 0x911E739A, 0x17AF8975, 0x32C7911C, 0x89F89468,
+ 0x0D01E980, 0x524755F4, 0x03B63CC9, 0x0CC844B2,
+ 0xBCF3F0AA, 0x87AC36E9, 0xE53A7426, 0x01B3D82B,
+ 0x1A9E7449, 0x64EE2D7E, 0xCDDBB1DA, 0x01C94910,
+ 0xB868BF80, 0x0D26F3FD, 0x9342EDE7, 0x04A5C284,
+ 0x636737B6, 0x50F5B616, 0xF24766E3, 0x8ECA36C1,
+ 0x136E05DB, 0xFEF18391, 0xFB887A37, 0xD6E7F7D4,
+ 0xC7FB7DC9, 0x3063FCDF, 0xB6F589DE, 0xEC2941DA,
+ 0x26E46695, 0xB7566419, 0xF654EFC5, 0xD08D58B7,
+ 0x48925401, 0xC1BACB7F, 0xE5FF550F, 0xB6083049,
+ 0x5BB5D0E8, 0x87D72E5A, 0xAB6A6EE1, 0x223A66CE,
+ 0xC62BF3CD, 0x9E0885F9, 0x68CB3E47, 0x086C010F,
+ 0xA21DE820, 0xD18B69DE, 0xF3F65777, 0xFA02C3F6,
+ 0x407EDAC3, 0xCBB3D550, 0x1793084D, 0xB0D70EBA,
+ 0x0AB378D5, 0xD951FB0C, 0xDED7DA56, 0x4124BBE4,
+ 0x94CA0B56, 0x0F5755D1, 0xE0E1E56E, 0x6184B5BE,
+ 0x580A249F, 0x94F74BC0, 0xE327888E, 0x9F7B5561,
+ 0xC3DC0280, 0x05687715, 0x646C6BD7, 0x44904DB3,
+ 0x66B4F0A3, 0xC0F1648A, 0x697ED5AF, 0x49E92FF6,
+ 0x309E374F, 0x2CB6356A, 0x85808573, 0x4991F840,
+ 0x76F0AE02, 0x083BE84D, 0x28421C9A, 0x44489406,
+ 0x736E4CB8, 0xC1092910, 0x8BC95FC6, 0x7D869CF4,
+ 0x134F616F, 0x2E77118D, 0xB31B2BE1, 0xAA90B472,
+ 0x3CA5D717, 0x7D161BBA, 0x9CAD9010, 0xAF462BA2,
+ 0x9FE459D2, 0x45D34559, 0xD9F2DA13, 0xDBC65487,
+ 0xF3E4F94E, 0x176D486F, 0x097C13EA, 0x631DA5C7,
+ 0x445F7382, 0x175683F4, 0xCDC66A97, 0x70BE0288,
+ 0xB3CDCF72, 0x6E5DD2F3, 0x20936079, 0x459B80A5,
+ 0xBE60E2DB, 0xA9C23101, 0xEBA5315C, 0x224E42F2,
+ 0x1C5C1572, 0xF6721B2C, 0x1AD2FFF3, 0x8C25404E,
+ 0x324ED72F, 0x4067B7FD, 0x0523138E, 0x5CA3BC78,
+ 0xDC0FD66E, 0x75922283, 0x784D6B17, 0x58EBB16E,
+ 0x44094F85, 0x3F481D87, 0xFCFEAE7B, 0x77B5FF76,
+ 0x8C2302BF, 0xAAF47556, 0x5F46B02A, 0x2B092801,
+ 0x3D38F5F7, 0x0CA81F36, 0x52AF4A8A, 0x66D5E7C0,
+ 0xDF3B0874, 0x95055110, 0x1B5AD7A8, 0xF61ED5AD,
+ 0x6CF6E479, 0x20758184, 0xD0CEFA65, 0x88F7BE58,
+ 0x4A046826, 0x0FF6F8F3, 0xA09C7F70, 0x5346ABA0,
+ 0x5CE96C28, 0xE176EDA3, 0x6BAC307F, 0x376829D2,
+ 0x85360FA9, 0x17E3FE2A, 0x24B79767, 0xF5A96B20,
+ 0xD6CD2595, 0x68FF1EBF, 0x7555442C, 0xF19F06BE,
+ 0xF9E0659A, 0xEEB9491D, 0x34010718, 0xBB30CAB8,
+ 0xE822FE15, 0x88570983, 0x750E6249, 0xDA627E55,
+ 0x5E76FFA8, 0xB1534546, 0x6D47DE08, 0xEFE9E7D4
+};
+
+static const u_int32_t cast_sbox6[256] = {
+ 0xF6FA8F9D, 0x2CAC6CE1, 0x4CA34867, 0xE2337F7C,
+ 0x95DB08E7, 0x016843B4, 0xECED5CBC, 0x325553AC,
+ 0xBF9F0960, 0xDFA1E2ED, 0x83F0579D, 0x63ED86B9,
+ 0x1AB6A6B8, 0xDE5EBE39, 0xF38FF732, 0x8989B138,
+ 0x33F14961, 0xC01937BD, 0xF506C6DA, 0xE4625E7E,
+ 0xA308EA99, 0x4E23E33C, 0x79CBD7CC, 0x48A14367,
+ 0xA3149619, 0xFEC94BD5, 0xA114174A, 0xEAA01866,
+ 0xA084DB2D, 0x09A8486F, 0xA888614A, 0x2900AF98,
+ 0x01665991, 0xE1992863, 0xC8F30C60, 0x2E78EF3C,
+ 0xD0D51932, 0xCF0FEC14, 0xF7CA07D2, 0xD0A82072,
+ 0xFD41197E, 0x9305A6B0, 0xE86BE3DA, 0x74BED3CD,
+ 0x372DA53C, 0x4C7F4448, 0xDAB5D440, 0x6DBA0EC3,
+ 0x083919A7, 0x9FBAEED9, 0x49DBCFB0, 0x4E670C53,
+ 0x5C3D9C01, 0x64BDB941, 0x2C0E636A, 0xBA7DD9CD,
+ 0xEA6F7388, 0xE70BC762, 0x35F29ADB, 0x5C4CDD8D,
+ 0xF0D48D8C, 0xB88153E2, 0x08A19866, 0x1AE2EAC8,
+ 0x284CAF89, 0xAA928223, 0x9334BE53, 0x3B3A21BF,
+ 0x16434BE3, 0x9AEA3906, 0xEFE8C36E, 0xF890CDD9,
+ 0x80226DAE, 0xC340A4A3, 0xDF7E9C09, 0xA694A807,
+ 0x5B7C5ECC, 0x221DB3A6, 0x9A69A02F, 0x68818A54,
+ 0xCEB2296F, 0x53C0843A, 0xFE893655, 0x25BFE68A,
+ 0xB4628ABC, 0xCF222EBF, 0x25AC6F48, 0xA9A99387,
+ 0x53BDDB65, 0xE76FFBE7, 0xE967FD78, 0x0BA93563,
+ 0x8E342BC1, 0xE8A11BE9, 0x4980740D, 0xC8087DFC,
+ 0x8DE4BF99, 0xA11101A0, 0x7FD37975, 0xDA5A26C0,
+ 0xE81F994F, 0x9528CD89, 0xFD339FED, 0xB87834BF,
+ 0x5F04456D, 0x22258698, 0xC9C4C83B, 0x2DC156BE,
+ 0x4F628DAA, 0x57F55EC5, 0xE2220ABE, 0xD2916EBF,
+ 0x4EC75B95, 0x24F2C3C0, 0x42D15D99, 0xCD0D7FA0,
+ 0x7B6E27FF, 0xA8DC8AF0, 0x7345C106, 0xF41E232F,
+ 0x35162386, 0xE6EA8926, 0x3333B094, 0x157EC6F2,
+ 0x372B74AF, 0x692573E4, 0xE9A9D848, 0xF3160289,
+ 0x3A62EF1D, 0xA787E238, 0xF3A5F676, 0x74364853,
+ 0x20951063, 0x4576698D, 0xB6FAD407, 0x592AF950,
+ 0x36F73523, 0x4CFB6E87, 0x7DA4CEC0, 0x6C152DAA,
+ 0xCB0396A8, 0xC50DFE5D, 0xFCD707AB, 0x0921C42F,
+ 0x89DFF0BB, 0x5FE2BE78, 0x448F4F33, 0x754613C9,
+ 0x2B05D08D, 0x48B9D585, 0xDC049441, 0xC8098F9B,
+ 0x7DEDE786, 0xC39A3373, 0x42410005, 0x6A091751,
+ 0x0EF3C8A6, 0x890072D6, 0x28207682, 0xA9A9F7BE,
+ 0xBF32679D, 0xD45B5B75, 0xB353FD00, 0xCBB0E358,
+ 0x830F220A, 0x1F8FB214, 0xD372CF08, 0xCC3C4A13,
+ 0x8CF63166, 0x061C87BE, 0x88C98F88, 0x6062E397,
+ 0x47CF8E7A, 0xB6C85283, 0x3CC2ACFB, 0x3FC06976,
+ 0x4E8F0252, 0x64D8314D, 0xDA3870E3, 0x1E665459,
+ 0xC10908F0, 0x513021A5, 0x6C5B68B7, 0x822F8AA0,
+ 0x3007CD3E, 0x74719EEF, 0xDC872681, 0x073340D4,
+ 0x7E432FD9, 0x0C5EC241, 0x8809286C, 0xF592D891,
+ 0x08A930F6, 0x957EF305, 0xB7FBFFBD, 0xC266E96F,
+ 0x6FE4AC98, 0xB173ECC0, 0xBC60B42A, 0x953498DA,
+ 0xFBA1AE12, 0x2D4BD736, 0x0F25FAAB, 0xA4F3FCEB,
+ 0xE2969123, 0x257F0C3D, 0x9348AF49, 0x361400BC,
+ 0xE8816F4A, 0x3814F200, 0xA3F94043, 0x9C7A54C2,
+ 0xBC704F57, 0xDA41E7F9, 0xC25AD33A, 0x54F4A084,
+ 0xB17F5505, 0x59357CBE, 0xEDBD15C8, 0x7F97C5AB,
+ 0xBA5AC7B5, 0xB6F6DEAF, 0x3A479C3A, 0x5302DA25,
+ 0x653D7E6A, 0x54268D49, 0x51A477EA, 0x5017D55B,
+ 0xD7D25D88, 0x44136C76, 0x0404A8C8, 0xB8E5A121,
+ 0xB81A928A, 0x60ED5869, 0x97C55B96, 0xEAEC991B,
+ 0x29935913, 0x01FDB7F1, 0x088E8DFA, 0x9AB6F6F5,
+ 0x3B4CBF9F, 0x4A5DE3AB, 0xE6051D35, 0xA0E1D855,
+ 0xD36B4CF1, 0xF544EDEB, 0xB0E93524, 0xBEBB8FBD,
+ 0xA2D762CF, 0x49C92F54, 0x38B5F331, 0x7128A454,
+ 0x48392905, 0xA65B1DB8, 0x851C97BD, 0xD675CF2F
+};
+
+static const u_int32_t cast_sbox7[256] = {
+ 0x85E04019, 0x332BF567, 0x662DBFFF, 0xCFC65693,
+ 0x2A8D7F6F, 0xAB9BC912, 0xDE6008A1, 0x2028DA1F,
+ 0x0227BCE7, 0x4D642916, 0x18FAC300, 0x50F18B82,
+ 0x2CB2CB11, 0xB232E75C, 0x4B3695F2, 0xB28707DE,
+ 0xA05FBCF6, 0xCD4181E9, 0xE150210C, 0xE24EF1BD,
+ 0xB168C381, 0xFDE4E789, 0x5C79B0D8, 0x1E8BFD43,
+ 0x4D495001, 0x38BE4341, 0x913CEE1D, 0x92A79C3F,
+ 0x089766BE, 0xBAEEADF4, 0x1286BECF, 0xB6EACB19,
+ 0x2660C200, 0x7565BDE4, 0x64241F7A, 0x8248DCA9,
+ 0xC3B3AD66, 0x28136086, 0x0BD8DFA8, 0x356D1CF2,
+ 0x107789BE, 0xB3B2E9CE, 0x0502AA8F, 0x0BC0351E,
+ 0x166BF52A, 0xEB12FF82, 0xE3486911, 0xD34D7516,
+ 0x4E7B3AFF, 0x5F43671B, 0x9CF6E037, 0x4981AC83,
+ 0x334266CE, 0x8C9341B7, 0xD0D854C0, 0xCB3A6C88,
+ 0x47BC2829, 0x4725BA37, 0xA66AD22B, 0x7AD61F1E,
+ 0x0C5CBAFA, 0x4437F107, 0xB6E79962, 0x42D2D816,
+ 0x0A961288, 0xE1A5C06E, 0x13749E67, 0x72FC081A,
+ 0xB1D139F7, 0xF9583745, 0xCF19DF58, 0xBEC3F756,
+ 0xC06EBA30, 0x07211B24, 0x45C28829, 0xC95E317F,
+ 0xBC8EC511, 0x38BC46E9, 0xC6E6FA14, 0xBAE8584A,
+ 0xAD4EBC46, 0x468F508B, 0x7829435F, 0xF124183B,
+ 0x821DBA9F, 0xAFF60FF4, 0xEA2C4E6D, 0x16E39264,
+ 0x92544A8B, 0x009B4FC3, 0xABA68CED, 0x9AC96F78,
+ 0x06A5B79A, 0xB2856E6E, 0x1AEC3CA9, 0xBE838688,
+ 0x0E0804E9, 0x55F1BE56, 0xE7E5363B, 0xB3A1F25D,
+ 0xF7DEBB85, 0x61FE033C, 0x16746233, 0x3C034C28,
+ 0xDA6D0C74, 0x79AAC56C, 0x3CE4E1AD, 0x51F0C802,
+ 0x98F8F35A, 0x1626A49F, 0xEED82B29, 0x1D382FE3,
+ 0x0C4FB99A, 0xBB325778, 0x3EC6D97B, 0x6E77A6A9,
+ 0xCB658B5C, 0xD45230C7, 0x2BD1408B, 0x60C03EB7,
+ 0xB9068D78, 0xA33754F4, 0xF430C87D, 0xC8A71302,
+ 0xB96D8C32, 0xEBD4E7BE, 0xBE8B9D2D, 0x7979FB06,
+ 0xE7225308, 0x8B75CF77, 0x11EF8DA4, 0xE083C858,
+ 0x8D6B786F, 0x5A6317A6, 0xFA5CF7A0, 0x5DDA0033,
+ 0xF28EBFB0, 0xF5B9C310, 0xA0EAC280, 0x08B9767A,
+ 0xA3D9D2B0, 0x79D34217, 0x021A718D, 0x9AC6336A,
+ 0x2711FD60, 0x438050E3, 0x069908A8, 0x3D7FEDC4,
+ 0x826D2BEF, 0x4EEB8476, 0x488DCF25, 0x36C9D566,
+ 0x28E74E41, 0xC2610ACA, 0x3D49A9CF, 0xBAE3B9DF,
+ 0xB65F8DE6, 0x92AEAF64, 0x3AC7D5E6, 0x9EA80509,
+ 0xF22B017D, 0xA4173F70, 0xDD1E16C3, 0x15E0D7F9,
+ 0x50B1B887, 0x2B9F4FD5, 0x625ABA82, 0x6A017962,
+ 0x2EC01B9C, 0x15488AA9, 0xD716E740, 0x40055A2C,
+ 0x93D29A22, 0xE32DBF9A, 0x058745B9, 0x3453DC1E,
+ 0xD699296E, 0x496CFF6F, 0x1C9F4986, 0xDFE2ED07,
+ 0xB87242D1, 0x19DE7EAE, 0x053E561A, 0x15AD6F8C,
+ 0x66626C1C, 0x7154C24C, 0xEA082B2A, 0x93EB2939,
+ 0x17DCB0F0, 0x58D4F2AE, 0x9EA294FB, 0x52CF564C,
+ 0x9883FE66, 0x2EC40581, 0x763953C3, 0x01D6692E,
+ 0xD3A0C108, 0xA1E7160E, 0xE4F2DFA6, 0x693ED285,
+ 0x74904698, 0x4C2B0EDD, 0x4F757656, 0x5D393378,
+ 0xA132234F, 0x3D321C5D, 0xC3F5E194, 0x4B269301,
+ 0xC79F022F, 0x3C997E7E, 0x5E4F9504, 0x3FFAFBBD,
+ 0x76F7AD0E, 0x296693F4, 0x3D1FCE6F, 0xC61E45BE,
+ 0xD3B5AB34, 0xF72BF9B7, 0x1B0434C0, 0x4E72B567,
+ 0x5592A33D, 0xB5229301, 0xCFD2A87F, 0x60AEB767,
+ 0x1814386B, 0x30BCC33D, 0x38A0C07D, 0xFD1606F2,
+ 0xC363519B, 0x589DD390, 0x5479F8E6, 0x1CB8D647,
+ 0x97FD61A9, 0xEA7759F4, 0x2D57539D, 0x569A58CF,
+ 0xE84E63AD, 0x462E1B78, 0x6580F87E, 0xF3817914,
+ 0x91DA55F4, 0x40A230F3, 0xD1988F35, 0xB6E318D2,
+ 0x3FFA50BC, 0x3D40F021, 0xC3C0BDAE, 0x4958C24C,
+ 0x518F36B2, 0x84B1D370, 0x0FEDCE83, 0x878DDADA,
+ 0xF2A279C7, 0x94E01BE8, 0x90716F4B, 0x954B8AA3
+};
+
+static const u_int32_t cast_sbox8[256] = {
+ 0xE216300D, 0xBBDDFFFC, 0xA7EBDABD, 0x35648095,
+ 0x7789F8B7, 0xE6C1121B, 0x0E241600, 0x052CE8B5,
+ 0x11A9CFB0, 0xE5952F11, 0xECE7990A, 0x9386D174,
+ 0x2A42931C, 0x76E38111, 0xB12DEF3A, 0x37DDDDFC,
+ 0xDE9ADEB1, 0x0A0CC32C, 0xBE197029, 0x84A00940,
+ 0xBB243A0F, 0xB4D137CF, 0xB44E79F0, 0x049EEDFD,
+ 0x0B15A15D, 0x480D3168, 0x8BBBDE5A, 0x669DED42,
+ 0xC7ECE831, 0x3F8F95E7, 0x72DF191B, 0x7580330D,
+ 0x94074251, 0x5C7DCDFA, 0xABBE6D63, 0xAA402164,
+ 0xB301D40A, 0x02E7D1CA, 0x53571DAE, 0x7A3182A2,
+ 0x12A8DDEC, 0xFDAA335D, 0x176F43E8, 0x71FB46D4,
+ 0x38129022, 0xCE949AD4, 0xB84769AD, 0x965BD862,
+ 0x82F3D055, 0x66FB9767, 0x15B80B4E, 0x1D5B47A0,
+ 0x4CFDE06F, 0xC28EC4B8, 0x57E8726E, 0x647A78FC,
+ 0x99865D44, 0x608BD593, 0x6C200E03, 0x39DC5FF6,
+ 0x5D0B00A3, 0xAE63AFF2, 0x7E8BD632, 0x70108C0C,
+ 0xBBD35049, 0x2998DF04, 0x980CF42A, 0x9B6DF491,
+ 0x9E7EDD53, 0x06918548, 0x58CB7E07, 0x3B74EF2E,
+ 0x522FFFB1, 0xD24708CC, 0x1C7E27CD, 0xA4EB215B,
+ 0x3CF1D2E2, 0x19B47A38, 0x424F7618, 0x35856039,
+ 0x9D17DEE7, 0x27EB35E6, 0xC9AFF67B, 0x36BAF5B8,
+ 0x09C467CD, 0xC18910B1, 0xE11DBF7B, 0x06CD1AF8,
+ 0x7170C608, 0x2D5E3354, 0xD4DE495A, 0x64C6D006,
+ 0xBCC0C62C, 0x3DD00DB3, 0x708F8F34, 0x77D51B42,
+ 0x264F620F, 0x24B8D2BF, 0x15C1B79E, 0x46A52564,
+ 0xF8D7E54E, 0x3E378160, 0x7895CDA5, 0x859C15A5,
+ 0xE6459788, 0xC37BC75F, 0xDB07BA0C, 0x0676A3AB,
+ 0x7F229B1E, 0x31842E7B, 0x24259FD7, 0xF8BEF472,
+ 0x835FFCB8, 0x6DF4C1F2, 0x96F5B195, 0xFD0AF0FC,
+ 0xB0FE134C, 0xE2506D3D, 0x4F9B12EA, 0xF215F225,
+ 0xA223736F, 0x9FB4C428, 0x25D04979, 0x34C713F8,
+ 0xC4618187, 0xEA7A6E98, 0x7CD16EFC, 0x1436876C,
+ 0xF1544107, 0xBEDEEE14, 0x56E9AF27, 0xA04AA441,
+ 0x3CF7C899, 0x92ECBAE6, 0xDD67016D, 0x151682EB,
+ 0xA842EEDF, 0xFDBA60B4, 0xF1907B75, 0x20E3030F,
+ 0x24D8C29E, 0xE139673B, 0xEFA63FB8, 0x71873054,
+ 0xB6F2CF3B, 0x9F326442, 0xCB15A4CC, 0xB01A4504,
+ 0xF1E47D8D, 0x844A1BE5, 0xBAE7DFDC, 0x42CBDA70,
+ 0xCD7DAE0A, 0x57E85B7A, 0xD53F5AF6, 0x20CF4D8C,
+ 0xCEA4D428, 0x79D130A4, 0x3486EBFB, 0x33D3CDDC,
+ 0x77853B53, 0x37EFFCB5, 0xC5068778, 0xE580B3E6,
+ 0x4E68B8F4, 0xC5C8B37E, 0x0D809EA2, 0x398FEB7C,
+ 0x132A4F94, 0x43B7950E, 0x2FEE7D1C, 0x223613BD,
+ 0xDD06CAA2, 0x37DF932B, 0xC4248289, 0xACF3EBC3,
+ 0x5715F6B7, 0xEF3478DD, 0xF267616F, 0xC148CBE4,
+ 0x9052815E, 0x5E410FAB, 0xB48A2465, 0x2EDA7FA4,
+ 0xE87B40E4, 0xE98EA084, 0x5889E9E1, 0xEFD390FC,
+ 0xDD07D35B, 0xDB485694, 0x38D7E5B2, 0x57720101,
+ 0x730EDEBC, 0x5B643113, 0x94917E4F, 0x503C2FBA,
+ 0x646F1282, 0x7523D24A, 0xE0779695, 0xF9C17A8F,
+ 0x7A5B2121, 0xD187B896, 0x29263A4D, 0xBA510CDF,
+ 0x81F47C9F, 0xAD1163ED, 0xEA7B5965, 0x1A00726E,
+ 0x11403092, 0x00DA6D77, 0x4A0CDD61, 0xAD1F4603,
+ 0x605BDFB0, 0x9EEDC364, 0x22EBE6A8, 0xCEE7D28A,
+ 0xA0E736A0, 0x5564A6B9, 0x10853209, 0xC7EB8F37,
+ 0x2DE705CA, 0x8951570F, 0xDF09822B, 0xBD691A6C,
+ 0xAA12E4F2, 0x87451C0F, 0xE0F6A27A, 0x3ADA4819,
+ 0x4CF1764F, 0x0D771C2B, 0x67CDB156, 0x350D8384,
+ 0x5938FA0F, 0x42399EF3, 0x36997B07, 0x0E84093D,
+ 0x4AA93E61, 0x8360D87B, 0x1FA98B0C, 0x1149382C,
+ 0xE97625A5, 0x0614D1B7, 0x0E25244B, 0x0C768347,
+ 0x589E8D82, 0x0D2059D1, 0xA466BB1E, 0xF8DA0A82,
+ 0x04F19130, 0xBA6E4EC0, 0x99265164, 0x1EE7230D,
+ 0x50B2AD80, 0xEAEE6801, 0x8DB2A283, 0xEA8BF59E
+};
+
diff --git a/sys/opencrypto/criov.c b/sys/opencrypto/criov.c
new file mode 100644
index 0000000..f8799f9
--- /dev/null
+++ b/sys/opencrypto/criov.c
@@ -0,0 +1,137 @@
+/* $FreeBSD$ */
+/* $OpenBSD: criov.c,v 1.9 2002/01/29 15:48:29 jason Exp $ */
+
+/*
+ * Copyright (c) 1999 Theo de Raadt
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/errno.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/uio.h>
+
+#include <opencrypto/cryptodev.h>
+
+void
+cuio_copydata(struct uio* uio, int off, int len, caddr_t cp)
+{
+ struct iovec *iov = uio->uio_iov;
+ int iol = uio->uio_iovcnt;
+ unsigned count;
+
+ if (off < 0)
+ panic("cuio_copydata: off %d < 0", off);
+ if (len < 0)
+ panic("cuio_copydata: len %d < 0", len);
+ while (off > 0) {
+ if (iol == 0)
+ panic("iov_copydata: empty in skip");
+ if (off < iov->iov_len)
+ break;
+ off -= iov->iov_len;
+ iol--;
+ iov++;
+ }
+ while (len > 0) {
+ if (iol == 0)
+ panic("cuio_copydata: empty");
+ count = min(iov->iov_len - off, len);
+ bcopy(((caddr_t)iov->iov_base) + off, cp, count);
+ len -= count;
+ cp += count;
+ off = 0;
+ iol--;
+ iov++;
+ }
+}
+
+void
+cuio_copyback(struct uio* uio, int off, int len, caddr_t cp)
+{
+ struct iovec *iov = uio->uio_iov;
+ int iol = uio->uio_iovcnt;
+ unsigned count;
+
+ if (off < 0)
+ panic("cuio_copyback: off %d < 0", off);
+ if (len < 0)
+ panic("cuio_copyback: len %d < 0", len);
+ while (off > 0) {
+ if (iol == 0)
+ panic("cuio_copyback: empty in skip");
+ if (off < iov->iov_len)
+ break;
+ off -= iov->iov_len;
+ iol--;
+ iov++;
+ }
+ while (len > 0) {
+ if (iol == 0)
+ panic("uio_copyback: empty");
+ count = min(iov->iov_len - off, len);
+ bcopy(cp, ((caddr_t)iov->iov_base) + off, count);
+ len -= count;
+ cp += count;
+ off = 0;
+ iol--;
+ iov++;
+ }
+}
+
+/*
+ * Return a pointer to iov/offset of location in iovec list.
+ */
+struct iovec *
+cuio_getptr(struct uio *uio, int loc, int *off)
+{
+ struct iovec *iov = uio->uio_iov;
+ int iol = uio->uio_iovcnt;
+
+ while (loc >= 0) {
+ /* Normal end of search */
+ if (loc < iov->iov_len) {
+ *off = loc;
+ return (iov);
+ }
+
+ loc -= iov->iov_len;
+ if (iol == 0) {
+ if (loc == 0) {
+ /* Point at the end of valid data */
+ *off = iov->iov_len;
+ return (iov);
+ } else
+ return (NULL);
+ } else {
+ iov++, iol--;
+ }
+ }
+
+ return (NULL);
+}
diff --git a/sys/opencrypto/crmbuf.c b/sys/opencrypto/crmbuf.c
new file mode 100644
index 0000000..a57322b
--- /dev/null
+++ b/sys/opencrypto/crmbuf.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2002 Somebody. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_param.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+
+/*
+ * Miscellaneous mbuf routines that belong in uipc_mbuf.c but
+ * are kept private to the crypto support for now.
+ */
+extern int m_apply(struct mbuf *m, int off, int len,
+ int (*f)(caddr_t, caddr_t, unsigned int), caddr_t fstate);
+extern struct mbuf * m_getptr(struct mbuf *m, int loc, int *off);
+
+/*
+ * Apply function f to the data in an mbuf chain starting "off" bytes from the
+ * beginning, continuing for "len" bytes.
+ */
+int
+m_apply(struct mbuf *m, int off, int len, int (*f)(caddr_t, caddr_t, unsigned int), caddr_t fstate)
+{
+ int rval;
+ unsigned int count;
+
+ if (len < 0)
+ panic("m_apply: len %d < 0", len);
+ if (off < 0)
+ panic("m_apply: off %d < 0", off);
+ while (off > 0) {
+ if (m == NULL)
+ panic("m_apply: null mbuf in skip");
+ if (off < m->m_len)
+ break;
+ off -= m->m_len;
+ m = m->m_next;
+ }
+ while (len > 0) {
+ if (m == NULL)
+ panic("m_apply: null mbuf");
+ count = min(m->m_len - off, len);
+
+ rval = f(fstate, mtod(m, caddr_t) + off, count);
+ if (rval)
+ return (rval);
+
+ len -= count;
+ off = 0;
+ m = m->m_next;
+ }
+
+ return (0);
+}
+
+/*
+ * Return a pointer to mbuf/offset of location in mbuf chain.
+ */
+struct mbuf *
+m_getptr(struct mbuf *m, int loc, int *off)
+{
+ while (loc >= 0) {
+ /* Normal end of search */
+ if (m->m_len > loc) {
+ *off = loc;
+ return (m);
+ }
+ else {
+ loc -= m->m_len;
+
+ if (m->m_next == NULL) {
+ if (loc == 0) {
+ /* Point at the end of valid data */
+ *off = m->m_len;
+ return (m);
+ }
+ else
+ return (NULL);
+ }
+ else
+ m = m->m_next;
+ }
+ }
+
+ return (NULL);
+}
diff --git a/sys/opencrypto/crypto.c b/sys/opencrypto/crypto.c
new file mode 100644
index 0000000..23869b3
--- /dev/null
+++ b/sys/opencrypto/crypto.c
@@ -0,0 +1,936 @@
+/* $FreeBSD$ */
+/* $OpenBSD: crypto.c,v 1.38 2002/06/11 11:14:29 beck Exp $ */
+/*
+ * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
+ *
+ * This code was written by Angelos D. Keromytis in Athens, Greece, in
+ * February 2000. Network Security Technologies Inc. (NSTI) kindly
+ * supported the development of this code.
+ *
+ * Copyright (c) 2000, 2001 Angelos D. Keromytis
+ *
+ * Permission to use, copy, and modify this software with or without fee
+ * is hereby granted, provided that this entire notice is included in
+ * all source code copies of any software which is or includes a copy or
+ * modification of this software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+ * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/eventhandler.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+
+#include <vm/uma.h>
+#include <opencrypto/cryptodev.h>
+
+#define SESID2HID(sid) (((sid) >> 32) & 0xffffffff)
+
+/*
+ * Crypto drivers register themselves by allocating a slot in the
+ * crypto_drivers table with crypto_get_driverid() and then registering
+ * each algorithm they support with crypto_register() and crypto_kregister().
+ */
+static struct mtx crypto_drivers_mtx; /* lock on driver table */
+#define CRYPTO_DRIVER_LOCK() mtx_lock(&crypto_drivers_mtx)
+#define CRYPTO_DRIVER_UNLOCK() mtx_unlock(&crypto_drivers_mtx)
+static struct cryptocap *crypto_drivers = NULL;
+static int crypto_drivers_num = 0;
+
+/*
+ * There are two queues for crypto requests; one for symmetric (e.g.
+ * cipher) operations and one for asymmetric (e.g. MOD)operations.
+ * A single mutex is used to lock access to both queues. We could
+ * have one per-queue but having one simplifies handling of block/unblock
+ * operations.
+ */
+static TAILQ_HEAD(,cryptop) crp_q; /* request queues */
+static TAILQ_HEAD(,cryptkop) crp_kq;
+static struct mtx crypto_q_mtx;
+#define CRYPTO_Q_LOCK() mtx_lock(&crypto_q_mtx)
+#define CRYPTO_Q_UNLOCK() mtx_unlock(&crypto_q_mtx)
+
+/*
+ * There are two queues for processing completed crypto requests; one
+ * for the symmetric and one for the asymmetric ops. We only need one
+ * but have two to avoid type futzing (cryptop vs. cryptkop). A single
+ * mutex is used to lock access to both queues. Note that this lock
+ * must be separate from the lock on request queues to insure driver
+ * callbacks don't generate lock order reversals.
+ */
+static TAILQ_HEAD(,cryptop) crp_ret_q; /* callback queues */
+static TAILQ_HEAD(,cryptkop) crp_ret_kq;
+static struct mtx crypto_ret_q_mtx;
+#define CRYPTO_RETQ_LOCK() mtx_lock(&crypto_ret_q_mtx)
+#define CRYPTO_RETQ_UNLOCK() mtx_unlock(&crypto_ret_q_mtx)
+
+static uma_zone_t cryptop_zone;
+static uma_zone_t cryptodesc_zone;
+
+int crypto_usercrypto = 1; /* userland may open /dev/crypto */
+SYSCTL_INT(_kern, OID_AUTO, usercrypto, CTLFLAG_RW,
+ &crypto_usercrypto, 0,
+ "Enable/disable user-mode access to crypto support");
+int crypto_userasymcrypto = 1; /* userland may do asym crypto reqs */
+SYSCTL_INT(_kern, OID_AUTO, userasymcrypto, CTLFLAG_RW,
+ &crypto_userasymcrypto, 0,
+ "Enable/disable user-mode access to asymmetric crypto support");
+int crypto_devallowsoft = 0; /* only use hardware crypto for asym */
+SYSCTL_INT(_kern, OID_AUTO, cryptodevallowsoft, CTLFLAG_RW,
+ &crypto_devallowsoft, 0,
+ "Enable/disable use of software asym crypto support");
+
+MALLOC_DEFINE(M_CRYPTO_DATA, "crypto", "crypto session records");
+
+static void
+crypto_init(void)
+{
+ cryptop_zone = uma_zcreate("cryptop", sizeof (struct cryptop),
+ 0, 0, 0, 0,
+ UMA_ALIGN_PTR, UMA_ZONE_ZINIT);
+ cryptodesc_zone = uma_zcreate("cryptodesc", sizeof (struct cryptodesc),
+ 0, 0, 0, 0,
+ UMA_ALIGN_PTR, UMA_ZONE_ZINIT);
+ if (cryptodesc_zone == NULL || cryptop_zone == NULL)
+ panic("cannot setup crypto zones");
+
+ mtx_init(&crypto_drivers_mtx, "crypto driver table",
+ NULL, MTX_DEF|MTX_QUIET);
+
+ crypto_drivers_num = CRYPTO_DRIVERS_INITIAL;
+ crypto_drivers = malloc(crypto_drivers_num *
+ sizeof(struct cryptocap), M_CRYPTO_DATA, M_NOWAIT | M_ZERO);
+ if (crypto_drivers == NULL)
+ panic("cannot setup crypto drivers");
+
+ TAILQ_INIT(&crp_q);
+ TAILQ_INIT(&crp_kq);
+ mtx_init(&crypto_q_mtx, "crypto op queues", NULL, MTX_DEF);
+
+ TAILQ_INIT(&crp_ret_q);
+ TAILQ_INIT(&crp_ret_kq);
+ mtx_init(&crypto_ret_q_mtx, "crypto return queues", NULL, MTX_DEF);
+}
+SYSINIT(crypto_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, crypto_init, NULL)
+
+/*
+ * Create a new session.
+ */
+int
+crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int hard)
+{
+ struct cryptoini *cr;
+ u_int32_t hid, lid;
+ int err = EINVAL;
+
+ CRYPTO_DRIVER_LOCK();
+
+ if (crypto_drivers == NULL)
+ goto done;
+
+ /*
+ * The algorithm we use here is pretty stupid; just use the
+ * first driver that supports all the algorithms we need.
+ *
+ * XXX We need more smarts here (in real life too, but that's
+ * XXX another story altogether).
+ */
+
+ for (hid = 0; hid < crypto_drivers_num; hid++) {
+ /*
+ * If it's not initialized or has remaining sessions
+ * referencing it, skip.
+ */
+ if (crypto_drivers[hid].cc_newsession == NULL ||
+ (crypto_drivers[hid].cc_flags & CRYPTOCAP_F_CLEANUP))
+ continue;
+
+ /* Hardware required -- ignore software drivers. */
+ if (hard > 0 &&
+ (crypto_drivers[hid].cc_flags & CRYPTOCAP_F_SOFTWARE))
+ continue;
+ /* Software required -- ignore hardware drivers. */
+ if (hard < 0 &&
+ (crypto_drivers[hid].cc_flags & CRYPTOCAP_F_SOFTWARE) == 0)
+ continue;
+
+ /* See if all the algorithms are supported. */
+ for (cr = cri; cr; cr = cr->cri_next)
+ if (crypto_drivers[hid].cc_alg[cr->cri_alg] == 0)
+ break;
+
+ if (cr == NULL) {
+ /* Ok, all algorithms are supported. */
+
+ /*
+ * Can't do everything in one session.
+ *
+ * XXX Fix this. We need to inject a "virtual" session layer right
+ * XXX about here.
+ */
+
+ /* Call the driver initialization routine. */
+ lid = hid; /* Pass the driver ID. */
+ err = crypto_drivers[hid].cc_newsession(
+ crypto_drivers[hid].cc_arg, &lid, cri);
+ if (err == 0) {
+ (*sid) = hid;
+ (*sid) <<= 32;
+ (*sid) |= (lid & 0xffffffff);
+ crypto_drivers[hid].cc_sessions++;
+ }
+ break;
+ }
+ }
+done:
+ CRYPTO_DRIVER_UNLOCK();
+ return err;
+}
+
+/*
+ * Delete an existing session (or a reserved session on an unregistered
+ * driver).
+ */
+int
+crypto_freesession(u_int64_t sid)
+{
+ u_int32_t hid;
+ int err;
+
+ CRYPTO_DRIVER_LOCK();
+
+ if (crypto_drivers == NULL) {
+ err = EINVAL;
+ goto done;
+ }
+
+ /* Determine two IDs. */
+ hid = SESID2HID(sid);
+
+ if (hid >= crypto_drivers_num) {
+ err = ENOENT;
+ goto done;
+ }
+
+ if (crypto_drivers[hid].cc_sessions)
+ crypto_drivers[hid].cc_sessions--;
+
+ /* Call the driver cleanup routine, if available. */
+ if (crypto_drivers[hid].cc_freesession)
+ err = crypto_drivers[hid].cc_freesession(
+ crypto_drivers[hid].cc_arg, sid);
+ else
+ err = 0;
+
+ /*
+ * If this was the last session of a driver marked as invalid,
+ * make the entry available for reuse.
+ */
+ if ((crypto_drivers[hid].cc_flags & CRYPTOCAP_F_CLEANUP) &&
+ crypto_drivers[hid].cc_sessions == 0)
+ bzero(&crypto_drivers[hid], sizeof(struct cryptocap));
+
+done:
+ CRYPTO_DRIVER_UNLOCK();
+ return err;
+}
+
+/*
+ * Return an unused driver id. Used by drivers prior to registering
+ * support for the algorithms they handle.
+ */
+int32_t
+crypto_get_driverid(u_int32_t flags)
+{
+ struct cryptocap *newdrv;
+ int i;
+
+ CRYPTO_DRIVER_LOCK();
+
+ for (i = 0; i < crypto_drivers_num; i++)
+ if (crypto_drivers[i].cc_process == NULL &&
+ (crypto_drivers[i].cc_flags & CRYPTOCAP_F_CLEANUP) == 0 &&
+ crypto_drivers[i].cc_sessions == 0)
+ break;
+
+ /* Out of entries, allocate some more. */
+ if (i == crypto_drivers_num) {
+ /* Be careful about wrap-around. */
+ if (2 * crypto_drivers_num <= crypto_drivers_num) {
+ CRYPTO_DRIVER_UNLOCK();
+ printf("crypto: driver count wraparound!\n");
+ return -1;
+ }
+
+ newdrv = malloc(2 * crypto_drivers_num *
+ sizeof(struct cryptocap), M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
+ if (newdrv == NULL) {
+ CRYPTO_DRIVER_UNLOCK();
+ printf("crypto: no space to expand driver table!\n");
+ return -1;
+ }
+
+ bcopy(crypto_drivers, newdrv,
+ crypto_drivers_num * sizeof(struct cryptocap));
+
+ crypto_drivers_num *= 2;
+
+ free(crypto_drivers, M_CRYPTO_DATA);
+ crypto_drivers = newdrv;
+ }
+
+ /* NB: state is zero'd on free */
+ crypto_drivers[i].cc_sessions = 1; /* Mark */
+ crypto_drivers[i].cc_flags = flags;
+ if (bootverbose)
+ printf("crypto: assign driver %u, flags %u\n", i, flags);
+
+ CRYPTO_DRIVER_UNLOCK();
+
+ return i;
+}
+
+static struct cryptocap *
+crypto_checkdriver(u_int32_t hid)
+{
+ if (crypto_drivers == NULL)
+ return NULL;
+ return (hid >= crypto_drivers_num ? NULL : &crypto_drivers[hid]);
+}
+
+/*
+ * Register support for a key-related algorithm. This routine
+ * is called once for each algorithm supported a driver.
+ */
+int
+crypto_kregister(u_int32_t driverid, int kalg, u_int32_t flags,
+ int (*kprocess)(void*, struct cryptkop *, int),
+ void *karg)
+{
+ struct cryptocap *cap;
+ int err;
+
+ CRYPTO_DRIVER_LOCK();
+
+ cap = crypto_checkdriver(driverid);
+ if (cap != NULL &&
+ (CRK_ALGORITM_MIN <= kalg && kalg <= CRK_ALGORITHM_MAX)) {
+ /*
+ * XXX Do some performance testing to determine placing.
+ * XXX We probably need an auxiliary data structure that
+ * XXX describes relative performances.
+ */
+
+ cap->cc_kalg[kalg] = flags | CRYPTO_ALG_FLAG_SUPPORTED;
+ if (bootverbose)
+ printf("crypto: driver %u registers key alg %u flags %u\n"
+ , driverid
+ , kalg
+ , flags
+ );
+
+ if (cap->cc_kprocess == NULL) {
+ cap->cc_karg = karg;
+ cap->cc_kprocess = kprocess;
+ }
+ err = 0;
+ } else
+ err = EINVAL;
+
+ CRYPTO_DRIVER_UNLOCK();
+ return err;
+}
+
+/*
+ * Register support for a non-key-related algorithm. This routine
+ * is called once for each such algorithm supported by a driver.
+ */
+int
+crypto_register(u_int32_t driverid, int alg, u_int16_t maxoplen,
+ u_int32_t flags,
+ int (*newses)(void*, u_int32_t*, struct cryptoini*),
+ int (*freeses)(void*, u_int64_t),
+ int (*process)(void*, struct cryptop *, int),
+ void *arg)
+{
+ struct cryptocap *cap;
+ int err;
+
+ CRYPTO_DRIVER_LOCK();
+
+ cap = crypto_checkdriver(driverid);
+ /* NB: algorithms are in the range [1..max] */
+ if (cap != NULL &&
+ (CRYPTO_ALGORITHM_MIN <= alg && alg <= CRYPTO_ALGORITHM_MAX)) {
+ /*
+ * XXX Do some performance testing to determine placing.
+ * XXX We probably need an auxiliary data structure that
+ * XXX describes relative performances.
+ */
+
+ cap->cc_alg[alg] = flags | CRYPTO_ALG_FLAG_SUPPORTED;
+ cap->cc_max_op_len[alg] = maxoplen;
+ if (bootverbose)
+ printf("crypto: driver %u registers alg %u flags %u maxoplen %u\n"
+ , driverid
+ , alg
+ , flags
+ , maxoplen
+ );
+
+ if (cap->cc_process == NULL) {
+ cap->cc_arg = arg;
+ cap->cc_newsession = newses;
+ cap->cc_process = process;
+ cap->cc_freesession = freeses;
+ cap->cc_sessions = 0; /* Unmark */
+ }
+ err = 0;
+ } else
+ err = EINVAL;
+
+ CRYPTO_DRIVER_UNLOCK();
+ return err;
+}
+
+/*
+ * Unregister a crypto driver. If there are pending sessions using it,
+ * leave enough information around so that subsequent calls using those
+ * sessions will correctly detect the driver has been unregistered and
+ * reroute requests.
+ */
+int
+crypto_unregister(u_int32_t driverid, int alg)
+{
+ int i, err;
+ u_int32_t ses;
+ struct cryptocap *cap;
+
+ CRYPTO_DRIVER_LOCK();
+
+ cap = crypto_checkdriver(driverid);
+ if (cap != NULL &&
+ (CRYPTO_ALGORITHM_MIN <= alg && alg <= CRYPTO_ALGORITHM_MAX) &&
+ cap->cc_alg[alg] != 0) {
+ cap->cc_alg[alg] = 0;
+ cap->cc_max_op_len[alg] = 0;
+
+ /* Was this the last algorithm ? */
+ for (i = 1; i <= CRYPTO_ALGORITHM_MAX; i++)
+ if (cap->cc_alg[i] != 0)
+ break;
+
+ if (i == CRYPTO_ALGORITHM_MAX + 1) {
+ ses = cap->cc_sessions;
+ bzero(cap, sizeof(struct cryptocap));
+ if (ses != 0) {
+ /*
+ * If there are pending sessions, just mark as invalid.
+ */
+ cap->cc_flags |= CRYPTOCAP_F_CLEANUP;
+ cap->cc_sessions = ses;
+ }
+ }
+ err = 0;
+ } else
+ err = EINVAL;
+
+ CRYPTO_DRIVER_UNLOCK();
+ return err;
+}
+
+/*
+ * Unregister all algorithms associated with a crypto driver.
+ * If there are pending sessions using it, leave enough information
+ * around so that subsequent calls using those sessions will
+ * correctly detect the driver has been unregistered and reroute
+ * requests.
+ */
+int
+crypto_unregister_all(u_int32_t driverid)
+{
+ int i, err;
+ u_int32_t ses;
+ struct cryptocap *cap;
+
+ CRYPTO_DRIVER_LOCK();
+
+ cap = crypto_checkdriver(driverid);
+ if (cap != NULL) {
+ for (i = CRYPTO_ALGORITHM_MIN; i <= CRYPTO_ALGORITHM_MAX; i++) {
+ cap->cc_alg[i] = 0;
+ cap->cc_max_op_len[i] = 0;
+ }
+ ses = cap->cc_sessions;
+ bzero(cap, sizeof(struct cryptocap));
+ if (ses != 0) {
+ /*
+ * If there are pending sessions, just mark as invalid.
+ */
+ cap->cc_flags |= CRYPTOCAP_F_CLEANUP;
+ cap->cc_sessions = ses;
+ }
+ err = 0;
+ } else
+ err = EINVAL;
+
+ CRYPTO_DRIVER_UNLOCK();
+ return err;
+}
+
+/*
+ * Clear blockage on a driver. The what parameter indicates whether
+ * the driver is now ready for cryptop's and/or cryptokop's.
+ */
+int
+crypto_unblock(u_int32_t driverid, int what)
+{
+ struct cryptocap *cap;
+ int needwakeup, err;
+
+ needwakeup = 0;
+
+ CRYPTO_Q_LOCK();
+ cap = crypto_checkdriver(driverid);
+ if (cap != NULL) {
+ if (what & CRYPTO_SYMQ) {
+ needwakeup |= cap->cc_qblocked;
+ cap->cc_qblocked = 0;
+ }
+ if (what & CRYPTO_ASYMQ) {
+ needwakeup |= cap->cc_kqblocked;
+ cap->cc_kqblocked = 0;
+ }
+ err = 0;
+ } else
+ err = EINVAL;
+ CRYPTO_Q_UNLOCK();
+
+ if (needwakeup)
+ wakeup_one(&crp_q);
+
+ return err;
+}
+
+/*
+ * Add a crypto request to a queue, to be processed by the kernel thread.
+ */
+int
+crypto_dispatch(struct cryptop *crp)
+{
+ struct cryptocap *cap;
+ int wasempty;
+
+ CRYPTO_Q_LOCK();
+ wasempty = TAILQ_EMPTY(&crp_q);
+ TAILQ_INSERT_TAIL(&crp_q, crp, crp_next);
+
+ /*
+ * Wakeup processing thread if driver is not blocked.
+ */
+ cap = crypto_checkdriver(SESID2HID(crp->crp_sid));
+ if (cap && !cap->cc_qblocked && wasempty)
+ wakeup_one(&crp_q);
+ CRYPTO_Q_UNLOCK();
+
+ return 0;
+}
+
+/*
+ * Add an asymetric crypto request to a queue,
+ * to be processed by the kernel thread.
+ */
+int
+crypto_kdispatch(struct cryptkop *krp)
+{
+ struct cryptocap *cap;
+ int wasempty;
+
+ CRYPTO_Q_LOCK();
+ wasempty = TAILQ_EMPTY(&crp_kq);
+ TAILQ_INSERT_TAIL(&crp_kq, krp, krp_next);
+
+ /*
+ * Wakeup processing thread if driver is not blocked.
+ */
+ cap = crypto_checkdriver(krp->krp_hid);
+ if (cap && !cap->cc_kqblocked && wasempty)
+ wakeup_one(&crp_q); /* NB: shared wait channel */
+ CRYPTO_Q_UNLOCK();
+
+ return 0;
+}
+
+/*
+ * Dispatch an assymetric crypto request to the appropriate crypto devices.
+ */
+static int
+crypto_kinvoke(struct cryptkop *krp, int hint)
+{
+ u_int32_t hid;
+ int error;
+
+ mtx_assert(&crypto_q_mtx, MA_OWNED);
+
+ /* Sanity checks. */
+ if (krp == NULL || krp->krp_callback == NULL)
+ return EINVAL;
+
+ for (hid = 0; hid < crypto_drivers_num; hid++) {
+ if ((crypto_drivers[hid].cc_flags & CRYPTOCAP_F_SOFTWARE) &&
+ !crypto_devallowsoft)
+ continue;
+ if (crypto_drivers[hid].cc_kprocess == NULL)
+ continue;
+ if ((crypto_drivers[hid].cc_kalg[krp->krp_op] &
+ CRYPTO_ALG_FLAG_SUPPORTED) == 0)
+ continue;
+ break;
+ }
+ if (hid < crypto_drivers_num) {
+ krp->krp_hid = hid;
+ error = crypto_drivers[hid].cc_kprocess(
+ crypto_drivers[hid].cc_karg, krp, hint);
+ } else
+ error = ENODEV;
+
+ if (error) {
+ krp->krp_status = error;
+ CRYPTO_RETQ_LOCK();
+ TAILQ_INSERT_TAIL(&crp_ret_kq, krp, krp_next);
+ CRYPTO_RETQ_UNLOCK();
+ }
+ return 0;
+}
+
+/*
+ * Dispatch a crypto request to the appropriate crypto devices.
+ */
+static int
+crypto_invoke(struct cryptop *crp, int hint)
+{
+ u_int32_t hid;
+ int (*process)(void*, struct cryptop *, int);
+
+ mtx_assert(&crypto_q_mtx, MA_OWNED);
+
+ /* Sanity checks. */
+ if (crp == NULL || crp->crp_callback == NULL)
+ return EINVAL;
+
+ if (crp->crp_desc == NULL) {
+ crp->crp_etype = EINVAL;
+ CRYPTO_RETQ_LOCK();
+ TAILQ_INSERT_TAIL(&crp_ret_q, crp, crp_next);
+ CRYPTO_RETQ_UNLOCK();
+ return 0;
+ }
+
+ hid = SESID2HID(crp->crp_sid);
+ if (hid < crypto_drivers_num) {
+ if (crypto_drivers[hid].cc_flags & CRYPTOCAP_F_CLEANUP)
+ crypto_freesession(crp->crp_sid);
+ process = crypto_drivers[hid].cc_process;
+ } else {
+ process = NULL;
+ }
+
+ if (process == NULL) {
+ struct cryptodesc *crd;
+ u_int64_t nid;
+
+ /*
+ * Driver has unregistered; migrate the session and return
+ * an error to the caller so they'll resubmit the op.
+ */
+ for (crd = crp->crp_desc; crd->crd_next; crd = crd->crd_next)
+ crd->CRD_INI.cri_next = &(crd->crd_next->CRD_INI);
+
+ if (crypto_newsession(&nid, &(crp->crp_desc->CRD_INI), 0) == 0)
+ crp->crp_sid = nid;
+
+ crp->crp_etype = EAGAIN;
+ CRYPTO_RETQ_LOCK();
+ TAILQ_INSERT_TAIL(&crp_ret_q, crp, crp_next);
+ CRYPTO_RETQ_UNLOCK();
+ return 0;
+ } else {
+ /*
+ * Invoke the driver to process the request.
+ */
+ return (*process)(crypto_drivers[hid].cc_arg, crp, hint);
+ }
+}
+
+/*
+ * Release a set of crypto descriptors.
+ */
+void
+crypto_freereq(struct cryptop *crp)
+{
+ struct cryptodesc *crd;
+
+ if (crp == NULL)
+ return;
+
+ while ((crd = crp->crp_desc) != NULL) {
+ crp->crp_desc = crd->crd_next;
+ uma_zfree(cryptodesc_zone, crd);
+ }
+
+ uma_zfree(cryptop_zone, crp);
+}
+
+/*
+ * Acquire a set of crypto descriptors.
+ */
+struct cryptop *
+crypto_getreq(int num)
+{
+ struct cryptodesc *crd;
+ struct cryptop *crp;
+
+ crp = uma_zalloc(cryptop_zone, 0);
+ if (crp != NULL) {
+ while (num--) {
+ crd = uma_zalloc(cryptodesc_zone, 0);
+ if (crd == NULL) {
+ crypto_freereq(crp);
+ return NULL;
+ }
+
+ crd->crd_next = crp->crp_desc;
+ crp->crp_desc = crd;
+ }
+ }
+ return crp;
+}
+
+/*
+ * Invoke the callback on behalf of the driver.
+ */
+void
+crypto_done(struct cryptop *crp)
+{
+ int wasempty;
+
+ CRYPTO_RETQ_LOCK();
+ wasempty = TAILQ_EMPTY(&crp_ret_q);
+ TAILQ_INSERT_TAIL(&crp_ret_q, crp, crp_next);
+ CRYPTO_RETQ_UNLOCK();
+
+ if (wasempty)
+ wakeup_one(&crp_q); /* shared wait channel */
+}
+
+/*
+ * Invoke the callback on behalf of the driver.
+ */
+void
+crypto_kdone(struct cryptkop *krp)
+{
+ int wasempty;
+
+ CRYPTO_RETQ_LOCK();
+ wasempty = TAILQ_EMPTY(&crp_ret_kq);
+ TAILQ_INSERT_TAIL(&crp_ret_kq, krp, krp_next);
+ CRYPTO_RETQ_UNLOCK();
+
+ if (wasempty)
+ wakeup_one(&crp_q); /* shared wait channel */
+}
+
+int
+crypto_getfeat(int *featp)
+{
+ int hid, kalg, feat = 0;
+
+ if (!crypto_userasymcrypto)
+ goto out;
+
+ CRYPTO_DRIVER_LOCK();
+ for (hid = 0; hid < crypto_drivers_num; hid++) {
+ if ((crypto_drivers[hid].cc_flags & CRYPTOCAP_F_SOFTWARE) &&
+ !crypto_devallowsoft) {
+ continue;
+ }
+ if (crypto_drivers[hid].cc_kprocess == NULL)
+ continue;
+ for (kalg = 0; kalg < CRK_ALGORITHM_MAX; kalg++)
+ if ((crypto_drivers[hid].cc_kalg[kalg] &
+ CRYPTO_ALG_FLAG_SUPPORTED) != 0)
+ feat |= 1 << kalg;
+ }
+ CRYPTO_DRIVER_UNLOCK();
+out:
+ *featp = feat;
+ return (0);
+}
+
+static struct proc *cryptoproc;
+
+static void
+crypto_shutdown(void *arg, int howto)
+{
+ /* XXX flush queues */
+}
+
+/*
+ * Crypto thread, runs as a kernel thread to process crypto requests.
+ */
+static void
+crypto_proc(void)
+{
+ struct cryptop *crp, *crpt, *submit;
+ struct cryptkop *krp, *krpt;
+ struct cryptocap *cap;
+ int result, hint;
+
+ mtx_lock(&Giant); /* XXX for msleep */
+
+ EVENTHANDLER_REGISTER(shutdown_pre_sync, crypto_shutdown, NULL,
+ SHUTDOWN_PRI_FIRST);
+
+ for (;;) {
+ /*
+ * Find the first element in the queue that can be
+ * processed and look-ahead to see if multiple ops
+ * are ready for the same driver.
+ */
+ submit = NULL;
+ hint = 0;
+ CRYPTO_Q_LOCK();
+ TAILQ_FOREACH(crp, &crp_q, crp_next) {
+ u_int32_t hid = SESID2HID(crp->crp_sid);
+ cap = crypto_checkdriver(hid);
+ if (cap == NULL || cap->cc_process == NULL) {
+ /* Op needs to be migrated, process it. */
+ if (submit == NULL)
+ submit = crp;
+ break;
+ }
+ if (!cap->cc_qblocked) {
+ if (submit != NULL) {
+ /*
+ * We stop on finding another op,
+ * regardless whether its for the same
+ * driver or not. We could keep
+ * searching the queue but it might be
+ * better to just use a per-driver
+ * queue instead.
+ */
+ if (SESID2HID(submit->crp_sid) == hid)
+ hint = CRYPTO_HINT_MORE;
+ break;
+ } else {
+ submit = crp;
+ if (submit->crp_flags & CRYPTO_F_NODELAY)
+ break;
+ /* keep scanning for more are q'd */
+ }
+ }
+ }
+ if (submit != NULL) {
+ TAILQ_REMOVE(&crp_q, submit, crp_next);
+ result = crypto_invoke(submit, hint);
+ if (result == ERESTART) {
+ /*
+ * The driver ran out of resources, mark the
+ * driver ``blocked'' for cryptop's and put
+ * the request back in the queue. It would
+ * best to put the request back where we got
+ * it but that's hard so for now we put it
+ * at the front. This should be ok; putting
+ * it at the end does not work.
+ */
+ /* XXX validate sid again? */
+ crypto_drivers[SESID2HID(submit->crp_sid)].cc_qblocked = 1;
+ TAILQ_INSERT_HEAD(&crp_q, submit, crp_next);
+ }
+ }
+
+ /* As above, but for key ops */
+ TAILQ_FOREACH(krp, &crp_kq, krp_next) {
+ cap = crypto_checkdriver(krp->krp_hid);
+ if (cap == NULL || cap->cc_kprocess == NULL) {
+ /* Op needs to be migrated, process it. */
+ break;
+ }
+ if (!cap->cc_kqblocked)
+ break;
+ }
+ if (krp != NULL) {
+ TAILQ_REMOVE(&crp_kq, krp, krp_next);
+ result = crypto_kinvoke(krp, 0);
+ if (result == ERESTART) {
+ /*
+ * The driver ran out of resources, mark the
+ * driver ``blocked'' for cryptkop's and put
+ * the request back in the queue. It would
+ * best to put the request back where we got
+ * it but that's hard so for now we put it
+ * at the front. This should be ok; putting
+ * it at the end does not work.
+ */
+ /* XXX validate sid again? */
+ crypto_drivers[krp->krp_hid].cc_kqblocked = 1;
+ TAILQ_INSERT_HEAD(&crp_kq, krp, krp_next);
+ }
+ }
+ CRYPTO_Q_UNLOCK();
+
+ /* Harvest return q for completed ops */
+ CRYPTO_RETQ_LOCK();
+ crpt = TAILQ_FIRST(&crp_ret_q);
+ if (crpt != NULL)
+ TAILQ_REMOVE(&crp_ret_q, crpt, crp_next);
+ CRYPTO_RETQ_UNLOCK();
+
+ if (crpt != NULL)
+ crpt->crp_callback(crpt);
+
+ /* Harvest return q for completed kops */
+ CRYPTO_RETQ_LOCK();
+ krpt = TAILQ_FIRST(&crp_ret_kq);
+ if (krpt != NULL)
+ TAILQ_REMOVE(&crp_ret_kq, krpt, krp_next);
+ CRYPTO_RETQ_UNLOCK();
+
+ if (krpt != NULL)
+ krp->krp_callback(krp);
+
+ if (crp == NULL && krp == NULL && crpt == NULL && krpt == NULL) {
+ /*
+ * Nothing more to be processed. Sleep until we're
+ * woken because there are more ops to process.
+ * This happens either by submission or by a driver
+ * becoming unblocked and notifying us through
+ * crypto_unblock. Note that when we wakeup we
+ * start processing each queue again from the
+ * front. It's not clear that it's important to
+ * preserve this ordering since ops may finish
+ * out of order if dispatched to different devices
+ * and some become blocked while others do not.
+ */
+ tsleep(&crp_q, PWAIT, "crypto_wait", 0);
+ }
+ }
+}
+
+static struct kproc_desc crypto_kp = {
+ "crypto",
+ crypto_proc,
+ &cryptoproc
+};
+SYSINIT(crypto_proc, SI_SUB_KTHREAD_IDLE, SI_ORDER_ANY, kproc_start, &crypto_kp)
diff --git a/sys/opencrypto/crypto_if.m b/sys/opencrypto/crypto_if.m
new file mode 100644
index 0000000..0ef17e6
--- /dev/null
+++ b/sys/opencrypto/crypto_if.m
@@ -0,0 +1,128 @@
+#
+# Copyright (c) 2002, Sam Leffler
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by Boris Popov.
+# 4. Neither the name of the author nor the names of any co-contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+#include <crypto/cryptodev.h>
+
+INTERFACE crypto;
+
+METHOD int32_t get_driverid {
+ u_int32_t flags;
+};
+
+# XXX define typedefs to work around inadequate parser
+HEADER {
+ typedef int crypto_newsession_cb(void*, u_int32_t*, struct cryptoini*);
+ typedef int crypto_freesession_cb(void*, u_int64_t*);
+ typedef int crypto_process_cb(void*, struct cryptop*);
+ typedef int crypto_kprocess_cb(void*, struct cryptkop*);
+};
+
+METHOD int register {
+ u_int32_t driverid;
+ int alg;
+ u_int16_t maxoplen;
+ u_int32_t flags;
+ crypto_newsession_cb* newses;
+ crypto_freesession_cb* freeses;
+ crypto_process_cb* process;
+ void *arg;
+};
+
+METHOD int kregister {
+ u_int32_t driverid;
+ int kalg;
+ u_int32_t flags;
+ crypto_kprocess_cb* kprocess;
+ void *arg;
+};
+
+METHOD int unregister {
+ u_int32_t driverid;
+ int alg;
+};
+
+METHOD int unregister_all {
+ u_int32_t driverid;
+};
+
+METHOD int newsession {
+ u_int64_t *sid;
+ struct cryptoini *cri;
+ int hard;
+};
+
+METHOD int freesession {
+ u_int64_t sid;
+};
+
+METHOD int dispatch {
+ struct cryptop *crp;
+};
+
+METHOD int kdispatch {
+ struct cryptkop *krp;
+};
+
+METHOD int crypto_unblock {
+ u_int32_t driverid;
+ int what;
+};
+
+METHOD int invoke {
+ struct cryptop *crp;
+};
+
+METHOD int kinvoke {
+ struct cryptkop *krp;
+};
+
+METHOD struct cryptop * getreq {
+ int num;
+};
+
+METHOD void freereq {
+ struct cryptop *crp;
+};
+
+METHOD void done {
+ struct cryptop *crp;
+};
+
+METHOD void kdone {
+ struct cryptkop *krp;
+};
+
+METHOD int getfeat {
+ int *featp;
+};
diff --git a/sys/opencrypto/cryptodev.c b/sys/opencrypto/cryptodev.c
new file mode 100644
index 0000000..0e88fda
--- /dev/null
+++ b/sys/opencrypto/cryptodev.c
@@ -0,0 +1,798 @@
+/* $FreeBSD$ */
+/* $OpenBSD: cryptodev.c,v 1.52 2002/06/19 07:22:46 deraadt Exp $ */
+
+/*
+ * Copyright (c) 2001 Theo de Raadt
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sysctl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/errno.h>
+#include <sys/uio.h>
+#include <sys/random.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/fcntl.h>
+
+#include <opencrypto/cryptodev.h>
+#include <opencrypto/xform.h>
+
+struct csession {
+ TAILQ_ENTRY(csession) next;
+ u_int64_t sid;
+ u_int32_t ses;
+
+ u_int32_t cipher;
+ struct enc_xform *txform;
+ u_int32_t mac;
+ struct auth_hash *thash;
+
+ caddr_t key;
+ int keylen;
+ u_char tmp_iv[EALG_MAX_BLOCK_LEN];
+
+ caddr_t mackey;
+ int mackeylen;
+ u_char tmp_mac[CRYPTO_MAX_MAC_LEN];
+
+ struct iovec iovec[UIO_MAXIOV];
+ struct uio uio;
+ int error;
+};
+
+struct fcrypt {
+ TAILQ_HEAD(csessionlist, csession) csessions;
+ int sesn;
+};
+
+static int cryptof_rw(struct file *fp, struct uio *uio,
+ struct ucred *cred, int flags, struct thread *);
+static int cryptof_ioctl(struct file *, u_long, void *,
+ struct ucred *, struct thread *);
+static int cryptof_poll(struct file *, int, struct ucred *, struct thread *);
+static int cryptof_kqfilter(struct file *, struct knote *);
+static int cryptof_stat(struct file *, struct stat *,
+ struct ucred *, struct thread *);
+static int cryptof_close(struct file *, struct thread *);
+
+static struct fileops cryptofops = {
+ cryptof_rw,
+ cryptof_rw,
+ cryptof_ioctl,
+ cryptof_poll,
+ cryptof_kqfilter,
+ cryptof_stat,
+ cryptof_close
+};
+
+static struct csession *csefind(struct fcrypt *, u_int);
+static int csedelete(struct fcrypt *, struct csession *);
+static struct csession *cseadd(struct fcrypt *, struct csession *);
+static struct csession *csecreate(struct fcrypt *, u_int64_t, caddr_t,
+ u_int64_t, caddr_t, u_int64_t, u_int32_t, u_int32_t, struct enc_xform *,
+ struct auth_hash *);
+static int csefree(struct csession *);
+
+static int cryptodev_op(struct csession *, struct crypt_op *,
+ struct ucred *, struct thread *td);
+static int cryptodev_key(struct crypt_kop *);
+
+static int
+cryptof_rw(
+ struct file *fp,
+ struct uio *uio,
+ struct ucred *active_cred,
+ int flags,
+ struct thread *td)
+{
+
+ return (EIO);
+}
+
+/* ARGSUSED */
+static int
+cryptof_ioctl(
+ struct file *fp,
+ u_long cmd,
+ void *data,
+ struct ucred *active_cred,
+ struct thread *td)
+{
+ struct cryptoini cria, crie;
+ struct fcrypt *fcr = (struct fcrypt *)fp->f_data;
+ struct csession *cse;
+ struct session_op *sop;
+ struct crypt_op *cop;
+ struct enc_xform *txform = NULL;
+ struct auth_hash *thash = NULL;
+ u_int64_t sid;
+ u_int32_t ses;
+ int error = 0;
+
+ switch (cmd) {
+ case CIOCGSESSION:
+ case CIOCGSSESSION:
+ sop = (struct session_op *)data;
+ switch (sop->cipher) {
+ case 0:
+ break;
+ case CRYPTO_DES_CBC:
+ txform = &enc_xform_des;
+ break;
+ case CRYPTO_3DES_CBC:
+ txform = &enc_xform_3des;
+ break;
+ case CRYPTO_BLF_CBC:
+ txform = &enc_xform_blf;
+ break;
+ case CRYPTO_CAST_CBC:
+ txform = &enc_xform_cast5;
+ break;
+ case CRYPTO_SKIPJACK_CBC:
+ txform = &enc_xform_skipjack;
+ break;
+ case CRYPTO_AES_CBC:
+ txform = &enc_xform_rijndael128;
+ break;
+ case CRYPTO_NULL_CBC:
+ txform = &enc_xform_null;
+ break;
+ case CRYPTO_ARC4:
+ txform = &enc_xform_arc4;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ switch (sop->mac) {
+ case 0:
+ break;
+ case CRYPTO_MD5_HMAC:
+ thash = &auth_hash_hmac_md5_96;
+ break;
+ case CRYPTO_SHA1_HMAC:
+ thash = &auth_hash_hmac_sha1_96;
+ break;
+ case CRYPTO_SHA2_HMAC:
+ if (sop->mackeylen == auth_hash_hmac_sha2_256.keysize)
+ thash = &auth_hash_hmac_sha2_256;
+ else if (sop->mackeylen == auth_hash_hmac_sha2_384.keysize)
+ thash = &auth_hash_hmac_sha2_384;
+ else if (sop->mackeylen == auth_hash_hmac_sha2_512.keysize)
+ thash = &auth_hash_hmac_sha2_512;
+ else
+ return (EINVAL);
+ break;
+ case CRYPTO_RIPEMD160_HMAC:
+ thash = &auth_hash_hmac_ripemd_160_96;
+ break;
+#ifdef notdef
+ case CRYPTO_MD5:
+ thash = &auth_hash_md5;
+ break;
+ case CRYPTO_SHA1:
+ thash = &auth_hash_sha1;
+ break;
+#endif
+ case CRYPTO_NULL_HMAC:
+ thash = &auth_hash_null;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ bzero(&crie, sizeof(crie));
+ bzero(&cria, sizeof(cria));
+
+ if (txform) {
+ crie.cri_alg = txform->type;
+ crie.cri_klen = sop->keylen * 8;
+ if (sop->keylen > txform->maxkey ||
+ sop->keylen < txform->minkey) {
+ error = EINVAL;
+ goto bail;
+ }
+
+ MALLOC(crie.cri_key, u_int8_t *,
+ crie.cri_klen / 8, M_XDATA, M_WAITOK);
+ if ((error = copyin(sop->key, crie.cri_key,
+ crie.cri_klen / 8)))
+ goto bail;
+ if (thash)
+ crie.cri_next = &cria;
+ }
+
+ if (thash) {
+ cria.cri_alg = thash->type;
+ cria.cri_klen = sop->mackeylen * 8;
+ if (sop->mackeylen != thash->keysize) {
+ error = EINVAL;
+ goto bail;
+ }
+
+ if (cria.cri_klen) {
+ MALLOC(cria.cri_key, u_int8_t *,
+ cria.cri_klen / 8, M_XDATA, M_WAITOK);
+ if ((error = copyin(sop->mackey, cria.cri_key,
+ cria.cri_klen / 8)))
+ goto bail;
+ }
+ }
+
+ error = crypto_newsession(&sid, (txform ? &crie : &cria),
+ (cmd == CIOCGSESSION ? 1 : -1));
+ if (error)
+ goto bail;
+
+ cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen,
+ cria.cri_key, cria.cri_klen, sop->cipher, sop->mac, txform,
+ thash);
+
+ if (cse == NULL) {
+ crypto_freesession(sid);
+ error = EINVAL;
+ goto bail;
+ }
+ sop->ses = cse->ses;
+
+bail:
+ if (error) {
+ if (crie.cri_key)
+ FREE(crie.cri_key, M_XDATA);
+ if (cria.cri_key)
+ FREE(cria.cri_key, M_XDATA);
+ }
+ break;
+ case CIOCFSESSION:
+ ses = *(u_int32_t *)data;
+ cse = csefind(fcr, ses);
+ if (cse == NULL)
+ return (EINVAL);
+ csedelete(fcr, cse);
+ error = csefree(cse);
+ break;
+ case CIOCCRYPT:
+ cop = (struct crypt_op *)data;
+ cse = csefind(fcr, cop->ses);
+ if (cse == NULL)
+ return (EINVAL);
+ error = cryptodev_op(cse, cop, active_cred, td);
+ break;
+ case CIOCKEY:
+ error = cryptodev_key((struct crypt_kop *)data);
+ break;
+ case CIOCASYMFEAT:
+ error = crypto_getfeat((int *)data);
+ break;
+ default:
+ error = EINVAL;
+ }
+ return (error);
+}
+
+static int cryptodev_cb(void *);
+
+
+static int
+cryptodev_op(
+ struct csession *cse,
+ struct crypt_op *cop,
+ struct ucred *active_cred,
+ struct thread *td)
+{
+ struct cryptop *crp = NULL;
+ struct cryptodesc *crde = NULL, *crda = NULL;
+ int i, error;
+
+ if (cop->len > 256*1024-4)
+ return (E2BIG);
+
+ if (cse->txform && (cop->len % cse->txform->blocksize) != 0)
+ return (EINVAL);
+
+ bzero(&cse->uio, sizeof(cse->uio));
+ cse->uio.uio_iovcnt = 1;
+ cse->uio.uio_resid = 0;
+ cse->uio.uio_segflg = UIO_SYSSPACE;
+ cse->uio.uio_rw = UIO_WRITE;
+ cse->uio.uio_td = td;
+ cse->uio.uio_iov = cse->iovec;
+ bzero(&cse->iovec, sizeof(cse->iovec));
+ cse->uio.uio_iov[0].iov_len = cop->len;
+ cse->uio.uio_iov[0].iov_base = malloc(cop->len, M_XDATA, M_WAITOK);
+ for (i = 0; i < cse->uio.uio_iovcnt; i++)
+ cse->uio.uio_resid += cse->uio.uio_iov[0].iov_len;
+
+ crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL));
+ if (crp == NULL) {
+ error = ENOMEM;
+ goto bail;
+ }
+
+ if (cse->thash) {
+ crda = crp->crp_desc;
+ if (cse->txform)
+ crde = crda->crd_next;
+ } else {
+ if (cse->txform)
+ crde = crp->crp_desc;
+ else {
+ error = EINVAL;
+ goto bail;
+ }
+ }
+
+ if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len)))
+ goto bail;
+
+ if (crda) {
+ crda->crd_skip = 0;
+ crda->crd_len = cop->len;
+ crda->crd_inject = 0; /* ??? */
+
+ crda->crd_alg = cse->mac;
+ crda->crd_key = cse->mackey;
+ crda->crd_klen = cse->mackeylen * 8;
+ }
+
+ if (crde) {
+ if (cop->op == COP_ENCRYPT)
+ crde->crd_flags |= CRD_F_ENCRYPT;
+ else
+ crde->crd_flags &= ~CRD_F_ENCRYPT;
+ crde->crd_len = cop->len;
+ crde->crd_inject = 0;
+
+ crde->crd_alg = cse->cipher;
+ crde->crd_key = cse->key;
+ crde->crd_klen = cse->keylen * 8;
+ }
+
+ crp->crp_ilen = cop->len;
+ crp->crp_flags = CRYPTO_F_IOV;
+ crp->crp_buf = (caddr_t)&cse->uio;
+ crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
+ crp->crp_sid = cse->sid;
+ crp->crp_opaque = (void *)cse;
+
+ if (cop->iv) {
+ if (crde == NULL) {
+ error = EINVAL;
+ goto bail;
+ }
+ if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
+ error = EINVAL;
+ goto bail;
+ }
+ if ((error = copyin(cop->iv, cse->tmp_iv, cse->txform->blocksize)))
+ goto bail;
+ bcopy(cse->tmp_iv, crde->crd_iv, cse->txform->blocksize);
+ crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
+ crde->crd_skip = 0;
+ } else if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
+ crde->crd_skip = 0;
+ } else if (crde) {
+ crde->crd_flags |= CRD_F_IV_PRESENT;
+ crde->crd_skip = cse->txform->blocksize;
+ crde->crd_len -= cse->txform->blocksize;
+ }
+
+ if (cop->mac) {
+ if (crda == NULL) {
+ error = EINVAL;
+ goto bail;
+ }
+ crp->crp_mac=cse->tmp_mac;
+ }
+
+ crypto_dispatch(crp);
+ error = tsleep(cse, PSOCK, "crydev", 0);
+ if (error) {
+ /* XXX can this happen? if so, how do we recover? */
+ goto bail;
+ }
+
+ if (crp->crp_etype != 0) {
+ error = crp->crp_etype;
+ goto bail;
+ }
+
+ if (cse->error) {
+ error = cse->error;
+ goto bail;
+ }
+
+ if (cop->dst &&
+ (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, cop->len)))
+ goto bail;
+
+ if (cop->mac &&
+ (error = copyout(crp->crp_mac, cop->mac, cse->thash->authsize)))
+ goto bail;
+
+bail:
+ if (crp)
+ crypto_freereq(crp);
+ if (cse->uio.uio_iov[0].iov_base)
+ free(cse->uio.uio_iov[0].iov_base, M_XDATA);
+
+ return (error);
+}
+
+static int
+cryptodev_cb(void *op)
+{
+ struct cryptop *crp = (struct cryptop *) op;
+ struct csession *cse = (struct csession *)crp->crp_opaque;
+
+ cse->error = crp->crp_etype;
+ if (crp->crp_etype == EAGAIN)
+ return crypto_dispatch(crp);
+ wakeup(cse);
+ return (0);
+}
+
+static int
+cryptodevkey_cb(void *op)
+{
+ struct cryptkop *krp = (struct cryptkop *) op;
+
+ wakeup(krp);
+ return (0);
+}
+
+static int
+cryptodev_key(struct crypt_kop *kop)
+{
+ struct cryptkop *krp = NULL;
+ int error = EINVAL;
+ int in, out, size, i;
+
+ if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) {
+ return (EFBIG);
+ }
+
+ in = kop->crk_iparams;
+ out = kop->crk_oparams;
+ switch (kop->crk_op) {
+ case CRK_MOD_EXP:
+ if (in == 3 && out == 1)
+ break;
+ return (EINVAL);
+ case CRK_MOD_EXP_CRT:
+ if (in == 6 && out == 1)
+ break;
+ return (EINVAL);
+ case CRK_DSA_SIGN:
+ if (in == 5 && out == 2)
+ break;
+ return (EINVAL);
+ case CRK_DSA_VERIFY:
+ if (in == 7 && out == 0)
+ break;
+ return (EINVAL);
+ case CRK_DH_COMPUTE_KEY:
+ if (in == 3 && out == 1)
+ break;
+ return (EINVAL);
+ default:
+ return (EINVAL);
+ }
+
+ krp = (struct cryptkop *)malloc(sizeof *krp, M_XDATA, M_WAITOK);
+ if (!krp)
+ return (ENOMEM);
+ bzero(krp, sizeof *krp);
+ krp->krp_op = kop->crk_op;
+ krp->krp_status = kop->crk_status;
+ krp->krp_iparams = kop->crk_iparams;
+ krp->krp_oparams = kop->crk_oparams;
+ krp->krp_status = 0;
+ krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
+
+ for (i = 0; i < CRK_MAXPARAM; i++)
+ krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
+ for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
+ size = (krp->krp_param[i].crp_nbits + 7) / 8;
+ if (size == 0)
+ continue;
+ MALLOC(krp->krp_param[i].crp_p, caddr_t, size, M_XDATA, M_WAITOK);
+ if (i >= krp->krp_iparams)
+ continue;
+ error = copyin(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p, size);
+ if (error)
+ goto fail;
+ }
+
+ error = crypto_kdispatch(krp);
+ if (error)
+ goto fail;
+ error = tsleep(krp, PSOCK, "crydev", 0);
+ if (error) {
+ /* XXX can this happen? if so, how do we recover? */
+ goto fail;
+ }
+
+ if (krp->krp_status != 0) {
+ error = krp->krp_status;
+ goto fail;
+ }
+
+ for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) {
+ size = (krp->krp_param[i].crp_nbits + 7) / 8;
+ if (size == 0)
+ continue;
+ error = copyout(krp->krp_param[i].crp_p, kop->crk_param[i].crp_p, size);
+ if (error)
+ goto fail;
+ }
+
+fail:
+ if (krp) {
+ kop->crk_status = krp->krp_status;
+ for (i = 0; i < CRK_MAXPARAM; i++) {
+ if (krp->krp_param[i].crp_p)
+ FREE(krp->krp_param[i].crp_p, M_XDATA);
+ }
+ free(krp, M_XDATA);
+ }
+ return (error);
+}
+
+/* ARGSUSED */
+static int
+cryptof_poll(
+ struct file *fp,
+ int events,
+ struct ucred *active_cred,
+ struct thread *td)
+{
+
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+cryptof_kqfilter(struct file *fp, struct knote *kn)
+{
+
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+cryptof_stat(
+ struct file *fp,
+ struct stat *sb,
+ struct ucred *active_cred,
+ struct thread *td)
+{
+
+ return (EOPNOTSUPP);
+}
+
+/* ARGSUSED */
+static int
+cryptof_close(struct file *fp, struct thread *td)
+{
+ struct fcrypt *fcr = (struct fcrypt *)fp->f_data;
+ struct csession *cse;
+
+ while ((cse = TAILQ_FIRST(&fcr->csessions))) {
+ TAILQ_REMOVE(&fcr->csessions, cse, next);
+ (void)csefree(cse);
+ }
+ FREE(fcr, M_XDATA);
+ fp->f_data = NULL;
+ return 0;
+}
+
+static struct csession *
+csefind(struct fcrypt *fcr, u_int ses)
+{
+ struct csession *cse;
+
+ TAILQ_FOREACH(cse, &fcr->csessions, next)
+ if (cse->ses == ses)
+ return (cse);
+ return (NULL);
+}
+
+static int
+csedelete(struct fcrypt *fcr, struct csession *cse_del)
+{
+ struct csession *cse;
+
+ TAILQ_FOREACH(cse, &fcr->csessions, next) {
+ if (cse == cse_del) {
+ TAILQ_REMOVE(&fcr->csessions, cse, next);
+ return (1);
+ }
+ }
+ return (0);
+}
+
+static struct csession *
+cseadd(struct fcrypt *fcr, struct csession *cse)
+{
+ TAILQ_INSERT_TAIL(&fcr->csessions, cse, next);
+ cse->ses = fcr->sesn++;
+ return (cse);
+}
+
+struct csession *
+csecreate(struct fcrypt *fcr, u_int64_t sid, caddr_t key, u_int64_t keylen,
+ caddr_t mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac,
+ struct enc_xform *txform, struct auth_hash *thash)
+{
+ struct csession *cse;
+
+ MALLOC(cse, struct csession *, sizeof(struct csession),
+ M_XDATA, M_NOWAIT);
+ if (cse == NULL)
+ return NULL;
+ cse->key = key;
+ cse->keylen = keylen/8;
+ cse->mackey = mackey;
+ cse->mackeylen = mackeylen/8;
+ cse->sid = sid;
+ cse->cipher = cipher;
+ cse->mac = mac;
+ cse->txform = txform;
+ cse->thash = thash;
+ cseadd(fcr, cse);
+ return (cse);
+}
+
+static int
+csefree(struct csession *cse)
+{
+ int error;
+
+ error = crypto_freesession(cse->sid);
+ if (cse->key)
+ FREE(cse->key, M_XDATA);
+ if (cse->mackey)
+ FREE(cse->mackey, M_XDATA);
+ FREE(cse, M_XDATA);
+ return (error);
+}
+
+static int
+cryptoopen(dev_t dev, int oflags, int devtype, struct thread *td)
+{
+ if (crypto_usercrypto == 0)
+ return (ENXIO);
+ return (0);
+}
+
+static int
+cryptoread(dev_t dev, struct uio *uio, int ioflag)
+{
+ return (EIO);
+}
+
+static int
+cryptowrite(dev_t dev, struct uio *uio, int ioflag)
+{
+ return (EIO);
+}
+
+static int
+cryptoioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
+{
+ struct file *f;
+ struct fcrypt *fcr;
+ int fd, error;
+
+ switch (cmd) {
+ case CRIOGET:
+ MALLOC(fcr, struct fcrypt *,
+ sizeof(struct fcrypt), M_XDATA, M_WAITOK);
+ TAILQ_INIT(&fcr->csessions);
+ fcr->sesn = 0;
+
+ error = falloc(td, &f, &fd);
+
+ if (error) {
+ FREE(fcr, M_XDATA);
+ return (error);
+ }
+ fhold(f);
+ f->f_flag = FREAD | FWRITE;
+ f->f_type = DTYPE_CRYPTO;
+ f->f_ops = &cryptofops;
+ f->f_data = (caddr_t) fcr;
+ *(u_int32_t *)data = fd;
+ fdrop(f, td);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ return (error);
+}
+
+#define CRYPTO_MAJOR 70 /* from openbsd */
+static struct cdevsw crypto_cdevsw = {
+ /* open */ cryptoopen,
+ /* close */ nullclose,
+ /* read */ cryptoread,
+ /* write */ cryptowrite,
+ /* ioctl */ cryptoioctl,
+ /* poll */ nopoll,
+ /* mmap */ nommap,
+ /* strategy */ nostrategy,
+ /* dev name */ "crypto",
+ /* dev major */ CRYPTO_MAJOR,
+ /* dump */ nodump,
+ /* psize */ nopsize,
+ /* flags */ 0,
+ /* kqfilter */ NULL
+};
+static dev_t crypto_dev;
+
+/*
+ * Initialization code, both for static and dynamic loading.
+ */
+static int
+cryptodev_modevent(module_t mod, int type, void *unused)
+{
+ switch (type) {
+ case MOD_LOAD:
+ if (bootverbose)
+ printf("crypto: <crypto device>\n");
+ crypto_dev = make_dev(&crypto_cdevsw, CRYPTO_MAJOR,
+ UID_ROOT, GID_WHEEL, 0666,
+ "crypto");
+ return 0;
+ case MOD_UNLOAD:
+ /*XXX disallow if active sessions */
+ destroy_dev(crypto_dev);
+ return 0;
+ }
+ return EINVAL;
+}
+
+static moduledata_t cryptodev_mod = {
+ "cryptodev",
+ cryptodev_modevent,
+ 0
+};
+MODULE_VERSION(cryptodev, 1);
+DECLARE_MODULE(cryptodev, cryptodev_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
diff --git a/sys/opencrypto/cryptodev.h b/sys/opencrypto/cryptodev.h
new file mode 100644
index 0000000..30962b9
--- /dev/null
+++ b/sys/opencrypto/cryptodev.h
@@ -0,0 +1,347 @@
+/* $FreeBSD$ */
+/* $OpenBSD: cryptodev.h,v 1.31 2002/06/11 11:14:29 beck Exp $ */
+
+/*
+ * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
+ *
+ * This code was written by Angelos D. Keromytis in Athens, Greece, in
+ * February 2000. Network Security Technologies Inc. (NSTI) kindly
+ * supported the development of this code.
+ *
+ * Copyright (c) 2000 Angelos D. Keromytis
+ *
+ * Permission to use, copy, and modify this software with or without fee
+ * is hereby granted, provided that this entire notice is included in
+ * all source code copies of any software which is or includes a copy or
+ * modification of this software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+ * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Copyright (c) 2001 Theo de Raadt
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
+ *
+ */
+
+#ifndef _CRYPTO_CRYPTO_H_
+#define _CRYPTO_CRYPTO_H_
+
+#include <sys/ioccom.h>
+
+/* Some initial values */
+#define CRYPTO_DRIVERS_INITIAL 4
+#define CRYPTO_SW_SESSIONS 32
+
+/* HMAC values */
+#define HMAC_BLOCK_LEN 64
+#define HMAC_IPAD_VAL 0x36
+#define HMAC_OPAD_VAL 0x5C
+
+/* Encryption algorithm block sizes */
+#define DES_BLOCK_LEN 8
+#define DES3_BLOCK_LEN 8
+#define BLOWFISH_BLOCK_LEN 8
+#define SKIPJACK_BLOCK_LEN 8
+#define CAST128_BLOCK_LEN 8
+#define RIJNDAEL128_BLOCK_LEN 16
+#define EALG_MAX_BLOCK_LEN 16 /* Keep this updated */
+
+/* Maximum hash algorithm result length */
+#define AALG_MAX_RESULT_LEN 64 /* Keep this updated */
+
+#define CRYPTO_ALGORITHM_MIN 1
+#define CRYPTO_DES_CBC 1
+#define CRYPTO_3DES_CBC 2
+#define CRYPTO_BLF_CBC 3
+#define CRYPTO_CAST_CBC 4
+#define CRYPTO_SKIPJACK_CBC 5
+#define CRYPTO_MD5_HMAC 6
+#define CRYPTO_SHA1_HMAC 7
+#define CRYPTO_RIPEMD160_HMAC 8
+#define CRYPTO_MD5_KPDK 9
+#define CRYPTO_SHA1_KPDK 10
+#define CRYPTO_RIJNDAEL128_CBC 11 /* 128 bit blocksize */
+#define CRYPTO_AES_CBC 11 /* 128 bit blocksize -- the same as above */
+#define CRYPTO_ARC4 12
+#define CRYPTO_MD5 13
+#define CRYPTO_SHA1 14
+#define CRYPTO_SHA2_HMAC 15
+#define CRYPTO_NULL_HMAC 16
+#define CRYPTO_NULL_CBC 17
+#define CRYPTO_DEFLATE_COMP 18 /* Deflate compression algorithm */
+#define CRYPTO_ALGORITHM_MAX 18 /* Keep updated - see below */
+
+/* Algorithm flags */
+#define CRYPTO_ALG_FLAG_SUPPORTED 0x01 /* Algorithm is supported */
+#define CRYPTO_ALG_FLAG_RNG_ENABLE 0x02 /* Has HW RNG for DH/DSA */
+#define CRYPTO_ALG_FLAG_DSA_SHA 0x04 /* Can do SHA on msg */
+
+struct session_op {
+ u_int32_t cipher; /* ie. CRYPTO_DES_CBC */
+ u_int32_t mac; /* ie. CRYPTO_MD5_HMAC */
+
+ u_int32_t keylen; /* cipher key */
+ caddr_t key;
+ int mackeylen; /* mac key */
+ caddr_t mackey;
+
+ u_int32_t ses; /* returns: session # */
+};
+
+struct crypt_op {
+ u_int32_t ses;
+ u_int16_t op; /* i.e. COP_ENCRYPT */
+#define COP_ENCRYPT 1
+#define COP_DECRYPT 2
+ u_int16_t flags; /* always 0 */
+ u_int len;
+ caddr_t src, dst; /* become iov[] inside kernel */
+ caddr_t mac; /* must be big enough for chosen MAC */
+ caddr_t iv;
+};
+
+#define CRYPTO_MAX_MAC_LEN 20
+
+/* bignum parameter, in packed bytes, ... */
+struct crparam {
+ caddr_t crp_p;
+ u_int crp_nbits;
+};
+
+#define CRK_MAXPARAM 8
+
+struct crypt_kop {
+ u_int crk_op; /* ie. CRK_MOD_EXP or other */
+ u_int crk_status; /* return status */
+ u_short crk_iparams; /* # of input parameters */
+ u_short crk_oparams; /* # of output parameters */
+ u_int crk_pad1;
+ struct crparam crk_param[CRK_MAXPARAM];
+};
+#define CRK_ALGORITM_MIN 0
+#define CRK_MOD_EXP 0
+#define CRK_MOD_EXP_CRT 1
+#define CRK_DSA_SIGN 2
+#define CRK_DSA_VERIFY 3
+#define CRK_DH_COMPUTE_KEY 4
+#define CRK_ALGORITHM_MAX 4 /* Keep updated - see below */
+
+#define CRF_MOD_EXP (1 << CRK_MOD_EXP)
+#define CRF_MOD_EXP_CRT (1 << CRK_MOD_EXP_CRT)
+#define CRF_DSA_SIGN (1 << CRK_DSA_SIGN)
+#define CRF_DSA_VERIFY (1 << CRK_DSA_VERIFY)
+#define CRF_DH_COMPUTE_KEY (1 << CRK_DH_COMPUTE_KEY)
+
+/*
+ * done against open of /dev/crypto, to get a cloned descriptor.
+ * Please use F_SETFD against the cloned descriptor.
+ */
+#define CRIOGET _IOWR('c', 100, u_int32_t)
+
+/* the following are done against the cloned descriptor */
+#define CIOCGSESSION _IOWR('c', 101, struct session_op)
+#define CIOCFSESSION _IOW('c', 102, u_int32_t)
+#define CIOCCRYPT _IOWR('c', 103, struct crypt_op)
+#define CIOCKEY _IOWR('c', 104, struct crypt_kop)
+#define CIOCGSSESSION _IOWR('c', 105, struct session_op)
+
+#define CIOCASYMFEAT _IOR('c', 105, u_int32_t)
+
+#ifdef _KERNEL
+/* Standard initialization structure beginning */
+struct cryptoini {
+ int cri_alg; /* Algorithm to use */
+ int cri_klen; /* Key length, in bits */
+ int cri_rnd; /* Algorithm rounds, where relevant */
+ caddr_t cri_key; /* key to use */
+ u_int8_t cri_iv[EALG_MAX_BLOCK_LEN]; /* IV to use */
+ struct cryptoini *cri_next;
+};
+
+/* Describe boundaries of a single crypto operation */
+struct cryptodesc {
+ int crd_skip; /* How many bytes to ignore from start */
+ int crd_len; /* How many bytes to process */
+ int crd_inject; /* Where to inject results, if applicable */
+ int crd_flags;
+
+#define CRD_F_ENCRYPT 0x01 /* Set when doing encryption */
+#define CRD_F_IV_PRESENT 0x02 /* When encrypting, IV is already in
+ place, so don't copy. */
+#define CRD_F_IV_EXPLICIT 0x04 /* IV explicitly provided */
+#define CRD_F_DSA_SHA_NEEDED 0x08 /* Compute SHA-1 of buffer for DSA */
+#define CRD_F_COMP 0x0f /* Set when doing compression */
+
+ struct cryptoini CRD_INI; /* Initialization/context data */
+#define crd_iv CRD_INI.cri_iv
+#define crd_key CRD_INI.cri_key
+#define crd_rnd CRD_INI.cri_rnd
+#define crd_alg CRD_INI.cri_alg
+#define crd_klen CRD_INI.cri_klen
+
+ struct cryptodesc *crd_next;
+};
+
+/* Structure describing complete operation */
+struct cryptop {
+ TAILQ_ENTRY(cryptop) crp_next;
+
+ u_int64_t crp_sid; /* Session ID */
+ int crp_ilen; /* Input data total length */
+ int crp_olen; /* Result total length */
+ int crp_alloctype; /* Type of buf to allocate if needed */
+
+ int crp_etype; /*
+ * Error type (zero means no error).
+ * All error codes except EAGAIN
+ * indicate possible data corruption (as in,
+ * the data have been touched). On all
+ * errors, the crp_sid may have changed
+ * (reset to a new one), so the caller
+ * should always check and use the new
+ * value on future requests.
+ */
+ int crp_flags;
+
+#define CRYPTO_F_IMBUF 0x0001 /* Input/output are mbuf chains, otherwise contig */
+#define CRYPTO_F_IOV 0x0002 /* Input/output are uio */
+#define CRYPTO_F_REL 0x0004 /* Must return data in same place */
+#define CRYPTO_F_NODELAY 0x0008 /* Dispatch as quickly as possible */
+
+ caddr_t crp_buf; /* Data to be processed */
+ caddr_t crp_opaque; /* Opaque pointer, passed along */
+ struct cryptodesc *crp_desc; /* Linked list of processing descriptors */
+
+ int (*crp_callback)(struct cryptop *); /* Callback function */
+
+ caddr_t crp_mac;
+};
+
+#define CRYPTO_BUF_CONTIG 0x0
+#define CRYPTO_BUF_IOV 0x1
+#define CRYPTO_BUF_MBUF 0x2
+
+#define CRYPTO_OP_DECRYPT 0x0
+#define CRYPTO_OP_ENCRYPT 0x1
+
+/*
+ * Hints passed to process methods.
+ */
+#define CRYPTO_HINT_MORE 0x1 /* more ops coming shortly */
+
+struct cryptkop {
+ TAILQ_ENTRY(cryptkop) krp_next;
+
+ u_int krp_op; /* ie. CRK_MOD_EXP or other */
+ u_int krp_status; /* return status */
+ u_short krp_iparams; /* # of input parameters */
+ u_short krp_oparams; /* # of output parameters */
+ u_int32_t krp_hid;
+ struct crparam krp_param[CRK_MAXPARAM]; /* kvm */
+ int (*krp_callback)(struct cryptkop *);
+};
+
+/* Crypto capabilities structure */
+struct cryptocap {
+ u_int32_t cc_sessions;
+
+ /*
+ * Largest possible operator length (in bits) for each type of
+ * encryption algorithm.
+ */
+ u_int16_t cc_max_op_len[CRYPTO_ALGORITHM_MAX + 1];
+
+ u_int8_t cc_alg[CRYPTO_ALGORITHM_MAX + 1];
+
+ u_int8_t cc_kalg[CRK_ALGORITHM_MAX + 1];
+
+ u_int8_t cc_flags;
+ u_int8_t cc_qblocked; /* symmetric q blocked */
+ u_int8_t cc_kqblocked; /* asymmetric q blocked */
+#define CRYPTOCAP_F_CLEANUP 0x1
+#define CRYPTOCAP_F_SOFTWARE 0x02
+
+ void *cc_arg; /* callback argument */
+ int (*cc_newsession)(void*, u_int32_t*, struct cryptoini*);
+ int (*cc_process)(void*, struct cryptop *, int);
+ int (*cc_freesession)(void*, u_int64_t);
+ void *cc_karg; /* callback argument */
+ int (*cc_kprocess) (void*, struct cryptkop *, int);
+};
+
+MALLOC_DECLARE(M_CRYPTO_DATA);
+
+extern int crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int hard);
+extern int crypto_freesession(u_int64_t sid);
+extern int32_t crypto_get_driverid(u_int32_t flags);
+extern int crypto_register(u_int32_t driverid, int alg, u_int16_t maxoplen,
+ u_int32_t flags,
+ int (*newses)(void*, u_int32_t*, struct cryptoini*),
+ int (*freeses)(void*, u_int64_t),
+ int (*process)(void*, struct cryptop *, int),
+ void *arg);
+extern int crypto_kregister(u_int32_t, int, u_int32_t,
+ int (*)(void*, struct cryptkop *, int),
+ void *arg);
+extern int crypto_unregister(u_int32_t driverid, int alg);
+extern int crypto_unregister_all(u_int32_t driverid);
+extern int crypto_dispatch(struct cryptop *crp);
+extern int crypto_kdispatch(struct cryptkop *);
+#define CRYPTO_SYMQ 0x1
+#define CRYPTO_ASYMQ 0x2
+extern int crypto_unblock(u_int32_t, int);
+extern void crypto_done(struct cryptop *crp);
+extern void crypto_kdone(struct cryptkop *);
+extern int crypto_getfeat(int *);
+
+extern void crypto_freereq(struct cryptop *crp);
+extern struct cryptop *crypto_getreq(int num);
+
+extern int crypto_usercrypto; /* userland may do crypto requests */
+extern int crypto_userasymcrypto; /* userland may do asym crypto reqs */
+extern int crypto_devallowsoft; /* only use hardware crypto */
+
+/*
+ * Crypto-related utility routines used mainly by drivers.
+ *
+ * XXX these don't really belong here; but for now they're
+ * kept apart from the rest of the system.
+ */
+struct mbuf;
+struct mbuf *m_getptr(struct mbuf *, int, int *);
+
+struct uio;
+extern void cuio_copydata(struct uio* uio, int off, int len, caddr_t cp);
+extern void cuio_copyback(struct uio* uio, int off, int len, caddr_t cp);
+extern struct iovec *cuio_getptr(struct uio *uio, int loc, int *off);
+#endif /* _KERNEL */
+#endif /* _CRYPTO_CRYPTO_H_ */
diff --git a/sys/opencrypto/cryptosoft.c b/sys/opencrypto/cryptosoft.c
new file mode 100644
index 0000000..b6ead2a
--- /dev/null
+++ b/sys/opencrypto/cryptosoft.c
@@ -0,0 +1,1025 @@
+/* $FreeBSD$ */
+/* $OpenBSD: cryptosoft.c,v 1.35 2002/04/26 08:43:50 deraadt Exp $ */
+
+/*
+ * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
+ *
+ * This code was written by Angelos D. Keromytis in Athens, Greece, in
+ * February 2000. Network Security Technologies Inc. (NSTI) kindly
+ * supported the development of this code.
+ *
+ * Copyright (c) 2000, 2001 Angelos D. Keromytis
+ *
+ * Permission to use, copy, and modify this software with or without fee
+ * is hereby granted, provided that this entire notice is included in
+ * all source code copies of any software which is or includes a copy or
+ * modification of this software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+ * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/sysctl.h>
+#include <sys/errno.h>
+#include <sys/random.h>
+#include <sys/kernel.h>
+#include <sys/uio.h>
+
+#include <crypto/blowfish/blowfish.h>
+#include <crypto/cast128/cast128.h>
+#include <crypto/sha1.h>
+#include <opencrypto/rmd160.h>
+#include <opencrypto/skipjack.h>
+#include <sys/md5.h>
+
+#include <opencrypto/cryptodev.h>
+#include <opencrypto/cryptosoft.h>
+#include <opencrypto/xform.h>
+
+u_int8_t hmac_ipad_buffer[64] = {
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
+};
+
+u_int8_t hmac_opad_buffer[64] = {
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C
+};
+
+
+struct swcr_data **swcr_sessions = NULL;
+u_int32_t swcr_sesnum = 0;
+int32_t swcr_id = -1;
+
+#define COPYBACK(x, a, b, c, d) \
+ (x) == CRYPTO_BUF_MBUF ? m_copyback((struct mbuf *)a,b,c,d) \
+ : cuio_copyback((struct uio *)a,b,c,d)
+#define COPYDATA(x, a, b, c, d) \
+ (x) == CRYPTO_BUF_MBUF ? m_copydata((struct mbuf *)a,b,c,d) \
+ : cuio_copydata((struct uio *)a,b,c,d)
+
+static int swcr_encdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
+static int swcr_authcompute(struct cryptop *crp, struct cryptodesc *crd,
+ struct swcr_data *sw, caddr_t buf, int outtype);
+static int swcr_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
+static int swcr_process(void *, struct cryptop *, int);
+static int swcr_newsession(void *, u_int32_t *, struct cryptoini *);
+static int swcr_freesession(void *, u_int64_t);
+
+/*
+ * NB: These came over from openbsd and are kept private
+ * to the crypto code for now.
+ */
+extern int m_apply(struct mbuf *m, int off, int len,
+ int (*f)(caddr_t, caddr_t, unsigned int), caddr_t fstate);
+
+/*
+ * Apply a symmetric encryption/decryption algorithm.
+ */
+static int
+swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
+ int outtype)
+{
+ unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN], *idat;
+ unsigned char *ivp, piv[EALG_MAX_BLOCK_LEN];
+ struct enc_xform *exf;
+ int i, k, j, blks;
+
+ exf = sw->sw_exf;
+ blks = exf->blocksize;
+
+ /* Check for non-padded data */
+ if (crd->crd_len % blks)
+ return EINVAL;
+
+ /* Initialize the IV */
+ if (crd->crd_flags & CRD_F_ENCRYPT) {
+ /* IV explicitly provided ? */
+ if (crd->crd_flags & CRD_F_IV_EXPLICIT)
+ bcopy(crd->crd_iv, iv, blks);
+ else {
+ /* Get random IV */
+ for (i = 0;
+ i + sizeof (u_int32_t) < EALG_MAX_BLOCK_LEN;
+ i += sizeof (u_int32_t)) {
+ u_int32_t temp = arc4random();
+
+ bcopy(&temp, iv + i, sizeof(u_int32_t));
+ }
+ /*
+ * What if the block size is not a multiple
+ * of sizeof (u_int32_t), which is the size of
+ * what arc4random() returns ?
+ */
+ if (EALG_MAX_BLOCK_LEN % sizeof (u_int32_t) != 0) {
+ u_int32_t temp = arc4random();
+
+ bcopy (&temp, iv + i,
+ EALG_MAX_BLOCK_LEN - i);
+ }
+ }
+
+ /* Do we need to write the IV */
+ if (!(crd->crd_flags & CRD_F_IV_PRESENT)) {
+ COPYBACK(outtype, buf, crd->crd_inject, blks, iv);
+ }
+
+ } else { /* Decryption */
+ /* IV explicitly provided ? */
+ if (crd->crd_flags & CRD_F_IV_EXPLICIT)
+ bcopy(crd->crd_iv, iv, blks);
+ else {
+ /* Get IV off buf */
+ COPYDATA(outtype, buf, crd->crd_inject, blks, iv);
+ }
+ }
+
+ ivp = iv;
+
+ if (outtype == CRYPTO_BUF_CONTIG) {
+ if (crd->crd_flags & CRD_F_ENCRYPT) {
+ for (i = crd->crd_skip;
+ i < crd->crd_skip + crd->crd_len; i += blks) {
+ /* XOR with the IV/previous block, as appropriate. */
+ if (i == crd->crd_skip)
+ for (k = 0; k < blks; k++)
+ buf[i + k] ^= ivp[k];
+ else
+ for (k = 0; k < blks; k++)
+ buf[i + k] ^= buf[i + k - blks];
+ exf->encrypt(sw->sw_kschedule, buf + i);
+ }
+ } else { /* Decrypt */
+ /*
+ * Start at the end, so we don't need to keep the encrypted
+ * block as the IV for the next block.
+ */
+ for (i = crd->crd_skip + crd->crd_len - blks;
+ i >= crd->crd_skip; i -= blks) {
+ exf->decrypt(sw->sw_kschedule, buf + i);
+
+ /* XOR with the IV/previous block, as appropriate */
+ if (i == crd->crd_skip)
+ for (k = 0; k < blks; k++)
+ buf[i + k] ^= ivp[k];
+ else
+ for (k = 0; k < blks; k++)
+ buf[i + k] ^= buf[i + k - blks];
+ }
+ }
+
+ return 0;
+ } else if (outtype == CRYPTO_BUF_MBUF) {
+ struct mbuf *m = (struct mbuf *) buf;
+
+ /* Find beginning of data */
+ m = m_getptr(m, crd->crd_skip, &k);
+ if (m == NULL)
+ return EINVAL;
+
+ i = crd->crd_len;
+
+ while (i > 0) {
+ /*
+ * If there's insufficient data at the end of
+ * an mbuf, we have to do some copying.
+ */
+ if (m->m_len < k + blks && m->m_len != k) {
+ m_copydata(m, k, blks, blk);
+
+ /* Actual encryption/decryption */
+ if (crd->crd_flags & CRD_F_ENCRYPT) {
+ /* XOR with previous block */
+ for (j = 0; j < blks; j++)
+ blk[j] ^= ivp[j];
+
+ exf->encrypt(sw->sw_kschedule, blk);
+
+ /*
+ * Keep encrypted block for XOR'ing
+ * with next block
+ */
+ bcopy(blk, iv, blks);
+ ivp = iv;
+ } else { /* decrypt */
+ /*
+ * Keep encrypted block for XOR'ing
+ * with next block
+ */
+ if (ivp == iv)
+ bcopy(blk, piv, blks);
+ else
+ bcopy(blk, iv, blks);
+
+ exf->decrypt(sw->sw_kschedule, blk);
+
+ /* XOR with previous block */
+ for (j = 0; j < blks; j++)
+ blk[j] ^= ivp[j];
+
+ if (ivp == iv)
+ bcopy(piv, iv, blks);
+ else
+ ivp = iv;
+ }
+
+ /* Copy back decrypted block */
+ m_copyback(m, k, blks, blk);
+
+ /* Advance pointer */
+ m = m_getptr(m, k + blks, &k);
+ if (m == NULL)
+ return EINVAL;
+
+ i -= blks;
+
+ /* Could be done... */
+ if (i == 0)
+ break;
+ }
+
+ /* Skip possibly empty mbufs */
+ if (k == m->m_len) {
+ for (m = m->m_next; m && m->m_len == 0;
+ m = m->m_next)
+ ;
+ k = 0;
+ }
+
+ /* Sanity check */
+ if (m == NULL)
+ return EINVAL;
+
+ /*
+ * Warning: idat may point to garbage here, but
+ * we only use it in the while() loop, only if
+ * there are indeed enough data.
+ */
+ idat = mtod(m, unsigned char *) + k;
+
+ while (m->m_len >= k + blks && i > 0) {
+ if (crd->crd_flags & CRD_F_ENCRYPT) {
+ /* XOR with previous block/IV */
+ for (j = 0; j < blks; j++)
+ idat[j] ^= ivp[j];
+
+ exf->encrypt(sw->sw_kschedule, idat);
+ ivp = idat;
+ } else { /* decrypt */
+ /*
+ * Keep encrypted block to be used
+ * in next block's processing.
+ */
+ if (ivp == iv)
+ bcopy(idat, piv, blks);
+ else
+ bcopy(idat, iv, blks);
+
+ exf->decrypt(sw->sw_kschedule, idat);
+
+ /* XOR with previous block/IV */
+ for (j = 0; j < blks; j++)
+ idat[j] ^= ivp[j];
+
+ if (ivp == iv)
+ bcopy(piv, iv, blks);
+ else
+ ivp = iv;
+ }
+
+ idat += blks;
+ k += blks;
+ i -= blks;
+ }
+ }
+
+ return 0; /* Done with mbuf encryption/decryption */
+ } else if (outtype == CRYPTO_BUF_IOV) {
+ struct uio *uio = (struct uio *) buf;
+ struct iovec *iov;
+
+ /* Find beginning of data */
+ iov = cuio_getptr(uio, crd->crd_skip, &k);
+ if (iov == NULL)
+ return EINVAL;
+
+ i = crd->crd_len;
+
+ while (i > 0) {
+ /*
+ * If there's insufficient data at the end of
+ * an iovec, we have to do some copying.
+ */
+ if (iov->iov_len < k + blks && iov->iov_len != k) {
+ cuio_copydata(uio, k, blks, blk);
+
+ /* Actual encryption/decryption */
+ if (crd->crd_flags & CRD_F_ENCRYPT) {
+ /* XOR with previous block */
+ for (j = 0; j < blks; j++)
+ blk[j] ^= ivp[j];
+
+ exf->encrypt(sw->sw_kschedule, blk);
+
+ /*
+ * Keep encrypted block for XOR'ing
+ * with next block
+ */
+ bcopy(blk, iv, blks);
+ ivp = iv;
+ } else { /* decrypt */
+ /*
+ * Keep encrypted block for XOR'ing
+ * with next block
+ */
+ if (ivp == iv)
+ bcopy(blk, piv, blks);
+ else
+ bcopy(blk, iv, blks);
+
+ exf->decrypt(sw->sw_kschedule, blk);
+
+ /* XOR with previous block */
+ for (j = 0; j < blks; j++)
+ blk[j] ^= ivp[j];
+
+ if (ivp == iv)
+ bcopy(piv, iv, blks);
+ else
+ ivp = iv;
+ }
+
+ /* Copy back decrypted block */
+ cuio_copyback(uio, k, blks, blk);
+
+ /* Advance pointer */
+ iov = cuio_getptr(uio, k + blks, &k);
+ if (iov == NULL)
+ return EINVAL;
+
+ i -= blks;
+
+ /* Could be done... */
+ if (i == 0)
+ break;
+ }
+
+ /*
+ * Warning: idat may point to garbage here, but
+ * we only use it in the while() loop, only if
+ * there are indeed enough data.
+ */
+ idat = iov->iov_base + k;
+
+ while (iov->iov_len >= k + blks && i > 0) {
+ if (crd->crd_flags & CRD_F_ENCRYPT) {
+ /* XOR with previous block/IV */
+ for (j = 0; j < blks; j++)
+ idat[j] ^= ivp[j];
+
+ exf->encrypt(sw->sw_kschedule, idat);
+ ivp = idat;
+ } else { /* decrypt */
+ /*
+ * Keep encrypted block to be used
+ * in next block's processing.
+ */
+ if (ivp == iv)
+ bcopy(idat, piv, blks);
+ else
+ bcopy(idat, iv, blks);
+
+ exf->decrypt(sw->sw_kschedule, idat);
+
+ /* XOR with previous block/IV */
+ for (j = 0; j < blks; j++)
+ idat[j] ^= ivp[j];
+
+ if (ivp == iv)
+ bcopy(piv, iv, blks);
+ else
+ ivp = iv;
+ }
+
+ idat += blks;
+ k += blks;
+ i -= blks;
+ }
+ }
+
+ return 0; /* Done with mbuf encryption/decryption */
+ }
+
+ /* Unreachable */
+ return EINVAL;
+}
+
+/*
+ * Compute keyed-hash authenticator.
+ */
+static int
+swcr_authcompute(struct cryptop *crp, struct cryptodesc *crd,
+ struct swcr_data *sw, caddr_t buf, int outtype)
+{
+ unsigned char aalg[AALG_MAX_RESULT_LEN];
+ struct auth_hash *axf;
+ union authctx ctx;
+ int err;
+
+ if (sw->sw_ictx == 0)
+ return EINVAL;
+
+ axf = sw->sw_axf;
+
+ bcopy(sw->sw_ictx, &ctx, axf->ctxsize);
+
+ switch (outtype) {
+ case CRYPTO_BUF_CONTIG:
+ axf->Update(&ctx, buf + crd->crd_skip, crd->crd_len);
+ break;
+ case CRYPTO_BUF_MBUF:
+ err = m_apply((struct mbuf *) buf, crd->crd_skip, crd->crd_len,
+ (int (*)(caddr_t, caddr_t, unsigned int)) axf->Update,
+ (caddr_t) &ctx);
+ if (err)
+ return err;
+ break;
+ case CRYPTO_BUF_IOV:
+ default:
+ return EINVAL;
+ }
+
+ switch (sw->sw_alg) {
+ case CRYPTO_MD5_HMAC:
+ case CRYPTO_SHA1_HMAC:
+ case CRYPTO_SHA2_HMAC:
+ case CRYPTO_RIPEMD160_HMAC:
+ if (sw->sw_octx == NULL)
+ return EINVAL;
+
+ axf->Final(aalg, &ctx);
+ bcopy(sw->sw_octx, &ctx, axf->ctxsize);
+ axf->Update(&ctx, aalg, axf->hashsize);
+ axf->Final(aalg, &ctx);
+ break;
+
+ case CRYPTO_MD5_KPDK:
+ case CRYPTO_SHA1_KPDK:
+ if (sw->sw_octx == NULL)
+ return EINVAL;
+
+ axf->Update(&ctx, sw->sw_octx, sw->sw_klen);
+ axf->Final(aalg, &ctx);
+ break;
+
+ case CRYPTO_NULL_HMAC:
+ axf->Final(aalg, &ctx);
+ break;
+ }
+
+ /* Inject the authentication data */
+ if (outtype == CRYPTO_BUF_CONTIG)
+ bcopy(aalg, buf + crd->crd_inject, axf->authsize);
+ else
+ m_copyback((struct mbuf *) buf, crd->crd_inject,
+ axf->authsize, aalg);
+ return 0;
+}
+
+/*
+ * Apply a compression/decompression algorithm
+ */
+static int
+swcr_compdec(struct cryptodesc *crd, struct swcr_data *sw,
+ caddr_t buf, int outtype)
+{
+ u_int8_t *data, *out;
+ struct comp_algo *cxf;
+ int adj;
+ u_int32_t result;
+
+ cxf = sw->sw_cxf;
+
+ /* We must handle the whole buffer of data in one time
+ * then if there is not all the data in the mbuf, we must
+ * copy in a buffer.
+ */
+
+ MALLOC(data, u_int8_t *, crd->crd_len, M_CRYPTO_DATA, M_NOWAIT);
+ if (data == NULL)
+ return (EINVAL);
+ COPYDATA(outtype, buf, crd->crd_skip, crd->crd_len, data);
+
+ if (crd->crd_flags & CRD_F_COMP)
+ result = cxf->compress(data, crd->crd_len, &out);
+ else
+ result = cxf->decompress(data, crd->crd_len, &out);
+
+ FREE(data, M_CRYPTO_DATA);
+ if (result == 0)
+ return EINVAL;
+
+ /* Copy back the (de)compressed data. m_copyback is
+ * extending the mbuf as necessary.
+ */
+ sw->sw_size = result;
+ /* Check the compressed size when doing compression */
+ if (crd->crd_flags & CRD_F_COMP) {
+ if (result > crd->crd_len) {
+ /* Compression was useless, we lost time */
+ FREE(out, M_CRYPTO_DATA);
+ return 0;
+ }
+ }
+
+ COPYBACK(outtype, buf, crd->crd_skip, result, out);
+ if (result < crd->crd_len) {
+ adj = result - crd->crd_len;
+ if (outtype == CRYPTO_BUF_MBUF) {
+ adj = result - crd->crd_len;
+ m_adj((struct mbuf *)buf, adj);
+ } else {
+ struct uio *uio = (struct uio *)buf;
+ int ind;
+
+ adj = crd->crd_len - result;
+ ind = uio->uio_iovcnt - 1;
+
+ while (adj > 0 && ind >= 0) {
+ if (adj < uio->uio_iov[ind].iov_len) {
+ uio->uio_iov[ind].iov_len -= adj;
+ break;
+ }
+
+ adj -= uio->uio_iov[ind].iov_len;
+ uio->uio_iov[ind].iov_len = 0;
+ ind--;
+ uio->uio_iovcnt--;
+ }
+ }
+ }
+ FREE(out, M_CRYPTO_DATA);
+ return 0;
+}
+
+/*
+ * Generate a new software session.
+ */
+static int
+swcr_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)
+{
+ struct swcr_data **swd;
+ struct auth_hash *axf;
+ struct enc_xform *txf;
+ struct comp_algo *cxf;
+ u_int32_t i;
+ int k, error;
+
+ if (sid == NULL || cri == NULL)
+ return EINVAL;
+
+ if (swcr_sessions) {
+ for (i = 1; i < swcr_sesnum; i++)
+ if (swcr_sessions[i] == NULL)
+ break;
+ } else
+ i = 1; /* NB: to silence compiler warning */
+
+ if (swcr_sessions == NULL || i == swcr_sesnum) {
+ if (swcr_sessions == NULL) {
+ i = 1; /* We leave swcr_sessions[0] empty */
+ swcr_sesnum = CRYPTO_SW_SESSIONS;
+ } else
+ swcr_sesnum *= 2;
+
+ swd = malloc(swcr_sesnum * sizeof(struct swcr_data *),
+ M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
+ if (swd == NULL) {
+ /* Reset session number */
+ if (swcr_sesnum == CRYPTO_SW_SESSIONS)
+ swcr_sesnum = 0;
+ else
+ swcr_sesnum /= 2;
+ return ENOBUFS;
+ }
+
+ /* Copy existing sessions */
+ if (swcr_sessions) {
+ bcopy(swcr_sessions, swd,
+ (swcr_sesnum / 2) * sizeof(struct swcr_data *));
+ free(swcr_sessions, M_CRYPTO_DATA);
+ }
+
+ swcr_sessions = swd;
+ }
+
+ swd = &swcr_sessions[i];
+ *sid = i;
+
+ while (cri) {
+ MALLOC(*swd, struct swcr_data *, sizeof(struct swcr_data),
+ M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
+ if (*swd == NULL) {
+ swcr_freesession(NULL, i);
+ return ENOBUFS;
+ }
+
+ switch (cri->cri_alg) {
+ case CRYPTO_DES_CBC:
+ txf = &enc_xform_des;
+ goto enccommon;
+ case CRYPTO_3DES_CBC:
+ txf = &enc_xform_3des;
+ goto enccommon;
+ case CRYPTO_BLF_CBC:
+ txf = &enc_xform_blf;
+ goto enccommon;
+ case CRYPTO_CAST_CBC:
+ txf = &enc_xform_cast5;
+ goto enccommon;
+ case CRYPTO_SKIPJACK_CBC:
+ txf = &enc_xform_skipjack;
+ goto enccommon;
+ case CRYPTO_RIJNDAEL128_CBC:
+ txf = &enc_xform_rijndael128;
+ goto enccommon;
+ case CRYPTO_NULL_CBC:
+ txf = &enc_xform_null;
+ goto enccommon;
+ enccommon:
+ error = txf->setkey(&((*swd)->sw_kschedule),
+ cri->cri_key, cri->cri_klen / 8);
+ if (error) {
+ swcr_freesession(NULL, i);
+ return error;
+ }
+ (*swd)->sw_exf = txf;
+ break;
+
+ case CRYPTO_MD5_HMAC:
+ axf = &auth_hash_hmac_md5_96;
+ goto authcommon;
+ case CRYPTO_SHA1_HMAC:
+ axf = &auth_hash_hmac_sha1_96;
+ goto authcommon;
+ case CRYPTO_SHA2_HMAC:
+ if (cri->cri_klen == 256)
+ axf = &auth_hash_hmac_sha2_256;
+ else if (cri->cri_klen == 384)
+ axf = &auth_hash_hmac_sha2_384;
+ else if (cri->cri_klen == 512)
+ axf = &auth_hash_hmac_sha2_512;
+ else {
+ swcr_freesession(NULL, i);
+ return EINVAL;
+ }
+ goto authcommon;
+ case CRYPTO_NULL_HMAC:
+ axf = &auth_hash_null;
+ goto authcommon;
+ case CRYPTO_RIPEMD160_HMAC:
+ axf = &auth_hash_hmac_ripemd_160_96;
+ authcommon:
+ (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
+ M_NOWAIT);
+ if ((*swd)->sw_ictx == NULL) {
+ swcr_freesession(NULL, i);
+ return ENOBUFS;
+ }
+
+ (*swd)->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
+ M_NOWAIT);
+ if ((*swd)->sw_octx == NULL) {
+ swcr_freesession(NULL, i);
+ return ENOBUFS;
+ }
+
+ for (k = 0; k < cri->cri_klen / 8; k++)
+ cri->cri_key[k] ^= HMAC_IPAD_VAL;
+
+ axf->Init((*swd)->sw_ictx);
+ axf->Update((*swd)->sw_ictx, cri->cri_key,
+ cri->cri_klen / 8);
+ axf->Update((*swd)->sw_ictx, hmac_ipad_buffer,
+ HMAC_BLOCK_LEN - (cri->cri_klen / 8));
+
+ for (k = 0; k < cri->cri_klen / 8; k++)
+ cri->cri_key[k] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
+
+ axf->Init((*swd)->sw_octx);
+ axf->Update((*swd)->sw_octx, cri->cri_key,
+ cri->cri_klen / 8);
+ axf->Update((*swd)->sw_octx, hmac_opad_buffer,
+ HMAC_BLOCK_LEN - (cri->cri_klen / 8));
+
+ for (k = 0; k < cri->cri_klen / 8; k++)
+ cri->cri_key[k] ^= HMAC_OPAD_VAL;
+ (*swd)->sw_axf = axf;
+ break;
+
+ case CRYPTO_MD5_KPDK:
+ axf = &auth_hash_key_md5;
+ goto auth2common;
+
+ case CRYPTO_SHA1_KPDK:
+ axf = &auth_hash_key_sha1;
+ auth2common:
+ (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
+ M_NOWAIT);
+ if ((*swd)->sw_ictx == NULL) {
+ swcr_freesession(NULL, i);
+ return ENOBUFS;
+ }
+
+ /* Store the key so we can "append" it to the payload */
+ (*swd)->sw_octx = malloc(cri->cri_klen / 8, M_CRYPTO_DATA,
+ M_NOWAIT);
+ if ((*swd)->sw_octx == NULL) {
+ swcr_freesession(NULL, i);
+ return ENOBUFS;
+ }
+
+ (*swd)->sw_klen = cri->cri_klen / 8;
+ bcopy(cri->cri_key, (*swd)->sw_octx, cri->cri_klen / 8);
+ axf->Init((*swd)->sw_ictx);
+ axf->Update((*swd)->sw_ictx, cri->cri_key,
+ cri->cri_klen / 8);
+ axf->Final(NULL, (*swd)->sw_ictx);
+ (*swd)->sw_axf = axf;
+ break;
+#ifdef notdef
+ case CRYPTO_MD5:
+ axf = &auth_hash_md5;
+ goto auth3common;
+
+ case CRYPTO_SHA1:
+ axf = &auth_hash_sha1;
+ auth3common:
+ (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
+ M_NOWAIT);
+ if ((*swd)->sw_ictx == NULL) {
+ swcr_freesession(NULL, i);
+ return ENOBUFS;
+ }
+
+ axf->Init((*swd)->sw_ictx);
+ (*swd)->sw_axf = axf;
+ break;
+#endif
+ case CRYPTO_DEFLATE_COMP:
+ cxf = &comp_algo_deflate;
+ (*swd)->sw_cxf = cxf;
+ break;
+ default:
+ swcr_freesession(NULL, i);
+ return EINVAL;
+ }
+
+ (*swd)->sw_alg = cri->cri_alg;
+ cri = cri->cri_next;
+ swd = &((*swd)->sw_next);
+ }
+ return 0;
+}
+
+/*
+ * Free a session.
+ */
+static int
+swcr_freesession(void *arg, u_int64_t tid)
+{
+ struct swcr_data *swd;
+ struct enc_xform *txf;
+ struct auth_hash *axf;
+ struct comp_algo *cxf;
+ u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
+
+ if (sid > swcr_sesnum || swcr_sessions == NULL ||
+ swcr_sessions[sid] == NULL)
+ return EINVAL;
+
+ /* Silently accept and return */
+ if (sid == 0)
+ return 0;
+
+ while ((swd = swcr_sessions[sid]) != NULL) {
+ swcr_sessions[sid] = swd->sw_next;
+
+ switch (swd->sw_alg) {
+ case CRYPTO_DES_CBC:
+ case CRYPTO_3DES_CBC:
+ case CRYPTO_BLF_CBC:
+ case CRYPTO_CAST_CBC:
+ case CRYPTO_SKIPJACK_CBC:
+ case CRYPTO_RIJNDAEL128_CBC:
+ case CRYPTO_NULL_CBC:
+ txf = swd->sw_exf;
+
+ if (swd->sw_kschedule)
+ txf->zerokey(&(swd->sw_kschedule));
+ break;
+
+ case CRYPTO_MD5_HMAC:
+ case CRYPTO_SHA1_HMAC:
+ case CRYPTO_SHA2_HMAC:
+ case CRYPTO_RIPEMD160_HMAC:
+ case CRYPTO_NULL_HMAC:
+ axf = swd->sw_axf;
+
+ if (swd->sw_ictx) {
+ bzero(swd->sw_ictx, axf->ctxsize);
+ free(swd->sw_ictx, M_CRYPTO_DATA);
+ }
+ if (swd->sw_octx) {
+ bzero(swd->sw_octx, axf->ctxsize);
+ free(swd->sw_octx, M_CRYPTO_DATA);
+ }
+ break;
+
+ case CRYPTO_MD5_KPDK:
+ case CRYPTO_SHA1_KPDK:
+ axf = swd->sw_axf;
+
+ if (swd->sw_ictx) {
+ bzero(swd->sw_ictx, axf->ctxsize);
+ free(swd->sw_ictx, M_CRYPTO_DATA);
+ }
+ if (swd->sw_octx) {
+ bzero(swd->sw_octx, swd->sw_klen);
+ free(swd->sw_octx, M_CRYPTO_DATA);
+ }
+ break;
+
+ case CRYPTO_MD5:
+ case CRYPTO_SHA1:
+ axf = swd->sw_axf;
+
+ if (swd->sw_ictx)
+ free(swd->sw_ictx, M_CRYPTO_DATA);
+ break;
+
+ case CRYPTO_DEFLATE_COMP:
+ cxf = swd->sw_cxf;
+ break;
+ }
+
+ FREE(swd, M_CRYPTO_DATA);
+ }
+ return 0;
+}
+
+/*
+ * Process a software request.
+ */
+static int
+swcr_process(void *arg, struct cryptop *crp, int hint)
+{
+ struct cryptodesc *crd;
+ struct swcr_data *sw;
+ u_int32_t lid;
+ int type;
+
+ /* Sanity check */
+ if (crp == NULL)
+ return EINVAL;
+
+ if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
+ crp->crp_etype = EINVAL;
+ goto done;
+ }
+
+ lid = crp->crp_sid & 0xffffffff;
+ if (lid >= swcr_sesnum || lid == 0 || swcr_sessions[lid] == NULL) {
+ crp->crp_etype = ENOENT;
+ goto done;
+ }
+
+ if (crp->crp_flags & CRYPTO_F_IMBUF) {
+ type = CRYPTO_BUF_MBUF;
+ } else if (crp->crp_flags & CRYPTO_F_IOV) {
+ type = CRYPTO_BUF_IOV;
+ } else {
+ type = CRYPTO_BUF_CONTIG;
+ }
+
+ /* Go through crypto descriptors, processing as we go */
+ for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
+ /*
+ * Find the crypto context.
+ *
+ * XXX Note that the logic here prevents us from having
+ * XXX the same algorithm multiple times in a session
+ * XXX (or rather, we can but it won't give us the right
+ * XXX results). To do that, we'd need some way of differentiating
+ * XXX between the various instances of an algorithm (so we can
+ * XXX locate the correct crypto context).
+ */
+ for (sw = swcr_sessions[lid];
+ sw && sw->sw_alg != crd->crd_alg;
+ sw = sw->sw_next)
+ ;
+
+ /* No such context ? */
+ if (sw == NULL) {
+ crp->crp_etype = EINVAL;
+ goto done;
+ }
+ switch (sw->sw_alg) {
+ case CRYPTO_DES_CBC:
+ case CRYPTO_3DES_CBC:
+ case CRYPTO_BLF_CBC:
+ case CRYPTO_CAST_CBC:
+ case CRYPTO_SKIPJACK_CBC:
+ case CRYPTO_RIJNDAEL128_CBC:
+ if ((crp->crp_etype = swcr_encdec(crd, sw,
+ crp->crp_buf, type)) != 0)
+ goto done;
+ break;
+ case CRYPTO_NULL_CBC:
+ crp->crp_etype = 0;
+ break;
+ case CRYPTO_MD5_HMAC:
+ case CRYPTO_SHA1_HMAC:
+ case CRYPTO_SHA2_HMAC:
+ case CRYPTO_RIPEMD160_HMAC:
+ case CRYPTO_NULL_HMAC:
+ case CRYPTO_MD5_KPDK:
+ case CRYPTO_SHA1_KPDK:
+ case CRYPTO_MD5:
+ case CRYPTO_SHA1:
+ if ((crp->crp_etype = swcr_authcompute(crp, crd, sw,
+ crp->crp_buf, type)) != 0)
+ goto done;
+ break;
+
+ case CRYPTO_DEFLATE_COMP:
+ if ((crp->crp_etype = swcr_compdec(crd, sw,
+ crp->crp_buf, type)) != 0)
+ goto done;
+ else
+ crp->crp_olen = (int)sw->sw_size;
+ break;
+
+ default:
+ /* Unknown/unsupported algorithm */
+ crp->crp_etype = EINVAL;
+ goto done;
+ }
+ }
+
+done:
+ crypto_done(crp);
+ return 0;
+}
+
+/*
+ * Initialize the driver, called from the kernel main().
+ */
+static void
+swcr_init(void)
+{
+ swcr_id = crypto_get_driverid(CRYPTOCAP_F_SOFTWARE);
+ if (swcr_id < 0)
+ panic("Software crypto device cannot initialize!");
+ crypto_register(swcr_id, CRYPTO_DES_CBC,
+ 0, 0, swcr_newsession, swcr_freesession, swcr_process, NULL);
+#define REGISTER(alg) \
+ crypto_register(swcr_id, alg, 0,0,NULL,NULL,NULL,NULL)
+ REGISTER(CRYPTO_3DES_CBC);
+ REGISTER(CRYPTO_BLF_CBC);
+ REGISTER(CRYPTO_CAST_CBC);
+ REGISTER(CRYPTO_SKIPJACK_CBC);
+ REGISTER(CRYPTO_NULL_CBC);
+ REGISTER(CRYPTO_MD5_HMAC);
+ REGISTER(CRYPTO_SHA1_HMAC);
+ REGISTER(CRYPTO_SHA2_HMAC);
+ REGISTER(CRYPTO_RIPEMD160_HMAC);
+ REGISTER(CRYPTO_NULL_HMAC);
+ REGISTER(CRYPTO_MD5_KPDK);
+ REGISTER(CRYPTO_SHA1_KPDK);
+ REGISTER(CRYPTO_MD5);
+ REGISTER(CRYPTO_SHA1);
+ REGISTER(CRYPTO_RIJNDAEL128_CBC);
+ REGISTER(CRYPTO_DEFLATE_COMP);
+#undef REGISTER
+}
+SYSINIT(cryptosoft_init, SI_SUB_PSEUDO, SI_ORDER_ANY, swcr_init, NULL)
diff --git a/sys/opencrypto/cryptosoft.h b/sys/opencrypto/cryptosoft.h
new file mode 100644
index 0000000..dea997e
--- /dev/null
+++ b/sys/opencrypto/cryptosoft.h
@@ -0,0 +1,65 @@
+/* $FreeBSD$ */
+/* $OpenBSD: cryptosoft.h,v 1.10 2002/04/22 23:10:09 deraadt Exp $ */
+
+/*
+ * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
+ *
+ * This code was written by Angelos D. Keromytis in Athens, Greece, in
+ * February 2000. Network Security Technologies Inc. (NSTI) kindly
+ * supported the development of this code.
+ *
+ * Copyright (c) 2000 Angelos D. Keromytis
+ *
+ * Permission to use, copy, and modify this software with or without fee
+ * is hereby granted, provided that this entire notice is included in
+ * all source code copies of any software which is or includes a copy or
+ * modification of this software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+ * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ */
+
+#ifndef _CRYPTO_CRYPTOSOFT_H_
+#define _CRYPTO_CRYPTOSOFT_H_
+
+/* Software session entry */
+struct swcr_data {
+ int sw_alg; /* Algorithm */
+ union {
+ struct {
+ u_int8_t *SW_ictx;
+ u_int8_t *SW_octx;
+ u_int32_t SW_klen;
+ struct auth_hash *SW_axf;
+ } SWCR_AUTH;
+ struct {
+ u_int8_t *SW_kschedule;
+ struct enc_xform *SW_exf;
+ } SWCR_ENC;
+ struct {
+ u_int32_t SW_size;
+ struct comp_algo *SW_cxf;
+ } SWCR_COMP;
+ } SWCR_UN;
+
+#define sw_ictx SWCR_UN.SWCR_AUTH.SW_ictx
+#define sw_octx SWCR_UN.SWCR_AUTH.SW_octx
+#define sw_klen SWCR_UN.SWCR_AUTH.SW_klen
+#define sw_axf SWCR_UN.SWCR_AUTH.SW_axf
+#define sw_kschedule SWCR_UN.SWCR_ENC.SW_kschedule
+#define sw_exf SWCR_UN.SWCR_ENC.SW_exf
+#define sw_size SWCR_UN.SWCR_COMP.SW_size
+#define sw_cxf SWCR_UN.SWCR_COMP.SW_cxf
+
+ struct swcr_data *sw_next;
+};
+
+#ifdef _KERNEL
+extern u_int8_t hmac_ipad_buffer[64];
+extern u_int8_t hmac_opad_buffer[64];
+#endif /* _KERNEL */
+
+#endif /* _CRYPTO_CRYPTO_H_ */
diff --git a/sys/opencrypto/deflate.c b/sys/opencrypto/deflate.c
new file mode 100644
index 0000000..af13ee6
--- /dev/null
+++ b/sys/opencrypto/deflate.c
@@ -0,0 +1,189 @@
+/* $FreeBSD$ */
+/* $OpenBSD: deflate.c,v 1.3 2001/08/20 02:45:22 hugh Exp $ */
+
+/*
+ * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file contains a wrapper around the deflate algo compression
+ * functions using the zlib library (see net/zlib.{c,h})
+ */
+
+#include <sys/types.h>
+#include <sys/malloc.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <net/zlib.h>
+
+#include <opencrypto/cryptodev.h>
+#include <opencrypto/deflate.h>
+
+int window_inflate = -1 * MAX_WBITS;
+int window_deflate = -12;
+
+/*
+ * This function takes a block of data and (de)compress it using the deflate
+ * algorithm
+ */
+
+u_int32_t
+deflate_global(data, size, decomp, out)
+ u_int8_t *data;
+ u_int32_t size;
+ int decomp;
+ u_int8_t **out;
+{
+ /* decomp indicates whether we compress (0) or decompress (1) */
+
+ z_stream zbuf;
+ u_int8_t *output;
+ u_int32_t count, result;
+ int error, i = 0, j;
+ struct deflate_buf buf[ZBUF];
+
+ bzero(&zbuf, sizeof(z_stream));
+ for (j = 0; j < ZBUF; j++)
+ buf[j].flag = 0;
+
+ zbuf.next_in = data; /* data that is going to be processed */
+ zbuf.zalloc = z_alloc;
+ zbuf.zfree = z_free;
+ zbuf.opaque = Z_NULL;
+ zbuf.avail_in = size; /* Total length of data to be processed */
+
+ if (!decomp) {
+ MALLOC(buf[i].out, u_int8_t *, (u_long) size, M_CRYPTO_DATA,
+ M_NOWAIT);
+ if (buf[i].out == NULL)
+ goto bad;
+ buf[i].size = size;
+ buf[i].flag = 1;
+ i++;
+ } else {
+ /*
+ * Choose a buffer with 4x the size of the input buffer
+ * for the size of the output buffer in the case of
+ * decompression. If it's not sufficient, it will need to be
+ * updated while the decompression is going on
+ */
+
+ MALLOC(buf[i].out, u_int8_t *, (u_long) (size * 4),
+ M_CRYPTO_DATA, M_NOWAIT);
+ if (buf[i].out == NULL)
+ goto bad;
+ buf[i].size = size * 4;
+ buf[i].flag = 1;
+ i++;
+ }
+
+ zbuf.next_out = buf[0].out;
+ zbuf.avail_out = buf[0].size;
+
+ error = decomp ? inflateInit2(&zbuf, window_inflate) :
+ deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD,
+ window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY);
+
+ if (error != Z_OK)
+ goto bad;
+ for (;;) {
+ error = decomp ? inflate(&zbuf, Z_PARTIAL_FLUSH) :
+ deflate(&zbuf, Z_PARTIAL_FLUSH);
+ if (error != Z_OK && error != Z_STREAM_END)
+ goto bad;
+ else if (zbuf.avail_in == 0 && zbuf.avail_out != 0)
+ goto end;
+ else if (zbuf.avail_out == 0 && i < (ZBUF - 1)) {
+ /* we need more output space, allocate size */
+ MALLOC(buf[i].out, u_int8_t *, (u_long) size,
+ M_CRYPTO_DATA, M_NOWAIT);
+ if (buf[i].out == NULL)
+ goto bad;
+ zbuf.next_out = buf[i].out;
+ buf[i].size = size;
+ buf[i].flag = 1;
+ zbuf.avail_out = buf[i].size;
+ i++;
+ } else
+ goto bad;
+ }
+
+end:
+ result = count = zbuf.total_out;
+
+ MALLOC(*out, u_int8_t *, (u_long) result, M_CRYPTO_DATA, M_NOWAIT);
+ if (*out == NULL)
+ goto bad;
+ if (decomp)
+ inflateEnd(&zbuf);
+ else
+ deflateEnd(&zbuf);
+ output = *out;
+ for (j = 0; buf[j].flag != 0; j++) {
+ if (count > buf[j].size) {
+ bcopy(buf[j].out, *out, buf[j].size);
+ *out += buf[j].size;
+ FREE(buf[j].out, M_CRYPTO_DATA);
+ count -= buf[j].size;
+ } else {
+ /* it should be the last buffer */
+ bcopy(buf[j].out, *out, count);
+ *out += count;
+ FREE(buf[j].out, M_CRYPTO_DATA);
+ count = 0;
+ }
+ }
+ *out = output;
+ return result;
+
+bad:
+ *out = NULL;
+ for (j = 0; buf[j].flag != 0; j++)
+ FREE(buf[j].out, M_CRYPTO_DATA);
+ if (decomp)
+ inflateEnd(&zbuf);
+ else
+ deflateEnd(&zbuf);
+ return 0;
+}
+
+void *
+z_alloc(nil, type, size)
+ void *nil;
+ u_int type, size;
+{
+ void *ptr;
+
+ ptr = malloc(type *size, M_CRYPTO_DATA, M_NOWAIT);
+ return ptr;
+}
+
+void
+z_free(nil, ptr)
+ void *nil, *ptr;
+{
+ free(ptr, M_CRYPTO_DATA);
+}
diff --git a/sys/opencrypto/deflate.h b/sys/opencrypto/deflate.h
new file mode 100644
index 0000000..81a8be7
--- /dev/null
+++ b/sys/opencrypto/deflate.h
@@ -0,0 +1,56 @@
+/* $FreeBSD$ */
+/* $OpenBSD: deflate.h,v 1.3 2002/03/14 01:26:51 millert Exp $ */
+
+/*
+ * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Definition for the wrapper around the deflate compression
+ * algorithm used in /sys/crypto
+ */
+
+#ifndef _CRYPTO_DEFLATE_H_
+#define _CRYPTO_DEFLATE_H_
+
+#include <net/zlib.h>
+
+#define Z_METHOD 8
+#define Z_MEMLEVEL 8
+#define MINCOMP 2 /* won't be used, but must be defined */
+#define ZBUF 10
+
+u_int32_t deflate_global(u_int8_t *, u_int32_t, int, u_int8_t **);
+void *z_alloc(void *, u_int, u_int);
+void z_free(void *, void *);
+
+struct deflate_buf {
+ u_int8_t *out;
+ u_int32_t size;
+ int flag;
+};
+
+#endif /* _CRYPTO_DEFLATE_H_ */
diff --git a/sys/opencrypto/rijndael.c b/sys/opencrypto/rijndael.c
new file mode 100644
index 0000000..5d346d5
--- /dev/null
+++ b/sys/opencrypto/rijndael.c
@@ -0,0 +1,1244 @@
+/* $FreeBSD$ */
+/* $OpenBSD: rijndael.c,v 1.12 2002/07/10 17:53:54 deraadt Exp $ */
+
+/**
+ * rijndael-alg-fst.c
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <opencrypto/rijndael.h>
+
+#define FULL_UNROLL
+
+/*
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+Te4[x] = S [x].[01, 01, 01, 01];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+Td4[x] = Si[x].[01, 01, 01, 01];
+*/
+
+static const u32 Te0[256] = {
+ 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+ 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+ 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+ 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+ 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+ 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+ 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+ 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+ 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+ 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+ 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+ 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+ 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+ 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+ 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+ 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+ 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+ 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+ 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+ 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+ 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+ 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+ 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+ 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+ 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+ 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+ 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+ 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+ 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+ 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+ 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+ 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+ 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+ 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+ 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+ 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+ 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+ 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+ 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+ 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+ 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+ 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+ 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+ 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+ 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+ 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+ 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+ 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+ 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+ 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+ 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+ 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+ 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+ 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+ 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+ 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+ 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+ 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+ 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+ 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+ 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+ 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+ 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+ 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+static const u32 Te1[256] = {
+ 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+ 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+ 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+ 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+ 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+ 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+ 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+ 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+ 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+ 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+ 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+ 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+ 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+ 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+ 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+ 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+ 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+ 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+ 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+ 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+ 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+ 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+ 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+ 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+ 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+ 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+ 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+ 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+ 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+ 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+ 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+ 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+ 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+ 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+ 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+ 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+ 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+ 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+ 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+ 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+ 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+ 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+ 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+ 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+ 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+ 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+ 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+ 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+ 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+ 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+ 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+ 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+ 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+ 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+ 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+ 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+ 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+ 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+ 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+ 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+ 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+ 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+ 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+ 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+};
+static const u32 Te2[256] = {
+ 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+ 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+ 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+ 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+ 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+ 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+ 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+ 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+ 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+ 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+ 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+ 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+ 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+ 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+ 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+ 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+ 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+ 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+ 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+ 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+ 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+ 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+ 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+ 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+ 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+ 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+ 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+ 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+ 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+ 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+ 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+ 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+ 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+ 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+ 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+ 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+ 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+ 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+ 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+ 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+ 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+ 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+ 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+ 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+ 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+ 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+ 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+ 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+ 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+ 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+ 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+ 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+ 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+ 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+ 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+ 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+ 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+ 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+ 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+ 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+ 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+ 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+ 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+ 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+};
+static const u32 Te3[256] = {
+
+ 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+ 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+ 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+ 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+ 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+ 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+ 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+ 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+ 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+ 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+ 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+ 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+ 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+ 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+ 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+ 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+ 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+ 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+ 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+ 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+ 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+ 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+ 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+ 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+ 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+ 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+ 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+ 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+ 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+ 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+ 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+ 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+ 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+ 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+ 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+ 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+ 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+ 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+ 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+ 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+ 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+ 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+ 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+ 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+ 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+ 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+ 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+ 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+ 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+ 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+ 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+ 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+ 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+ 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+ 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+ 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+ 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+ 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+ 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+ 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+ 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+ 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+ 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+ 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+};
+static const u32 Te4[256] = {
+ 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
+ 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
+ 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
+ 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
+ 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
+ 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
+ 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
+ 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
+ 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
+ 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
+ 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
+ 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
+ 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
+ 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
+ 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
+ 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
+ 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
+ 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
+ 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
+ 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
+ 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
+ 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
+ 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
+ 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
+ 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
+ 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
+ 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
+ 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
+ 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
+ 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
+ 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
+ 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
+ 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
+ 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
+ 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
+ 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
+ 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
+ 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
+ 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
+ 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
+ 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
+ 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
+ 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
+ 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
+ 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
+ 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
+ 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
+ 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
+ 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
+ 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
+ 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
+ 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
+ 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
+ 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
+ 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
+ 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
+ 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
+ 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
+ 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
+ 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
+ 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
+ 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
+ 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
+ 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
+};
+static const u32 Td0[256] = {
+ 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+ 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+ 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+ 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+ 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+ 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+ 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+ 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+ 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+ 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+ 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+ 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+ 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+ 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+ 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+ 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+ 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+ 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+ 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+ 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+ 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+ 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+ 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+ 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+ 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+ 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+ 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+ 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+ 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+ 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+ 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+ 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+ 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+ 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+ 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+ 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+ 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+ 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+ 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+ 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+ 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+ 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+ 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+ 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+ 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+ 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+ 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+ 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+ 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+ 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+ 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+ 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+ 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+ 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+ 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+ 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+ 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+ 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+ 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+ 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+ 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+ 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+ 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+ 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+static const u32 Td1[256] = {
+ 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
+ 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
+ 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
+ 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
+ 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
+ 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
+ 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
+ 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
+ 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
+ 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
+ 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
+ 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
+ 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
+ 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
+ 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
+ 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
+ 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
+ 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
+ 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
+ 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
+ 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
+ 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
+ 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
+ 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
+ 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
+ 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
+ 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
+ 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
+ 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
+ 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
+ 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
+ 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
+ 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
+ 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
+ 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
+ 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
+ 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
+ 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
+ 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
+ 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
+ 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
+ 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
+ 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
+ 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
+ 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
+ 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
+ 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
+ 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
+ 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
+ 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
+ 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
+ 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
+ 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
+ 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
+ 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
+ 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
+ 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
+ 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
+ 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
+ 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
+ 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
+ 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
+ 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
+ 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
+};
+static const u32 Td2[256] = {
+ 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
+ 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
+ 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
+ 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
+ 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
+ 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
+ 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
+ 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
+ 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
+ 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
+ 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
+ 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
+ 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
+ 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
+ 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
+ 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
+ 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
+ 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
+ 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
+ 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
+
+ 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
+ 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
+ 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
+ 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
+ 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
+ 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
+ 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
+ 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
+ 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
+ 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
+ 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
+ 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
+ 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
+ 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
+ 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
+ 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
+ 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
+ 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
+ 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
+ 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
+ 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
+ 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
+ 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
+ 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
+ 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
+ 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
+ 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
+ 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
+ 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
+ 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
+ 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
+ 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
+ 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
+ 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
+ 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
+ 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
+ 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
+ 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
+ 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
+ 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
+ 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
+ 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
+ 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
+ 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
+};
+static const u32 Td3[256] = {
+ 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
+ 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
+ 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
+ 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
+ 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
+ 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
+ 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
+ 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
+ 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
+ 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
+ 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
+ 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
+ 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
+ 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
+ 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
+ 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
+ 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
+ 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
+ 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
+ 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
+ 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
+ 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
+ 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
+ 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
+ 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
+ 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
+ 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
+ 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
+ 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
+ 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
+ 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
+ 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
+ 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
+ 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
+ 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
+ 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
+ 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
+ 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
+ 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
+ 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
+ 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
+ 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
+ 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
+ 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
+ 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
+ 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
+ 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
+ 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
+ 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
+ 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
+ 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
+ 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
+ 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
+ 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
+ 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
+ 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
+ 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
+ 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
+ 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
+ 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
+ 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
+ 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
+ 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
+ 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
+};
+static const u32 Td4[256] = {
+ 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
+ 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
+ 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
+ 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
+ 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
+ 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
+ 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
+ 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
+ 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
+ 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
+ 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
+ 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
+ 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
+ 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
+ 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
+ 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
+ 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
+ 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
+ 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
+ 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
+ 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
+ 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
+ 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
+ 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
+ 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
+ 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
+ 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
+ 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
+ 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
+ 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
+ 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
+ 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
+ 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
+ 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
+ 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
+ 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
+ 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
+ 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
+ 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
+ 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
+ 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
+ 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
+ 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
+ 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
+ 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
+ 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
+ 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
+ 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
+ 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
+ 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
+ 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
+ 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
+ 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
+ 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
+ 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
+ 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
+ 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
+ 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
+ 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
+ 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
+ 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
+ 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
+ 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
+ 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
+};
+static const u32 rcon[] = {
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
+ 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
+#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
+
+/**
+ * Expand the cipher key into the encryption key schedule.
+ *
+ * @return the number of rounds for the given cipher key size.
+ */
+static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
+ int i = 0;
+ u32 temp;
+
+ rk[0] = GETU32(cipherKey );
+ rk[1] = GETU32(cipherKey + 4);
+ rk[2] = GETU32(cipherKey + 8);
+ rk[3] = GETU32(cipherKey + 12);
+ if (keyBits == 128) {
+ for (;;) {
+ temp = rk[3];
+ rk[4] = rk[0] ^
+ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
+ (Te4[(temp ) & 0xff] & 0x0000ff00) ^
+ (Te4[(temp >> 24) ] & 0x000000ff) ^
+ rcon[i];
+ rk[5] = rk[1] ^ rk[4];
+ rk[6] = rk[2] ^ rk[5];
+ rk[7] = rk[3] ^ rk[6];
+ if (++i == 10) {
+ return 10;
+ }
+ rk += 4;
+ }
+ }
+ rk[4] = GETU32(cipherKey + 16);
+ rk[5] = GETU32(cipherKey + 20);
+ if (keyBits == 192) {
+ for (;;) {
+ temp = rk[ 5];
+ rk[ 6] = rk[ 0] ^
+ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
+ (Te4[(temp ) & 0xff] & 0x0000ff00) ^
+ (Te4[(temp >> 24) ] & 0x000000ff) ^
+ rcon[i];
+ rk[ 7] = rk[ 1] ^ rk[ 6];
+ rk[ 8] = rk[ 2] ^ rk[ 7];
+ rk[ 9] = rk[ 3] ^ rk[ 8];
+ if (++i == 8) {
+ return 12;
+ }
+ rk[10] = rk[ 4] ^ rk[ 9];
+ rk[11] = rk[ 5] ^ rk[10];
+ rk += 6;
+ }
+ }
+ rk[6] = GETU32(cipherKey + 24);
+ rk[7] = GETU32(cipherKey + 28);
+ if (keyBits == 256) {
+ for (;;) {
+ temp = rk[ 7];
+ rk[ 8] = rk[ 0] ^
+ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
+ (Te4[(temp ) & 0xff] & 0x0000ff00) ^
+ (Te4[(temp >> 24) ] & 0x000000ff) ^
+ rcon[i];
+ rk[ 9] = rk[ 1] ^ rk[ 8];
+ rk[10] = rk[ 2] ^ rk[ 9];
+ rk[11] = rk[ 3] ^ rk[10];
+ if (++i == 7) {
+ return 14;
+ }
+ temp = rk[11];
+ rk[12] = rk[ 4] ^
+ (Te4[(temp >> 24) ] & 0xff000000) ^
+ (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
+ (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^
+ (Te4[(temp ) & 0xff] & 0x000000ff);
+ rk[13] = rk[ 5] ^ rk[12];
+ rk[14] = rk[ 6] ^ rk[13];
+ rk[15] = rk[ 7] ^ rk[14];
+ rk += 8;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Expand the cipher key into the decryption key schedule.
+ *
+ * @return the number of rounds for the given cipher key size.
+ */
+static int
+rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits,
+ int have_encrypt) {
+ int Nr, i, j;
+ u32 temp;
+
+ if (have_encrypt) {
+ Nr = have_encrypt;
+ } else {
+ /* expand the cipher key: */
+ Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
+ }
+ /* invert the order of the round keys: */
+ for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
+ temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;
+ temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
+ temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
+ temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
+ }
+ /* apply the inverse MixColumn transform to all round keys but the first and the last: */
+ for (i = 1; i < Nr; i++) {
+ rk += 4;
+ rk[0] =
+ Td0[Te4[(rk[0] >> 24) ] & 0xff] ^
+ Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
+ Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^
+ Td3[Te4[(rk[0] ) & 0xff] & 0xff];
+ rk[1] =
+ Td0[Te4[(rk[1] >> 24) ] & 0xff] ^
+ Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
+ Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^
+ Td3[Te4[(rk[1] ) & 0xff] & 0xff];
+ rk[2] =
+ Td0[Te4[(rk[2] >> 24) ] & 0xff] ^
+ Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
+ Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^
+ Td3[Te4[(rk[2] ) & 0xff] & 0xff];
+ rk[3] =
+ Td0[Te4[(rk[3] >> 24) ] & 0xff] ^
+ Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
+ Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^
+ Td3[Te4[(rk[3] ) & 0xff] & 0xff];
+ }
+ return Nr;
+}
+
+static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) {
+ u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+ int r;
+#endif /* ?FULL_UNROLL */
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ s0 = GETU32(pt ) ^ rk[0];
+ s1 = GETU32(pt + 4) ^ rk[1];
+ s2 = GETU32(pt + 8) ^ rk[2];
+ s3 = GETU32(pt + 12) ^ rk[3];
+#ifdef FULL_UNROLL
+ /* round 1: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
+ /* round 2: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
+ /* round 3: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
+ /* round 4: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
+ /* round 5: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
+ /* round 6: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
+ /* round 7: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
+ /* round 8: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
+ /* round 9: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
+ if (Nr > 10) {
+ /* round 10: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
+ /* round 11: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
+ if (Nr > 12) {
+ /* round 12: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
+ /* round 13: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
+ }
+ }
+ rk += Nr << 2;
+#else /* !FULL_UNROLL */
+ /*
+ * Nr - 1 full rounds:
+ */
+ r = Nr >> 1;
+ for (;;) {
+ t0 =
+ Te0[(s0 >> 24) ] ^
+ Te1[(s1 >> 16) & 0xff] ^
+ Te2[(s2 >> 8) & 0xff] ^
+ Te3[(s3 ) & 0xff] ^
+ rk[4];
+ t1 =
+ Te0[(s1 >> 24) ] ^
+ Te1[(s2 >> 16) & 0xff] ^
+ Te2[(s3 >> 8) & 0xff] ^
+ Te3[(s0 ) & 0xff] ^
+ rk[5];
+ t2 =
+ Te0[(s2 >> 24) ] ^
+ Te1[(s3 >> 16) & 0xff] ^
+ Te2[(s0 >> 8) & 0xff] ^
+ Te3[(s1 ) & 0xff] ^
+ rk[6];
+ t3 =
+ Te0[(s3 >> 24) ] ^
+ Te1[(s0 >> 16) & 0xff] ^
+ Te2[(s1 >> 8) & 0xff] ^
+ Te3[(s2 ) & 0xff] ^
+ rk[7];
+
+ rk += 8;
+ if (--r == 0) {
+ break;
+ }
+
+ s0 =
+ Te0[(t0 >> 24) ] ^
+ Te1[(t1 >> 16) & 0xff] ^
+ Te2[(t2 >> 8) & 0xff] ^
+ Te3[(t3 ) & 0xff] ^
+ rk[0];
+ s1 =
+ Te0[(t1 >> 24) ] ^
+ Te1[(t2 >> 16) & 0xff] ^
+ Te2[(t3 >> 8) & 0xff] ^
+ Te3[(t0 ) & 0xff] ^
+ rk[1];
+ s2 =
+ Te0[(t2 >> 24) ] ^
+ Te1[(t3 >> 16) & 0xff] ^
+ Te2[(t0 >> 8) & 0xff] ^
+ Te3[(t1 ) & 0xff] ^
+ rk[2];
+ s3 =
+ Te0[(t3 >> 24) ] ^
+ Te1[(t0 >> 16) & 0xff] ^
+ Te2[(t1 >> 8) & 0xff] ^
+ Te3[(t2 ) & 0xff] ^
+ rk[3];
+ }
+#endif /* ?FULL_UNROLL */
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 =
+ (Te4[(t0 >> 24) ] & 0xff000000) ^
+ (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
+ (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
+ (Te4[(t3 ) & 0xff] & 0x000000ff) ^
+ rk[0];
+ PUTU32(ct , s0);
+ s1 =
+ (Te4[(t1 >> 24) ] & 0xff000000) ^
+ (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
+ (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
+ (Te4[(t0 ) & 0xff] & 0x000000ff) ^
+ rk[1];
+ PUTU32(ct + 4, s1);
+ s2 =
+ (Te4[(t2 >> 24) ] & 0xff000000) ^
+ (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
+ (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
+ (Te4[(t1 ) & 0xff] & 0x000000ff) ^
+ rk[2];
+ PUTU32(ct + 8, s2);
+ s3 =
+ (Te4[(t3 >> 24) ] & 0xff000000) ^
+ (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
+ (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
+ (Te4[(t2 ) & 0xff] & 0x000000ff) ^
+ rk[3];
+ PUTU32(ct + 12, s3);
+}
+
+static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) {
+ u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+ int r;
+#endif /* ?FULL_UNROLL */
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ s0 = GETU32(ct ) ^ rk[0];
+ s1 = GETU32(ct + 4) ^ rk[1];
+ s2 = GETU32(ct + 8) ^ rk[2];
+ s3 = GETU32(ct + 12) ^ rk[3];
+#ifdef FULL_UNROLL
+ /* round 1: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
+ /* round 2: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
+ /* round 3: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
+ /* round 4: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
+ /* round 5: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
+ /* round 6: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
+ /* round 7: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
+ /* round 8: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
+ /* round 9: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
+ if (Nr > 10) {
+ /* round 10: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];
+ /* round 11: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];
+ if (Nr > 12) {
+ /* round 12: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];
+ /* round 13: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
+ }
+ }
+ rk += Nr << 2;
+#else /* !FULL_UNROLL */
+ /*
+ * Nr - 1 full rounds:
+ */
+ r = Nr >> 1;
+ for (;;) {
+ t0 =
+ Td0[(s0 >> 24) ] ^
+ Td1[(s3 >> 16) & 0xff] ^
+ Td2[(s2 >> 8) & 0xff] ^
+ Td3[(s1 ) & 0xff] ^
+ rk[4];
+ t1 =
+ Td0[(s1 >> 24) ] ^
+ Td1[(s0 >> 16) & 0xff] ^
+ Td2[(s3 >> 8) & 0xff] ^
+ Td3[(s2 ) & 0xff] ^
+ rk[5];
+ t2 =
+ Td0[(s2 >> 24) ] ^
+ Td1[(s1 >> 16) & 0xff] ^
+ Td2[(s0 >> 8) & 0xff] ^
+ Td3[(s3 ) & 0xff] ^
+ rk[6];
+ t3 =
+ Td0[(s3 >> 24) ] ^
+ Td1[(s2 >> 16) & 0xff] ^
+ Td2[(s1 >> 8) & 0xff] ^
+ Td3[(s0 ) & 0xff] ^
+ rk[7];
+
+ rk += 8;
+ if (--r == 0) {
+ break;
+ }
+
+ s0 =
+ Td0[(t0 >> 24) ] ^
+ Td1[(t3 >> 16) & 0xff] ^
+ Td2[(t2 >> 8) & 0xff] ^
+ Td3[(t1 ) & 0xff] ^
+ rk[0];
+ s1 =
+ Td0[(t1 >> 24) ] ^
+ Td1[(t0 >> 16) & 0xff] ^
+ Td2[(t3 >> 8) & 0xff] ^
+ Td3[(t2 ) & 0xff] ^
+ rk[1];
+ s2 =
+ Td0[(t2 >> 24) ] ^
+ Td1[(t1 >> 16) & 0xff] ^
+ Td2[(t0 >> 8) & 0xff] ^
+ Td3[(t3 ) & 0xff] ^
+ rk[2];
+ s3 =
+ Td0[(t3 >> 24) ] ^
+ Td1[(t2 >> 16) & 0xff] ^
+ Td2[(t1 >> 8) & 0xff] ^
+ Td3[(t0 ) & 0xff] ^
+ rk[3];
+ }
+#endif /* ?FULL_UNROLL */
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 =
+ (Td4[(t0 >> 24) ] & 0xff000000) ^
+ (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
+ (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
+ (Td4[(t1 ) & 0xff] & 0x000000ff) ^
+ rk[0];
+ PUTU32(pt , s0);
+ s1 =
+ (Td4[(t1 >> 24) ] & 0xff000000) ^
+ (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
+ (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
+ (Td4[(t2 ) & 0xff] & 0x000000ff) ^
+ rk[1];
+ PUTU32(pt + 4, s1);
+ s2 =
+ (Td4[(t2 >> 24) ] & 0xff000000) ^
+ (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
+ (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
+ (Td4[(t3 ) & 0xff] & 0x000000ff) ^
+ rk[2];
+ PUTU32(pt + 8, s2);
+ s3 =
+ (Td4[(t3 >> 24) ] & 0xff000000) ^
+ (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
+ (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
+ (Td4[(t0 ) & 0xff] & 0x000000ff) ^
+ rk[3];
+ PUTU32(pt + 12, s3);
+}
+
+void
+rijndael_set_key(rijndael_ctx *ctx, u_char *key, int bits, int encrypt)
+{
+ ctx->Nr = rijndaelKeySetupEnc(ctx->ek, key, bits);
+ if (encrypt) {
+ ctx->decrypt = 0;
+ memset(ctx->dk, 0, sizeof(ctx->dk));
+ } else {
+ ctx->decrypt = 1;
+ memcpy(ctx->dk, ctx->ek, sizeof(ctx->dk));
+ rijndaelKeySetupDec(ctx->dk, key, bits, ctx->Nr);
+ }
+}
+
+void
+rijndael_decrypt(rijndael_ctx *ctx, u_char *src, u_char *dst)
+{
+ rijndaelDecrypt(ctx->dk, ctx->Nr, src, dst);
+}
+
+void
+rijndael_encrypt(rijndael_ctx *ctx, u_char *src, u_char *dst)
+{
+ rijndaelEncrypt(ctx->ek, ctx->Nr, src, dst);
+}
diff --git a/sys/opencrypto/rijndael.h b/sys/opencrypto/rijndael.h
new file mode 100644
index 0000000..5c530e1
--- /dev/null
+++ b/sys/opencrypto/rijndael.h
@@ -0,0 +1,52 @@
+/* $FreeBSD$ */
+/* $OpenBSD: rijndael.h,v 1.7 2001/12/19 17:42:24 markus Exp $ */
+
+/**
+ * rijndael-alg-fst.h
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __RIJNDAEL_H
+#define __RIJNDAEL_H
+
+#define MAXKC (256/32)
+#define MAXKB (256/8)
+#define MAXNR 14
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+
+/* The structure for key information */
+typedef struct {
+ int decrypt;
+ int Nr; /* key-length-dependent number of rounds */
+ u32 ek[4*(MAXNR + 1)]; /* encrypt key schedule */
+ u32 dk[4*(MAXNR + 1)]; /* decrypt key schedule */
+} rijndael_ctx;
+
+void rijndael_set_key(rijndael_ctx *, u_char *, int, int);
+void rijndael_decrypt(rijndael_ctx *, u_char *, u_char *);
+void rijndael_encrypt(rijndael_ctx *, u_char *, u_char *);
+
+#endif /* __RIJNDAEL_H */
diff --git a/sys/opencrypto/rmd160.c b/sys/opencrypto/rmd160.c
new file mode 100644
index 0000000..39268e2
--- /dev/null
+++ b/sys/opencrypto/rmd160.c
@@ -0,0 +1,363 @@
+/* $FreeBSD$ */
+/* $OpenBSD: rmd160.c,v 1.3 2001/09/26 21:40:13 markus Exp $ */
+/*
+ * Copyright (c) 2001 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Preneel, Bosselaers, Dobbertin, "The Cryptographic Hash Function RIPEMD-160",
+ * RSA Laboratories, CryptoBytes, Volume 3, Number 2, Autumn 1997,
+ * ftp://ftp.rsasecurity.com/pub/cryptobytes/crypto3n2.pdf
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/endian.h>
+#include <opencrypto/rmd160.h>
+
+#define PUT_64BIT_LE(cp, value) do { \
+ (cp)[7] = (value) >> 56; \
+ (cp)[6] = (value) >> 48; \
+ (cp)[5] = (value) >> 40; \
+ (cp)[4] = (value) >> 32; \
+ (cp)[3] = (value) >> 24; \
+ (cp)[2] = (value) >> 16; \
+ (cp)[1] = (value) >> 8; \
+ (cp)[0] = (value); } while (0)
+
+#define PUT_32BIT_LE(cp, value) do { \
+ (cp)[3] = (value) >> 24; \
+ (cp)[2] = (value) >> 16; \
+ (cp)[1] = (value) >> 8; \
+ (cp)[0] = (value); } while (0)
+
+#define H0 0x67452301U
+#define H1 0xEFCDAB89U
+#define H2 0x98BADCFEU
+#define H3 0x10325476U
+#define H4 0xC3D2E1F0U
+
+#define K0 0x00000000U
+#define K1 0x5A827999U
+#define K2 0x6ED9EBA1U
+#define K3 0x8F1BBCDCU
+#define K4 0xA953FD4EU
+
+#define KK0 0x50A28BE6U
+#define KK1 0x5C4DD124U
+#define KK2 0x6D703EF3U
+#define KK3 0x7A6D76E9U
+#define KK4 0x00000000U
+
+/* rotate x left n bits. */
+#define ROL(n, x) (((x) << (n)) | ((x) >> (32-(n))))
+
+#define F0(x, y, z) ((x) ^ (y) ^ (z))
+#define F1(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define F2(x, y, z) (((x) | (~y)) ^ (z))
+#define F3(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define F4(x, y, z) ((x) ^ ((y) | (~z)))
+
+#define R(a, b, c, d, e, Fj, Kj, sj, rj) \
+ do { \
+ a = ROL(sj, a + Fj(b,c,d) + X(rj) + Kj) + e; \
+ c = ROL(10, c); \
+ } while(0)
+
+#define X(i) x[i]
+
+static u_char PADDING[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+void
+RMD160Init(RMD160_CTX *ctx)
+{
+ ctx->count = 0;
+ ctx->state[0] = H0;
+ ctx->state[1] = H1;
+ ctx->state[2] = H2;
+ ctx->state[3] = H3;
+ ctx->state[4] = H4;
+}
+
+void
+RMD160Update(RMD160_CTX *ctx, const u_char *input, u_int32_t len)
+{
+ u_int32_t have, off, need;
+
+ have = (ctx->count/8) % 64;
+ need = 64 - have;
+ ctx->count += 8 * len;
+ off = 0;
+
+ if (len >= need) {
+ if (have) {
+ memcpy(ctx->buffer + have, input, need);
+ RMD160Transform(ctx->state, ctx->buffer);
+ off = need;
+ have = 0;
+ }
+ /* now the buffer is empty */
+ while (off + 64 <= len) {
+ RMD160Transform(ctx->state, input+off);
+ off += 64;
+ }
+ }
+ if (off < len)
+ memcpy(ctx->buffer + have, input+off, len-off);
+}
+
+void
+RMD160Final(u_char digest[20], RMD160_CTX *ctx)
+{
+ int i;
+ u_char size[8];
+ u_int32_t padlen;
+
+ PUT_64BIT_LE(size, ctx->count);
+
+ /*
+ * pad to 64 byte blocks, at least one byte from PADDING plus 8 bytes
+ * for the size
+ */
+ padlen = 64 - ((ctx->count/8) % 64);
+ if (padlen < 1 + 8)
+ padlen += 64;
+ RMD160Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */
+ RMD160Update(ctx, size, 8);
+
+ if (digest != NULL)
+ for (i = 0; i < 5; i++)
+ PUT_32BIT_LE(digest + i*4, ctx->state[i]);
+
+ memset(ctx, 0, sizeof (*ctx));
+}
+
+void
+RMD160Transform(u_int32_t state[5], const u_char block[64])
+{
+ u_int32_t a, b, c, d, e, aa, bb, cc, dd, ee, t, x[16];
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ memcpy(x, block, 64);
+#else
+ int i;
+
+ for (i = 0; i < 16; i++)
+ x[i] = bswap32(*(const u_int32_t*)(block+i*4));
+#endif
+
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+
+ /* Round 1 */
+ R(a, b, c, d, e, F0, K0, 11, 0);
+ R(e, a, b, c, d, F0, K0, 14, 1);
+ R(d, e, a, b, c, F0, K0, 15, 2);
+ R(c, d, e, a, b, F0, K0, 12, 3);
+ R(b, c, d, e, a, F0, K0, 5, 4);
+ R(a, b, c, d, e, F0, K0, 8, 5);
+ R(e, a, b, c, d, F0, K0, 7, 6);
+ R(d, e, a, b, c, F0, K0, 9, 7);
+ R(c, d, e, a, b, F0, K0, 11, 8);
+ R(b, c, d, e, a, F0, K0, 13, 9);
+ R(a, b, c, d, e, F0, K0, 14, 10);
+ R(e, a, b, c, d, F0, K0, 15, 11);
+ R(d, e, a, b, c, F0, K0, 6, 12);
+ R(c, d, e, a, b, F0, K0, 7, 13);
+ R(b, c, d, e, a, F0, K0, 9, 14);
+ R(a, b, c, d, e, F0, K0, 8, 15); /* #15 */
+ /* Round 2 */
+ R(e, a, b, c, d, F1, K1, 7, 7);
+ R(d, e, a, b, c, F1, K1, 6, 4);
+ R(c, d, e, a, b, F1, K1, 8, 13);
+ R(b, c, d, e, a, F1, K1, 13, 1);
+ R(a, b, c, d, e, F1, K1, 11, 10);
+ R(e, a, b, c, d, F1, K1, 9, 6);
+ R(d, e, a, b, c, F1, K1, 7, 15);
+ R(c, d, e, a, b, F1, K1, 15, 3);
+ R(b, c, d, e, a, F1, K1, 7, 12);
+ R(a, b, c, d, e, F1, K1, 12, 0);
+ R(e, a, b, c, d, F1, K1, 15, 9);
+ R(d, e, a, b, c, F1, K1, 9, 5);
+ R(c, d, e, a, b, F1, K1, 11, 2);
+ R(b, c, d, e, a, F1, K1, 7, 14);
+ R(a, b, c, d, e, F1, K1, 13, 11);
+ R(e, a, b, c, d, F1, K1, 12, 8); /* #31 */
+ /* Round 3 */
+ R(d, e, a, b, c, F2, K2, 11, 3);
+ R(c, d, e, a, b, F2, K2, 13, 10);
+ R(b, c, d, e, a, F2, K2, 6, 14);
+ R(a, b, c, d, e, F2, K2, 7, 4);
+ R(e, a, b, c, d, F2, K2, 14, 9);
+ R(d, e, a, b, c, F2, K2, 9, 15);
+ R(c, d, e, a, b, F2, K2, 13, 8);
+ R(b, c, d, e, a, F2, K2, 15, 1);
+ R(a, b, c, d, e, F2, K2, 14, 2);
+ R(e, a, b, c, d, F2, K2, 8, 7);
+ R(d, e, a, b, c, F2, K2, 13, 0);
+ R(c, d, e, a, b, F2, K2, 6, 6);
+ R(b, c, d, e, a, F2, K2, 5, 13);
+ R(a, b, c, d, e, F2, K2, 12, 11);
+ R(e, a, b, c, d, F2, K2, 7, 5);
+ R(d, e, a, b, c, F2, K2, 5, 12); /* #47 */
+ /* Round 4 */
+ R(c, d, e, a, b, F3, K3, 11, 1);
+ R(b, c, d, e, a, F3, K3, 12, 9);
+ R(a, b, c, d, e, F3, K3, 14, 11);
+ R(e, a, b, c, d, F3, K3, 15, 10);
+ R(d, e, a, b, c, F3, K3, 14, 0);
+ R(c, d, e, a, b, F3, K3, 15, 8);
+ R(b, c, d, e, a, F3, K3, 9, 12);
+ R(a, b, c, d, e, F3, K3, 8, 4);
+ R(e, a, b, c, d, F3, K3, 9, 13);
+ R(d, e, a, b, c, F3, K3, 14, 3);
+ R(c, d, e, a, b, F3, K3, 5, 7);
+ R(b, c, d, e, a, F3, K3, 6, 15);
+ R(a, b, c, d, e, F3, K3, 8, 14);
+ R(e, a, b, c, d, F3, K3, 6, 5);
+ R(d, e, a, b, c, F3, K3, 5, 6);
+ R(c, d, e, a, b, F3, K3, 12, 2); /* #63 */
+ /* Round 5 */
+ R(b, c, d, e, a, F4, K4, 9, 4);
+ R(a, b, c, d, e, F4, K4, 15, 0);
+ R(e, a, b, c, d, F4, K4, 5, 5);
+ R(d, e, a, b, c, F4, K4, 11, 9);
+ R(c, d, e, a, b, F4, K4, 6, 7);
+ R(b, c, d, e, a, F4, K4, 8, 12);
+ R(a, b, c, d, e, F4, K4, 13, 2);
+ R(e, a, b, c, d, F4, K4, 12, 10);
+ R(d, e, a, b, c, F4, K4, 5, 14);
+ R(c, d, e, a, b, F4, K4, 12, 1);
+ R(b, c, d, e, a, F4, K4, 13, 3);
+ R(a, b, c, d, e, F4, K4, 14, 8);
+ R(e, a, b, c, d, F4, K4, 11, 11);
+ R(d, e, a, b, c, F4, K4, 8, 6);
+ R(c, d, e, a, b, F4, K4, 5, 15);
+ R(b, c, d, e, a, F4, K4, 6, 13); /* #79 */
+
+ aa = a ; bb = b; cc = c; dd = d; ee = e;
+
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+
+ /* Parallel round 1 */
+ R(a, b, c, d, e, F4, KK0, 8, 5);
+ R(e, a, b, c, d, F4, KK0, 9, 14);
+ R(d, e, a, b, c, F4, KK0, 9, 7);
+ R(c, d, e, a, b, F4, KK0, 11, 0);
+ R(b, c, d, e, a, F4, KK0, 13, 9);
+ R(a, b, c, d, e, F4, KK0, 15, 2);
+ R(e, a, b, c, d, F4, KK0, 15, 11);
+ R(d, e, a, b, c, F4, KK0, 5, 4);
+ R(c, d, e, a, b, F4, KK0, 7, 13);
+ R(b, c, d, e, a, F4, KK0, 7, 6);
+ R(a, b, c, d, e, F4, KK0, 8, 15);
+ R(e, a, b, c, d, F4, KK0, 11, 8);
+ R(d, e, a, b, c, F4, KK0, 14, 1);
+ R(c, d, e, a, b, F4, KK0, 14, 10);
+ R(b, c, d, e, a, F4, KK0, 12, 3);
+ R(a, b, c, d, e, F4, KK0, 6, 12); /* #15 */
+ /* Parallel round 2 */
+ R(e, a, b, c, d, F3, KK1, 9, 6);
+ R(d, e, a, b, c, F3, KK1, 13, 11);
+ R(c, d, e, a, b, F3, KK1, 15, 3);
+ R(b, c, d, e, a, F3, KK1, 7, 7);
+ R(a, b, c, d, e, F3, KK1, 12, 0);
+ R(e, a, b, c, d, F3, KK1, 8, 13);
+ R(d, e, a, b, c, F3, KK1, 9, 5);
+ R(c, d, e, a, b, F3, KK1, 11, 10);
+ R(b, c, d, e, a, F3, KK1, 7, 14);
+ R(a, b, c, d, e, F3, KK1, 7, 15);
+ R(e, a, b, c, d, F3, KK1, 12, 8);
+ R(d, e, a, b, c, F3, KK1, 7, 12);
+ R(c, d, e, a, b, F3, KK1, 6, 4);
+ R(b, c, d, e, a, F3, KK1, 15, 9);
+ R(a, b, c, d, e, F3, KK1, 13, 1);
+ R(e, a, b, c, d, F3, KK1, 11, 2); /* #31 */
+ /* Parallel round 3 */
+ R(d, e, a, b, c, F2, KK2, 9, 15);
+ R(c, d, e, a, b, F2, KK2, 7, 5);
+ R(b, c, d, e, a, F2, KK2, 15, 1);
+ R(a, b, c, d, e, F2, KK2, 11, 3);
+ R(e, a, b, c, d, F2, KK2, 8, 7);
+ R(d, e, a, b, c, F2, KK2, 6, 14);
+ R(c, d, e, a, b, F2, KK2, 6, 6);
+ R(b, c, d, e, a, F2, KK2, 14, 9);
+ R(a, b, c, d, e, F2, KK2, 12, 11);
+ R(e, a, b, c, d, F2, KK2, 13, 8);
+ R(d, e, a, b, c, F2, KK2, 5, 12);
+ R(c, d, e, a, b, F2, KK2, 14, 2);
+ R(b, c, d, e, a, F2, KK2, 13, 10);
+ R(a, b, c, d, e, F2, KK2, 13, 0);
+ R(e, a, b, c, d, F2, KK2, 7, 4);
+ R(d, e, a, b, c, F2, KK2, 5, 13); /* #47 */
+ /* Parallel round 4 */
+ R(c, d, e, a, b, F1, KK3, 15, 8);
+ R(b, c, d, e, a, F1, KK3, 5, 6);
+ R(a, b, c, d, e, F1, KK3, 8, 4);
+ R(e, a, b, c, d, F1, KK3, 11, 1);
+ R(d, e, a, b, c, F1, KK3, 14, 3);
+ R(c, d, e, a, b, F1, KK3, 14, 11);
+ R(b, c, d, e, a, F1, KK3, 6, 15);
+ R(a, b, c, d, e, F1, KK3, 14, 0);
+ R(e, a, b, c, d, F1, KK3, 6, 5);
+ R(d, e, a, b, c, F1, KK3, 9, 12);
+ R(c, d, e, a, b, F1, KK3, 12, 2);
+ R(b, c, d, e, a, F1, KK3, 9, 13);
+ R(a, b, c, d, e, F1, KK3, 12, 9);
+ R(e, a, b, c, d, F1, KK3, 5, 7);
+ R(d, e, a, b, c, F1, KK3, 15, 10);
+ R(c, d, e, a, b, F1, KK3, 8, 14); /* #63 */
+ /* Parallel round 5 */
+ R(b, c, d, e, a, F0, KK4, 8, 12);
+ R(a, b, c, d, e, F0, KK4, 5, 15);
+ R(e, a, b, c, d, F0, KK4, 12, 10);
+ R(d, e, a, b, c, F0, KK4, 9, 4);
+ R(c, d, e, a, b, F0, KK4, 12, 1);
+ R(b, c, d, e, a, F0, KK4, 5, 5);
+ R(a, b, c, d, e, F0, KK4, 14, 8);
+ R(e, a, b, c, d, F0, KK4, 6, 7);
+ R(d, e, a, b, c, F0, KK4, 8, 6);
+ R(c, d, e, a, b, F0, KK4, 13, 2);
+ R(b, c, d, e, a, F0, KK4, 6, 13);
+ R(a, b, c, d, e, F0, KK4, 5, 14);
+ R(e, a, b, c, d, F0, KK4, 15, 0);
+ R(d, e, a, b, c, F0, KK4, 13, 3);
+ R(c, d, e, a, b, F0, KK4, 11, 9);
+ R(b, c, d, e, a, F0, KK4, 11, 11); /* #79 */
+
+ t = state[1] + cc + d;
+ state[1] = state[2] + dd + e;
+ state[2] = state[3] + ee + a;
+ state[3] = state[4] + aa + b;
+ state[4] = state[0] + bb + c;
+ state[0] = t;
+}
diff --git a/sys/opencrypto/rmd160.h b/sys/opencrypto/rmd160.h
new file mode 100644
index 0000000..604b0c9
--- /dev/null
+++ b/sys/opencrypto/rmd160.h
@@ -0,0 +1,41 @@
+/* $FreeBSD$ */
+/* $OpenBSD: rmd160.h,v 1.3 2002/03/14 01:26:51 millert Exp $ */
+/*
+ * Copyright (c) 2001 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _RMD160_H
+#define _RMD160_H
+
+/* RMD160 context. */
+typedef struct RMD160Context {
+ u_int32_t state[5]; /* state */
+ u_int64_t count; /* number of bits, modulo 2^64 */
+ u_char buffer[64]; /* input buffer */
+} RMD160_CTX;
+
+void RMD160Init(RMD160_CTX *);
+void RMD160Transform(u_int32_t [5], const u_char [64]);
+void RMD160Update(RMD160_CTX *, const u_char *, u_int32_t);
+void RMD160Final(u_char [20], RMD160_CTX *);
+
+#endif /* _RMD160_H */
diff --git a/sys/opencrypto/skipjack.c b/sys/opencrypto/skipjack.c
new file mode 100644
index 0000000..8ba0a42
--- /dev/null
+++ b/sys/opencrypto/skipjack.c
@@ -0,0 +1,258 @@
+/* $FreeBSD$ */
+/* $OpenBSD: skipjack.c,v 1.3 2001/05/05 00:31:34 angelos Exp $ */
+
+/*
+ * Further optimized test implementation of SKIPJACK algorithm
+ * Mark Tillotson <markt@chaos.org.uk>, 25 June 98
+ * Optimizations suit RISC (lots of registers) machine best.
+ *
+ * based on unoptimized implementation of
+ * Panu Rissanen <bande@lut.fi> 960624
+ *
+ * SKIPJACK and KEA Algorithm Specifications
+ * Version 2.0
+ * 29 May 1998
+*/
+
+#include <sys/param.h>
+
+#include <opencrypto/skipjack.h>
+
+static const u_int8_t ftable[0x100] =
+{
+ 0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4,
+ 0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9,
+ 0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e,
+ 0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28,
+ 0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68,
+ 0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53,
+ 0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19,
+ 0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2,
+ 0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b,
+ 0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8,
+ 0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0,
+ 0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90,
+ 0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69,
+ 0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76,
+ 0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20,
+ 0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d,
+ 0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43,
+ 0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18,
+ 0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa,
+ 0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4,
+ 0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87,
+ 0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40,
+ 0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b,
+ 0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5,
+ 0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0,
+ 0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2,
+ 0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1,
+ 0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8,
+ 0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5,
+ 0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac,
+ 0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3,
+ 0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46
+};
+
+/*
+ * For each key byte generate a table to represent the function
+ * ftable [in ^ keybyte]
+ *
+ * These tables used to save an XOR in each stage of the G-function
+ * the tables are hopefully pointed to by register allocated variables
+ * k0, k1..k9
+ */
+void
+subkey_table_gen (u_int8_t *key, u_int8_t **key_tables)
+{
+ int i, k;
+
+ for (k = 0; k < 10; k++) {
+ u_int8_t key_byte = key [k];
+ u_int8_t * table = key_tables[k];
+ for (i = 0; i < 0x100; i++)
+ table [i] = ftable [i ^ key_byte];
+ }
+}
+
+
+#define g(k0, k1, k2, k3, ih, il, oh, ol) \
+{ \
+ oh = k##k0 [il] ^ ih; \
+ ol = k##k1 [oh] ^ il; \
+ oh = k##k2 [ol] ^ oh; \
+ ol = k##k3 [oh] ^ ol; \
+}
+
+#define g0(ih, il, oh, ol) g(0, 1, 2, 3, ih, il, oh, ol)
+#define g4(ih, il, oh, ol) g(4, 5, 6, 7, ih, il, oh, ol)
+#define g8(ih, il, oh, ol) g(8, 9, 0, 1, ih, il, oh, ol)
+#define g2(ih, il, oh, ol) g(2, 3, 4, 5, ih, il, oh, ol)
+#define g6(ih, il, oh, ol) g(6, 7, 8, 9, ih, il, oh, ol)
+
+
+#define g_inv(k0, k1, k2, k3, ih, il, oh, ol) \
+{ \
+ ol = k##k3 [ih] ^ il; \
+ oh = k##k2 [ol] ^ ih; \
+ ol = k##k1 [oh] ^ ol; \
+ oh = k##k0 [ol] ^ oh; \
+}
+
+
+#define g0_inv(ih, il, oh, ol) g_inv(0, 1, 2, 3, ih, il, oh, ol)
+#define g4_inv(ih, il, oh, ol) g_inv(4, 5, 6, 7, ih, il, oh, ol)
+#define g8_inv(ih, il, oh, ol) g_inv(8, 9, 0, 1, ih, il, oh, ol)
+#define g2_inv(ih, il, oh, ol) g_inv(2, 3, 4, 5, ih, il, oh, ol)
+#define g6_inv(ih, il, oh, ol) g_inv(6, 7, 8, 9, ih, il, oh, ol)
+
+/* optimized version of Skipjack algorithm
+ *
+ * the appropriate g-function is inlined for each round
+ *
+ * the data movement is minimized by rotating the names of the
+ * variables w1..w4, not their contents (saves 3 moves per round)
+ *
+ * the loops are completely unrolled (needed to staticize choice of g)
+ *
+ * compiles to about 470 instructions on a Sparc (gcc -O)
+ * which is about 58 instructions per byte, 14 per round.
+ * gcc seems to leave in some unnecessary and with 0xFF operations
+ * but only in the latter part of the functions. Perhaps it
+ * runs out of resources to properly optimize long inlined function?
+ * in theory should get about 11 instructions per round, not 14
+ */
+
+void
+skipjack_forwards(u_int8_t *plain, u_int8_t *cipher, u_int8_t **key_tables)
+{
+ u_int8_t wh1 = plain[0]; u_int8_t wl1 = plain[1];
+ u_int8_t wh2 = plain[2]; u_int8_t wl2 = plain[3];
+ u_int8_t wh3 = plain[4]; u_int8_t wl3 = plain[5];
+ u_int8_t wh4 = plain[6]; u_int8_t wl4 = plain[7];
+
+ u_int8_t * k0 = key_tables [0];
+ u_int8_t * k1 = key_tables [1];
+ u_int8_t * k2 = key_tables [2];
+ u_int8_t * k3 = key_tables [3];
+ u_int8_t * k4 = key_tables [4];
+ u_int8_t * k5 = key_tables [5];
+ u_int8_t * k6 = key_tables [6];
+ u_int8_t * k7 = key_tables [7];
+ u_int8_t * k8 = key_tables [8];
+ u_int8_t * k9 = key_tables [9];
+
+ /* first 8 rounds */
+ g0 (wh1,wl1, wh1,wl1); wl4 ^= wl1 ^ 1; wh4 ^= wh1;
+ g4 (wh4,wl4, wh4,wl4); wl3 ^= wl4 ^ 2; wh3 ^= wh4;
+ g8 (wh3,wl3, wh3,wl3); wl2 ^= wl3 ^ 3; wh2 ^= wh3;
+ g2 (wh2,wl2, wh2,wl2); wl1 ^= wl2 ^ 4; wh1 ^= wh2;
+ g6 (wh1,wl1, wh1,wl1); wl4 ^= wl1 ^ 5; wh4 ^= wh1;
+ g0 (wh4,wl4, wh4,wl4); wl3 ^= wl4 ^ 6; wh3 ^= wh4;
+ g4 (wh3,wl3, wh3,wl3); wl2 ^= wl3 ^ 7; wh2 ^= wh3;
+ g8 (wh2,wl2, wh2,wl2); wl1 ^= wl2 ^ 8; wh1 ^= wh2;
+
+ /* second 8 rounds */
+ wh2 ^= wh1; wl2 ^= wl1 ^ 9 ; g2 (wh1,wl1, wh1,wl1);
+ wh1 ^= wh4; wl1 ^= wl4 ^ 10; g6 (wh4,wl4, wh4,wl4);
+ wh4 ^= wh3; wl4 ^= wl3 ^ 11; g0 (wh3,wl3, wh3,wl3);
+ wh3 ^= wh2; wl3 ^= wl2 ^ 12; g4 (wh2,wl2, wh2,wl2);
+ wh2 ^= wh1; wl2 ^= wl1 ^ 13; g8 (wh1,wl1, wh1,wl1);
+ wh1 ^= wh4; wl1 ^= wl4 ^ 14; g2 (wh4,wl4, wh4,wl4);
+ wh4 ^= wh3; wl4 ^= wl3 ^ 15; g6 (wh3,wl3, wh3,wl3);
+ wh3 ^= wh2; wl3 ^= wl2 ^ 16; g0 (wh2,wl2, wh2,wl2);
+
+ /* third 8 rounds */
+ g4 (wh1,wl1, wh1,wl1); wl4 ^= wl1 ^ 17; wh4 ^= wh1;
+ g8 (wh4,wl4, wh4,wl4); wl3 ^= wl4 ^ 18; wh3 ^= wh4;
+ g2 (wh3,wl3, wh3,wl3); wl2 ^= wl3 ^ 19; wh2 ^= wh3;
+ g6 (wh2,wl2, wh2,wl2); wl1 ^= wl2 ^ 20; wh1 ^= wh2;
+ g0 (wh1,wl1, wh1,wl1); wl4 ^= wl1 ^ 21; wh4 ^= wh1;
+ g4 (wh4,wl4, wh4,wl4); wl3 ^= wl4 ^ 22; wh3 ^= wh4;
+ g8 (wh3,wl3, wh3,wl3); wl2 ^= wl3 ^ 23; wh2 ^= wh3;
+ g2 (wh2,wl2, wh2,wl2); wl1 ^= wl2 ^ 24; wh1 ^= wh2;
+
+ /* last 8 rounds */
+ wh2 ^= wh1; wl2 ^= wl1 ^ 25; g6 (wh1,wl1, wh1,wl1);
+ wh1 ^= wh4; wl1 ^= wl4 ^ 26; g0 (wh4,wl4, wh4,wl4);
+ wh4 ^= wh3; wl4 ^= wl3 ^ 27; g4 (wh3,wl3, wh3,wl3);
+ wh3 ^= wh2; wl3 ^= wl2 ^ 28; g8 (wh2,wl2, wh2,wl2);
+ wh2 ^= wh1; wl2 ^= wl1 ^ 29; g2 (wh1,wl1, wh1,wl1);
+ wh1 ^= wh4; wl1 ^= wl4 ^ 30; g6 (wh4,wl4, wh4,wl4);
+ wh4 ^= wh3; wl4 ^= wl3 ^ 31; g0 (wh3,wl3, wh3,wl3);
+ wh3 ^= wh2; wl3 ^= wl2 ^ 32; g4 (wh2,wl2, wh2,wl2);
+
+ /* pack into byte vector */
+ cipher [0] = wh1; cipher [1] = wl1;
+ cipher [2] = wh2; cipher [3] = wl2;
+ cipher [4] = wh3; cipher [5] = wl3;
+ cipher [6] = wh4; cipher [7] = wl4;
+}
+
+
+void
+skipjack_backwards (u_int8_t *cipher, u_int8_t *plain, u_int8_t **key_tables)
+{
+ /* setup 4 16-bit portions */
+ u_int8_t wh1 = cipher[0]; u_int8_t wl1 = cipher[1];
+ u_int8_t wh2 = cipher[2]; u_int8_t wl2 = cipher[3];
+ u_int8_t wh3 = cipher[4]; u_int8_t wl3 = cipher[5];
+ u_int8_t wh4 = cipher[6]; u_int8_t wl4 = cipher[7];
+
+ u_int8_t * k0 = key_tables [0];
+ u_int8_t * k1 = key_tables [1];
+ u_int8_t * k2 = key_tables [2];
+ u_int8_t * k3 = key_tables [3];
+ u_int8_t * k4 = key_tables [4];
+ u_int8_t * k5 = key_tables [5];
+ u_int8_t * k6 = key_tables [6];
+ u_int8_t * k7 = key_tables [7];
+ u_int8_t * k8 = key_tables [8];
+ u_int8_t * k9 = key_tables [9];
+
+ /* first 8 rounds */
+ g4_inv (wh2,wl2, wh2,wl2); wl3 ^= wl2 ^ 32; wh3 ^= wh2;
+ g0_inv (wh3,wl3, wh3,wl3); wl4 ^= wl3 ^ 31; wh4 ^= wh3;
+ g6_inv (wh4,wl4, wh4,wl4); wl1 ^= wl4 ^ 30; wh1 ^= wh4;
+ g2_inv (wh1,wl1, wh1,wl1); wl2 ^= wl1 ^ 29; wh2 ^= wh1;
+ g8_inv (wh2,wl2, wh2,wl2); wl3 ^= wl2 ^ 28; wh3 ^= wh2;
+ g4_inv (wh3,wl3, wh3,wl3); wl4 ^= wl3 ^ 27; wh4 ^= wh3;
+ g0_inv (wh4,wl4, wh4,wl4); wl1 ^= wl4 ^ 26; wh1 ^= wh4;
+ g6_inv (wh1,wl1, wh1,wl1); wl2 ^= wl1 ^ 25; wh2 ^= wh1;
+
+ /* second 8 rounds */
+ wh1 ^= wh2; wl1 ^= wl2 ^ 24; g2_inv (wh2,wl2, wh2,wl2);
+ wh2 ^= wh3; wl2 ^= wl3 ^ 23; g8_inv (wh3,wl3, wh3,wl3);
+ wh3 ^= wh4; wl3 ^= wl4 ^ 22; g4_inv (wh4,wl4, wh4,wl4);
+ wh4 ^= wh1; wl4 ^= wl1 ^ 21; g0_inv (wh1,wl1, wh1,wl1);
+ wh1 ^= wh2; wl1 ^= wl2 ^ 20; g6_inv (wh2,wl2, wh2,wl2);
+ wh2 ^= wh3; wl2 ^= wl3 ^ 19; g2_inv (wh3,wl3, wh3,wl3);
+ wh3 ^= wh4; wl3 ^= wl4 ^ 18; g8_inv (wh4,wl4, wh4,wl4);
+ wh4 ^= wh1; wl4 ^= wl1 ^ 17; g4_inv (wh1,wl1, wh1,wl1);
+
+ /* third 8 rounds */
+ g0_inv (wh2,wl2, wh2,wl2); wl3 ^= wl2 ^ 16; wh3 ^= wh2;
+ g6_inv (wh3,wl3, wh3,wl3); wl4 ^= wl3 ^ 15; wh4 ^= wh3;
+ g2_inv (wh4,wl4, wh4,wl4); wl1 ^= wl4 ^ 14; wh1 ^= wh4;
+ g8_inv (wh1,wl1, wh1,wl1); wl2 ^= wl1 ^ 13; wh2 ^= wh1;
+ g4_inv (wh2,wl2, wh2,wl2); wl3 ^= wl2 ^ 12; wh3 ^= wh2;
+ g0_inv (wh3,wl3, wh3,wl3); wl4 ^= wl3 ^ 11; wh4 ^= wh3;
+ g6_inv (wh4,wl4, wh4,wl4); wl1 ^= wl4 ^ 10; wh1 ^= wh4;
+ g2_inv (wh1,wl1, wh1,wl1); wl2 ^= wl1 ^ 9; wh2 ^= wh1;
+
+ /* last 8 rounds */
+ wh1 ^= wh2; wl1 ^= wl2 ^ 8; g8_inv (wh2,wl2, wh2,wl2);
+ wh2 ^= wh3; wl2 ^= wl3 ^ 7; g4_inv (wh3,wl3, wh3,wl3);
+ wh3 ^= wh4; wl3 ^= wl4 ^ 6; g0_inv (wh4,wl4, wh4,wl4);
+ wh4 ^= wh1; wl4 ^= wl1 ^ 5; g6_inv (wh1,wl1, wh1,wl1);
+ wh1 ^= wh2; wl1 ^= wl2 ^ 4; g2_inv (wh2,wl2, wh2,wl2);
+ wh2 ^= wh3; wl2 ^= wl3 ^ 3; g8_inv (wh3,wl3, wh3,wl3);
+ wh3 ^= wh4; wl3 ^= wl4 ^ 2; g4_inv (wh4,wl4, wh4,wl4);
+ wh4 ^= wh1; wl4 ^= wl1 ^ 1; g0_inv (wh1,wl1, wh1,wl1);
+
+ /* pack into byte vector */
+ plain [0] = wh1; plain [1] = wl1;
+ plain [2] = wh2; plain [3] = wl2;
+ plain [4] = wh3; plain [5] = wl3;
+ plain [6] = wh4; plain [7] = wl4;
+}
diff --git a/sys/opencrypto/skipjack.h b/sys/opencrypto/skipjack.h
new file mode 100644
index 0000000..70df788
--- /dev/null
+++ b/sys/opencrypto/skipjack.h
@@ -0,0 +1,19 @@
+/* $FreeBSD$ */
+/* $OpenBSD: skipjack.h,v 1.3 2002/03/14 01:26:51 millert Exp $ */
+
+/*
+ * Further optimized test implementation of SKIPJACK algorithm
+ * Mark Tillotson <markt@chaos.org.uk>, 25 June 98
+ * Optimizations suit RISC (lots of registers) machine best.
+ *
+ * based on unoptimized implementation of
+ * Panu Rissanen <bande@lut.fi> 960624
+ *
+ * SKIPJACK and KEA Algorithm Specifications
+ * Version 2.0
+ * 29 May 1998
+*/
+
+extern void skipjack_forwards(u_int8_t *plain, u_int8_t *cipher, u_int8_t **key);
+extern void skipjack_backwards(u_int8_t *cipher, u_int8_t *plain, u_int8_t **key);
+extern void subkey_table_gen(u_int8_t *key, u_int8_t **key_tables);
diff --git a/sys/opencrypto/xform.c b/sys/opencrypto/xform.c
new file mode 100644
index 0000000..f3bac85
--- /dev/null
+++ b/sys/opencrypto/xform.c
@@ -0,0 +1,629 @@
+/* $FreeBSD$ */
+/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
+/*
+ * The authors of this code are John Ioannidis (ji@tla.org),
+ * Angelos D. Keromytis (kermit@csd.uch.gr) and
+ * Niels Provos (provos@physnet.uni-hamburg.de).
+ *
+ * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
+ * in November 1995.
+ *
+ * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
+ * by Angelos D. Keromytis.
+ *
+ * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
+ * and Niels Provos.
+ *
+ * Additional features in 1999 by Angelos D. Keromytis.
+ *
+ * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
+ * Angelos D. Keromytis and Niels Provos.
+ *
+ * Copyright (C) 2001, Angelos D. Keromytis.
+ *
+ * Permission to use, copy, and modify this software with or without fee
+ * is hereby granted, provided that this entire notice is included in
+ * all copies of any software which is or includes a copy or
+ * modification of this software.
+ * You may use this code under the GNU public license if you so wish. Please
+ * contribute changes back to the authors under this freer than GPL license
+ * so that we may further the use of strong encryption without limitations to
+ * all.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+ * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/sysctl.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <machine/cpu.h>
+
+#include <crypto/blowfish/blowfish.h>
+#include <crypto/des/des.h>
+#include <crypto/sha1.h>
+
+#include <opencrypto/cast.h>
+#include <opencrypto/deflate.h>
+#include <opencrypto/rijndael.h>
+#include <opencrypto/rmd160.h>
+#include <opencrypto/skipjack.h>
+
+#include <sys/md5.h>
+
+#include <opencrypto/cryptodev.h>
+#include <opencrypto/xform.h>
+
+static void null_encrypt(caddr_t, u_int8_t *);
+static void null_decrypt(caddr_t, u_int8_t *);
+static int null_setkey(u_int8_t **, u_int8_t *, int);
+static void null_zerokey(u_int8_t **);
+
+static int des1_setkey(u_int8_t **, u_int8_t *, int);
+static int des3_setkey(u_int8_t **, u_int8_t *, int);
+static int blf_setkey(u_int8_t **, u_int8_t *, int);
+static int cast5_setkey(u_int8_t **, u_int8_t *, int);
+static int skipjack_setkey(u_int8_t **, u_int8_t *, int);
+static int rijndael128_setkey(u_int8_t **, u_int8_t *, int);
+static void des1_encrypt(caddr_t, u_int8_t *);
+static void des3_encrypt(caddr_t, u_int8_t *);
+static void blf_encrypt(caddr_t, u_int8_t *);
+static void cast5_encrypt(caddr_t, u_int8_t *);
+static void skipjack_encrypt(caddr_t, u_int8_t *);
+static void rijndael128_encrypt(caddr_t, u_int8_t *);
+static void des1_decrypt(caddr_t, u_int8_t *);
+static void des3_decrypt(caddr_t, u_int8_t *);
+static void blf_decrypt(caddr_t, u_int8_t *);
+static void cast5_decrypt(caddr_t, u_int8_t *);
+static void skipjack_decrypt(caddr_t, u_int8_t *);
+static void rijndael128_decrypt(caddr_t, u_int8_t *);
+static void des1_zerokey(u_int8_t **);
+static void des3_zerokey(u_int8_t **);
+static void blf_zerokey(u_int8_t **);
+static void cast5_zerokey(u_int8_t **);
+static void skipjack_zerokey(u_int8_t **);
+static void rijndael128_zerokey(u_int8_t **);
+
+static void null_init(void *);
+static int null_update(void *, u_int8_t *, u_int16_t);
+static void null_final(u_int8_t *, void *);
+static int MD5Update_int(void *, u_int8_t *, u_int16_t);
+static void SHA1Init_int(void *);
+static int SHA1Update_int(void *, u_int8_t *, u_int16_t);
+static void SHA1Final_int(u_int8_t *, void *);
+static int RMD160Update_int(void *, u_int8_t *, u_int16_t);
+static int SHA256Update_int(void *, u_int8_t *, u_int16_t);
+static int SHA384Update_int(void *, u_int8_t *, u_int16_t);
+static int SHA512Update_int(void *, u_int8_t *, u_int16_t);
+
+static u_int32_t deflate_compress(u_int8_t *, u_int32_t, u_int8_t **);
+static u_int32_t deflate_decompress(u_int8_t *, u_int32_t, u_int8_t **);
+
+MALLOC_DEFINE(M_XDATA, "xform", "xform data buffers");
+
+/* Encryption instances */
+struct enc_xform enc_xform_null = {
+ CRYPTO_NULL_CBC, "NULL",
+ /* NB: blocksize of 4 is to generate a properly aligned ESP header */
+ 4, 0, 256, /* 2048 bits, max key */
+ null_encrypt,
+ null_decrypt,
+ null_setkey,
+ null_zerokey,
+};
+
+struct enc_xform enc_xform_des = {
+ CRYPTO_DES_CBC, "DES",
+ 8, 8, 8,
+ des1_encrypt,
+ des1_decrypt,
+ des1_setkey,
+ des1_zerokey,
+};
+
+struct enc_xform enc_xform_3des = {
+ CRYPTO_3DES_CBC, "3DES",
+ 8, 24, 24,
+ des3_encrypt,
+ des3_decrypt,
+ des3_setkey,
+ des3_zerokey
+};
+
+struct enc_xform enc_xform_blf = {
+ CRYPTO_BLF_CBC, "Blowfish",
+ 8, 5, 56 /* 448 bits, max key */,
+ blf_encrypt,
+ blf_decrypt,
+ blf_setkey,
+ blf_zerokey
+};
+
+struct enc_xform enc_xform_cast5 = {
+ CRYPTO_CAST_CBC, "CAST-128",
+ 8, 5, 16,
+ cast5_encrypt,
+ cast5_decrypt,
+ cast5_setkey,
+ cast5_zerokey
+};
+
+struct enc_xform enc_xform_skipjack = {
+ CRYPTO_SKIPJACK_CBC, "Skipjack",
+ 8, 10, 10,
+ skipjack_encrypt,
+ skipjack_decrypt,
+ skipjack_setkey,
+ skipjack_zerokey
+};
+
+struct enc_xform enc_xform_rijndael128 = {
+ CRYPTO_RIJNDAEL128_CBC, "Rijndael-128/AES",
+ 16, 8, 32,
+ rijndael128_encrypt,
+ rijndael128_decrypt,
+ rijndael128_setkey,
+ rijndael128_zerokey,
+};
+
+struct enc_xform enc_xform_arc4 = {
+ CRYPTO_ARC4, "ARC4",
+ 1, 1, 32,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+/* Authentication instances */
+struct auth_hash auth_hash_null = {
+ CRYPTO_NULL_HMAC, "NULL-HMAC",
+ 0, 0, 12, sizeof(int), /* NB: context isn't used */
+ null_init, null_update, null_final
+};
+
+struct auth_hash auth_hash_hmac_md5_96 = {
+ CRYPTO_MD5_HMAC, "HMAC-MD5",
+ 16, 16, 12, sizeof(MD5_CTX),
+ (void (*) (void *)) MD5Init, MD5Update_int,
+ (void (*) (u_int8_t *, void *)) MD5Final
+};
+
+struct auth_hash auth_hash_hmac_sha1_96 = {
+ CRYPTO_SHA1_HMAC, "HMAC-SHA1",
+ 20, 20, 12, sizeof(SHA1_CTX),
+ SHA1Init_int, SHA1Update_int, SHA1Final_int
+};
+
+struct auth_hash auth_hash_hmac_ripemd_160_96 = {
+ CRYPTO_RIPEMD160_HMAC, "HMAC-RIPEMD-160",
+ 20, 20, 12, sizeof(RMD160_CTX),
+ (void (*)(void *)) RMD160Init, RMD160Update_int,
+ (void (*)(u_int8_t *, void *)) RMD160Final
+};
+
+struct auth_hash auth_hash_key_md5 = {
+ CRYPTO_MD5_KPDK, "Keyed MD5",
+ 0, 16, 12, sizeof(MD5_CTX),
+ (void (*)(void *)) MD5Init, MD5Update_int,
+ (void (*)(u_int8_t *, void *)) MD5Final
+};
+
+struct auth_hash auth_hash_key_sha1 = {
+ CRYPTO_SHA1_KPDK, "Keyed SHA1",
+ 0, 20, 12, sizeof(SHA1_CTX),
+ SHA1Init_int, SHA1Update_int, SHA1Final_int
+};
+
+struct auth_hash auth_hash_hmac_sha2_256 = {
+ CRYPTO_SHA2_HMAC, "HMAC-SHA2",
+ 32, 32, 12, sizeof(SHA256_CTX),
+ (void (*)(void *)) SHA256_Init, SHA256Update_int,
+ (void (*)(u_int8_t *, void *)) SHA256_Final
+};
+
+struct auth_hash auth_hash_hmac_sha2_384 = {
+ CRYPTO_SHA2_HMAC, "HMAC-SHA2-384",
+ 48, 48, 12, sizeof(SHA384_CTX),
+ (void (*)(void *)) SHA384_Init, SHA384Update_int,
+ (void (*)(u_int8_t *, void *)) SHA384_Final
+};
+
+struct auth_hash auth_hash_hmac_sha2_512 = {
+ CRYPTO_SHA2_HMAC, "HMAC-SHA2-512",
+ 64, 64, 12, sizeof(SHA512_CTX),
+ (void (*)(void *)) SHA512_Init, SHA512Update_int,
+ (void (*)(u_int8_t *, void *)) SHA512_Final
+};
+
+/* Compression instance */
+struct comp_algo comp_algo_deflate = {
+ CRYPTO_DEFLATE_COMP, "Deflate",
+ 90, deflate_compress,
+ deflate_decompress
+};
+
+/*
+ * Encryption wrapper routines.
+ */
+static void
+null_encrypt(caddr_t key, u_int8_t *blk)
+{
+}
+static void
+null_decrypt(caddr_t key, u_int8_t *blk)
+{
+}
+static int
+null_setkey(u_int8_t **sched, u_int8_t *key, int len)
+{
+ *sched = NULL;
+ return 0;
+}
+static void
+null_zerokey(u_int8_t **sched)
+{
+ *sched = NULL;
+}
+
+static void
+des1_encrypt(caddr_t key, u_int8_t *blk)
+{
+ des_cblock *cb = (des_cblock *) blk;
+ des_key_schedule *p = (des_key_schedule *) key;
+
+ des_ecb_encrypt(cb, cb, p[0], DES_ENCRYPT);
+}
+
+static void
+des1_decrypt(caddr_t key, u_int8_t *blk)
+{
+ des_cblock *cb = (des_cblock *) blk;
+ des_key_schedule *p = (des_key_schedule *) key;
+
+ des_ecb_encrypt(cb, cb, p[0], DES_DECRYPT);
+}
+
+static int
+des1_setkey(u_int8_t **sched, u_int8_t *key, int len)
+{
+ des_key_schedule *p;
+ int err;
+
+ MALLOC(p, des_key_schedule *, sizeof (des_key_schedule),
+ M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
+ if (p != NULL) {
+ des_set_key((des_cblock *) key, p[0]);
+ err = 0;
+ } else
+ err = ENOMEM;
+ *sched = (u_int8_t *) p;
+ return err;
+}
+
+static void
+des1_zerokey(u_int8_t **sched)
+{
+ bzero(*sched, sizeof (des_key_schedule));
+ FREE(*sched, M_CRYPTO_DATA);
+ *sched = NULL;
+}
+
+static void
+des3_encrypt(caddr_t key, u_int8_t *blk)
+{
+ des_cblock *cb = (des_cblock *) blk;
+ des_key_schedule *p = (des_key_schedule *) key;
+
+ des_ecb3_encrypt(cb, cb, p[0], p[1], p[2], DES_ENCRYPT);
+}
+
+static void
+des3_decrypt(caddr_t key, u_int8_t *blk)
+{
+ des_cblock *cb = (des_cblock *) blk;
+ des_key_schedule *p = (des_key_schedule *) key;
+
+ des_ecb3_encrypt(cb, cb, p[0], p[1], p[2], DES_DECRYPT);
+}
+
+static int
+des3_setkey(u_int8_t **sched, u_int8_t *key, int len)
+{
+ des_key_schedule *p;
+ int err;
+
+ MALLOC(p, des_key_schedule *, 3*sizeof (des_key_schedule),
+ M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
+ if (p != NULL) {
+ des_set_key((des_cblock *)(key + 0), p[0]);
+ des_set_key((des_cblock *)(key + 8), p[1]);
+ des_set_key((des_cblock *)(key + 16), p[2]);
+ err = 0;
+ } else
+ err = ENOMEM;
+ *sched = (u_int8_t *) p;
+ return err;
+}
+
+static void
+des3_zerokey(u_int8_t **sched)
+{
+ bzero(*sched, 3*sizeof (des_key_schedule));
+ FREE(*sched, M_CRYPTO_DATA);
+ *sched = NULL;
+}
+
+static void
+blf_encrypt(caddr_t key, u_int8_t *blk)
+{
+ BF_LONG t[2];
+
+ memcpy(t, blk, sizeof (t));
+ t[0] = ntohl(t[0]);
+ t[1] = ntohl(t[1]);
+ /* NB: BF_encrypt expects the block in host order! */
+ BF_encrypt(t, (BF_KEY *) key);
+ t[0] = htonl(t[0]);
+ t[1] = htonl(t[1]);
+ memcpy(blk, t, sizeof (t));
+}
+
+static void
+blf_decrypt(caddr_t key, u_int8_t *blk)
+{
+ BF_LONG t[2];
+
+ memcpy(t, blk, sizeof (t));
+ t[0] = ntohl(t[0]);
+ t[1] = ntohl(t[1]);
+ /* NB: BF_decrypt expects the block in host order! */
+ BF_decrypt(t, (BF_KEY *) key);
+ t[0] = htonl(t[0]);
+ t[1] = htonl(t[1]);
+ memcpy(blk, t, sizeof (t));
+}
+
+static int
+blf_setkey(u_int8_t **sched, u_int8_t *key, int len)
+{
+ int err;
+
+ MALLOC(*sched, u_int8_t *, sizeof(BF_KEY),
+ M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
+ if (*sched != NULL) {
+ BF_set_key((BF_KEY *) *sched, len, key);
+ err = 0;
+ } else
+ err = ENOMEM;
+ return err;
+}
+
+static void
+blf_zerokey(u_int8_t **sched)
+{
+ bzero(*sched, sizeof(BF_KEY));
+ FREE(*sched, M_CRYPTO_DATA);
+ *sched = NULL;
+}
+
+static void
+cast5_encrypt(caddr_t key, u_int8_t *blk)
+{
+ cast_encrypt((cast_key *) key, blk, blk);
+}
+
+static void
+cast5_decrypt(caddr_t key, u_int8_t *blk)
+{
+ cast_decrypt((cast_key *) key, blk, blk);
+}
+
+static int
+cast5_setkey(u_int8_t **sched, u_int8_t *key, int len)
+{
+ int err;
+
+ MALLOC(*sched, u_int8_t *, sizeof(cast_key), M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
+ if (*sched != NULL) {
+ cast_setkey((cast_key *)*sched, key, len);
+ err = 0;
+ } else
+ err = ENOMEM;
+ return err;
+}
+
+static void
+cast5_zerokey(u_int8_t **sched)
+{
+ bzero(*sched, sizeof(cast_key));
+ FREE(*sched, M_CRYPTO_DATA);
+ *sched = NULL;
+}
+
+static void
+skipjack_encrypt(caddr_t key, u_int8_t *blk)
+{
+ skipjack_forwards(blk, blk, (u_int8_t **) key);
+}
+
+static void
+skipjack_decrypt(caddr_t key, u_int8_t *blk)
+{
+ skipjack_backwards(blk, blk, (u_int8_t **) key);
+}
+
+static int
+skipjack_setkey(u_int8_t **sched, u_int8_t *key, int len)
+{
+ int err;
+
+ /* NB: allocate all the memory that's needed at once */
+ MALLOC(*sched, u_int8_t *, 10 * (sizeof(u_int8_t *) + 0x100),
+ M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
+ if (*sched != NULL) {
+ u_int8_t** key_tables = (u_int8_t**) *sched;
+ u_int8_t* table = (u_int8_t*) &key_tables[10];
+ int k;
+
+ for (k = 0; k < 10; k++) {
+ key_tables[k] = table;
+ table += 0x100;
+ }
+ subkey_table_gen(key, (u_int8_t **) *sched);
+ err = 0;
+ } else
+ err = ENOMEM;
+ return err;
+}
+
+static void
+skipjack_zerokey(u_int8_t **sched)
+{
+ bzero(*sched, 10 * (sizeof(u_int8_t *) + 0x100));
+ FREE(*sched, M_CRYPTO_DATA);
+ *sched = NULL;
+}
+
+static void
+rijndael128_encrypt(caddr_t key, u_int8_t *blk)
+{
+ rijndael_encrypt((rijndael_ctx *) key, (u_char *) blk, (u_char *) blk);
+}
+
+static void
+rijndael128_decrypt(caddr_t key, u_int8_t *blk)
+{
+ rijndael_decrypt(((rijndael_ctx *) key) + 1, (u_char *) blk,
+ (u_char *) blk);
+}
+
+static int
+rijndael128_setkey(u_int8_t **sched, u_int8_t *key, int len)
+{
+ int err;
+
+ MALLOC(*sched, u_int8_t *, 2 * sizeof(rijndael_ctx), M_CRYPTO_DATA,
+ M_NOWAIT|M_ZERO);
+ if (*sched != NULL) {
+ rijndael_set_key((rijndael_ctx *) *sched, (u_char *) key, len * 8, 1);
+ rijndael_set_key(((rijndael_ctx *) *sched) + 1, (u_char *) key,
+ len * 8, 0);
+ err = 0;
+ } else
+ err = ENOMEM;
+ return err;
+}
+
+static void
+rijndael128_zerokey(u_int8_t **sched)
+{
+ bzero(*sched, 2 * sizeof(rijndael_ctx));
+ FREE(*sched, M_CRYPTO_DATA);
+ *sched = NULL;
+}
+
+/*
+ * And now for auth.
+ */
+
+static void
+null_init(void *ctx)
+{
+}
+
+static int
+null_update(void *ctx, u_int8_t *buf, u_int16_t len)
+{
+ return 0;
+}
+
+static void
+null_final(u_int8_t *buf, void *ctx)
+{
+ if (buf != (u_int8_t *) 0)
+ bzero(buf, 12);
+}
+
+static int
+RMD160Update_int(void *ctx, u_int8_t *buf, u_int16_t len)
+{
+ RMD160Update(ctx, buf, len);
+ return 0;
+}
+
+static int
+MD5Update_int(void *ctx, u_int8_t *buf, u_int16_t len)
+{
+ MD5Update(ctx, buf, len);
+ return 0;
+}
+
+static void
+SHA1Init_int(void *ctx)
+{
+ SHA1Init(ctx);
+}
+
+static int
+SHA1Update_int(void *ctx, u_int8_t *buf, u_int16_t len)
+{
+ SHA1Update(ctx, buf, len);
+ return 0;
+}
+
+static void
+SHA1Final_int(u_int8_t *blk, void *ctx)
+{
+ SHA1Final(blk, ctx);
+}
+
+static int
+SHA256Update_int(void *ctx, u_int8_t *buf, u_int16_t len)
+{
+ SHA256_Update(ctx, buf, len);
+ return 0;
+}
+
+static int
+SHA384Update_int(void *ctx, u_int8_t *buf, u_int16_t len)
+{
+ SHA384_Update(ctx, buf, len);
+ return 0;
+}
+
+static int
+SHA512Update_int(void *ctx, u_int8_t *buf, u_int16_t len)
+{
+ SHA512_Update(ctx, buf, len);
+ return 0;
+}
+
+/*
+ * And compression
+ */
+
+static u_int32_t
+deflate_compress(data, size, out)
+ u_int8_t *data;
+ u_int32_t size;
+ u_int8_t **out;
+{
+ return deflate_global(data, size, 0, out);
+}
+
+static u_int32_t
+deflate_decompress(data, size, out)
+ u_int8_t *data;
+ u_int32_t size;
+ u_int8_t **out;
+{
+ return deflate_global(data, size, 1, out);
+}
diff --git a/sys/opencrypto/xform.h b/sys/opencrypto/xform.h
new file mode 100644
index 0000000..a4960b9
--- /dev/null
+++ b/sys/opencrypto/xform.h
@@ -0,0 +1,101 @@
+/* $FreeBSD$ */
+/* $OpenBSD: xform.h,v 1.8 2001/08/28 12:20:43 ben Exp $ */
+
+/*
+ * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
+ *
+ * This code was written by Angelos D. Keromytis in Athens, Greece, in
+ * February 2000. Network Security Technologies Inc. (NSTI) kindly
+ * supported the development of this code.
+ *
+ * Copyright (c) 2000 Angelos D. Keromytis
+ *
+ * Permission to use, copy, and modify this software without fee
+ * is hereby granted, provided that this entire notice is included in
+ * all source code copies of any software which is or includes a copy or
+ * modification of this software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+ * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ */
+
+#ifndef _CRYPTO_XFORM_H_
+#define _CRYPTO_XFORM_H_
+
+#include <sys/md5.h>
+#include <crypto/sha1.h>
+#include <crypto/sha2/sha2.h>
+#include <opencrypto/rmd160.h>
+
+/* Declarations */
+struct auth_hash {
+ int type;
+ char *name;
+ u_int16_t keysize;
+ u_int16_t hashsize;
+ u_int16_t authsize;
+ u_int16_t ctxsize;
+ void (*Init) (void *);
+ int (*Update) (void *, u_int8_t *, u_int16_t);
+ void (*Final) (u_int8_t *, void *);
+};
+
+#define AH_ALEN_MAX 20 /* max authenticator hash length */
+
+struct enc_xform {
+ int type;
+ char *name;
+ u_int16_t blocksize;
+ u_int16_t minkey, maxkey;
+ void (*encrypt) (caddr_t, u_int8_t *);
+ void (*decrypt) (caddr_t, u_int8_t *);
+ int (*setkey) (u_int8_t **, u_int8_t *, int len);
+ void (*zerokey) (u_int8_t **);
+};
+
+struct comp_algo {
+ int type;
+ char *name;
+ size_t minlen;
+ u_int32_t (*compress) (u_int8_t *, u_int32_t, u_int8_t **);
+ u_int32_t (*decompress) (u_int8_t *, u_int32_t, u_int8_t **);
+};
+
+union authctx {
+ MD5_CTX md5ctx;
+ SHA1_CTX sha1ctx;
+ RMD160_CTX rmd160ctx;
+ SHA256_CTX sha256ctx;
+ SHA384_CTX sha384ctx;
+ SHA512_CTX sha512ctx;
+};
+
+extern struct enc_xform enc_xform_null;
+extern struct enc_xform enc_xform_des;
+extern struct enc_xform enc_xform_3des;
+extern struct enc_xform enc_xform_blf;
+extern struct enc_xform enc_xform_cast5;
+extern struct enc_xform enc_xform_skipjack;
+extern struct enc_xform enc_xform_rijndael128;
+extern struct enc_xform enc_xform_arc4;
+
+extern struct auth_hash auth_hash_null;
+extern struct auth_hash auth_hash_key_md5;
+extern struct auth_hash auth_hash_key_sha1;
+extern struct auth_hash auth_hash_hmac_md5_96;
+extern struct auth_hash auth_hash_hmac_sha1_96;
+extern struct auth_hash auth_hash_hmac_ripemd_160_96;
+extern struct auth_hash auth_hash_hmac_sha2_256;
+extern struct auth_hash auth_hash_hmac_sha2_384;
+extern struct auth_hash auth_hash_hmac_sha2_512;
+
+extern struct comp_algo comp_algo_deflate;
+
+#ifdef _KERNEL
+#include <sys/malloc.h>
+MALLOC_DECLARE(M_XDATA);
+#endif
+#endif /* _CRYPTO_XFORM_H_ */
OpenPOWER on IntegriCloud