diff options
-rw-r--r-- | sys/opencrypto/cast.c | 243 | ||||
-rw-r--r-- | sys/opencrypto/cast.h | 23 | ||||
-rw-r--r-- | sys/opencrypto/castsb.h | 545 | ||||
-rw-r--r-- | sys/opencrypto/criov.c | 137 | ||||
-rw-r--r-- | sys/opencrypto/crmbuf.c | 118 | ||||
-rw-r--r-- | sys/opencrypto/crypto.c | 936 | ||||
-rw-r--r-- | sys/opencrypto/crypto_if.m | 128 | ||||
-rw-r--r-- | sys/opencrypto/cryptodev.c | 798 | ||||
-rw-r--r-- | sys/opencrypto/cryptodev.h | 347 | ||||
-rw-r--r-- | sys/opencrypto/cryptosoft.c | 1025 | ||||
-rw-r--r-- | sys/opencrypto/cryptosoft.h | 65 | ||||
-rw-r--r-- | sys/opencrypto/deflate.c | 189 | ||||
-rw-r--r-- | sys/opencrypto/deflate.h | 56 | ||||
-rw-r--r-- | sys/opencrypto/rijndael.c | 1244 | ||||
-rw-r--r-- | sys/opencrypto/rijndael.h | 52 | ||||
-rw-r--r-- | sys/opencrypto/rmd160.c | 363 | ||||
-rw-r--r-- | sys/opencrypto/rmd160.h | 41 | ||||
-rw-r--r-- | sys/opencrypto/skipjack.c | 258 | ||||
-rw-r--r-- | sys/opencrypto/skipjack.h | 19 | ||||
-rw-r--r-- | sys/opencrypto/xform.c | 629 | ||||
-rw-r--r-- | sys/opencrypto/xform.h | 101 |
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_ */ |