summaryrefslogtreecommitdiffstats
path: root/sys/opencrypto/cast.c
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2002-10-04 20:31:23 +0000
committersam <sam@FreeBSD.org>2002-10-04 20:31:23 +0000
commit91416784e40204fddb837d3327a21b7fe803599b (patch)
tree031839b89be777f8989910a091b189457858c99d /sys/opencrypto/cast.c
parent16827939fabe12f22c5b06ee3fdf29f6c10b1de2 (diff)
downloadFreeBSD-src-91416784e40204fddb837d3327a21b7fe803599b.zip
FreeBSD-src-91416784e40204fddb837d3327a21b7fe803599b.tar.gz
In-kernel crypto framework derived from openbsd. This facility provides
a consistent interface to h/w and s/w crypto algorithms for use by the kernel and (for h/w at least) by user-mode apps. Access for user-level code is through a /dev/crypto device that'll eventually be used by openssl to (potentially) accelerate many applications. Coming soon is an IPsec that makes use of this service to accelerate ESP, AH, and IPCOMP protocols. Included here is the "core" crypto support, /dev/crypto driver, various crypto algorithms that are not already present in the KAME crypto area, and support routines used by crypto device drivers. Obtained from: openbsd
Diffstat (limited to 'sys/opencrypto/cast.c')
-rw-r--r--sys/opencrypto/cast.c243
1 files changed, 243 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 */
+
OpenPOWER on IntegriCloud