1104476Ssam/* $OpenBSD: cast.c,v 1.2 2000/06/06 06:49:47 deraadt Exp $ */ 2139825Simp/*- 3104476Ssam * CAST-128 in C 4104476Ssam * Written by Steve Reid <sreid@sea-to-sky.net> 5104476Ssam * 100% Public Domain - no warranty 6104476Ssam * Released 1997.10.11 7104476Ssam */ 8104476Ssam 9116191Sobrien#include <sys/cdefs.h> 10116191Sobrien__FBSDID("$FreeBSD$"); 11116191Sobrien 12104476Ssam#include <sys/types.h> 13104476Ssam#include <opencrypto/cast.h> 14104476Ssam#include <opencrypto/castsb.h> 15104476Ssam 16104476Ssam/* Macros to access 8-bit bytes out of a 32-bit word */ 17104476Ssam#define U_INT8_Ta(x) ( (u_int8_t) (x>>24) ) 18104476Ssam#define U_INT8_Tb(x) ( (u_int8_t) ((x>>16)&255) ) 19104476Ssam#define U_INT8_Tc(x) ( (u_int8_t) ((x>>8)&255) ) 20104476Ssam#define U_INT8_Td(x) ( (u_int8_t) ((x)&255) ) 21104476Ssam 22104476Ssam/* Circular left shift */ 23104476Ssam#define ROL(x, n) ( ((x)<<(n)) | ((x)>>(32-(n))) ) 24104476Ssam 25104476Ssam/* CAST-128 uses three different round functions */ 26104476Ssam#define F1(l, r, i) \ 27104476Ssam t = ROL(key->xkey[i] + r, key->xkey[i+16]); \ 28104476Ssam l ^= ((cast_sbox1[U_INT8_Ta(t)] ^ cast_sbox2[U_INT8_Tb(t)]) - \ 29104476Ssam cast_sbox3[U_INT8_Tc(t)]) + cast_sbox4[U_INT8_Td(t)]; 30104476Ssam#define F2(l, r, i) \ 31104476Ssam t = ROL(key->xkey[i] ^ r, key->xkey[i+16]); \ 32104476Ssam l ^= ((cast_sbox1[U_INT8_Ta(t)] - cast_sbox2[U_INT8_Tb(t)]) + \ 33104476Ssam cast_sbox3[U_INT8_Tc(t)]) ^ cast_sbox4[U_INT8_Td(t)]; 34104476Ssam#define F3(l, r, i) \ 35104476Ssam t = ROL(key->xkey[i] - r, key->xkey[i+16]); \ 36104476Ssam l ^= ((cast_sbox1[U_INT8_Ta(t)] + cast_sbox2[U_INT8_Tb(t)]) ^ \ 37104476Ssam cast_sbox3[U_INT8_Tc(t)]) - cast_sbox4[U_INT8_Td(t)]; 38104476Ssam 39104476Ssam 40104476Ssam/***** Encryption Function *****/ 41104476Ssam 42104476Ssamvoid cast_encrypt(cast_key* key, u_int8_t* inblock, u_int8_t* outblock) 43104476Ssam{ 44104476Ssamu_int32_t t, l, r; 45104476Ssam 46104476Ssam /* Get inblock into l,r */ 47104476Ssam l = ((u_int32_t)inblock[0] << 24) | ((u_int32_t)inblock[1] << 16) | 48104476Ssam ((u_int32_t)inblock[2] << 8) | (u_int32_t)inblock[3]; 49104476Ssam r = ((u_int32_t)inblock[4] << 24) | ((u_int32_t)inblock[5] << 16) | 50104476Ssam ((u_int32_t)inblock[6] << 8) | (u_int32_t)inblock[7]; 51104476Ssam /* Do the work */ 52104476Ssam F1(l, r, 0); 53104476Ssam F2(r, l, 1); 54104476Ssam F3(l, r, 2); 55104476Ssam F1(r, l, 3); 56104476Ssam F2(l, r, 4); 57104476Ssam F3(r, l, 5); 58104476Ssam F1(l, r, 6); 59104476Ssam F2(r, l, 7); 60104476Ssam F3(l, r, 8); 61104476Ssam F1(r, l, 9); 62104476Ssam F2(l, r, 10); 63104476Ssam F3(r, l, 11); 64104476Ssam /* Only do full 16 rounds if key length > 80 bits */ 65104476Ssam if (key->rounds > 12) { 66104476Ssam F1(l, r, 12); 67104476Ssam F2(r, l, 13); 68104476Ssam F3(l, r, 14); 69104476Ssam F1(r, l, 15); 70104476Ssam } 71104476Ssam /* Put l,r into outblock */ 72104476Ssam outblock[0] = U_INT8_Ta(r); 73104476Ssam outblock[1] = U_INT8_Tb(r); 74104476Ssam outblock[2] = U_INT8_Tc(r); 75104476Ssam outblock[3] = U_INT8_Td(r); 76104476Ssam outblock[4] = U_INT8_Ta(l); 77104476Ssam outblock[5] = U_INT8_Tb(l); 78104476Ssam outblock[6] = U_INT8_Tc(l); 79104476Ssam outblock[7] = U_INT8_Td(l); 80104476Ssam /* Wipe clean */ 81104476Ssam t = l = r = 0; 82104476Ssam} 83104476Ssam 84104476Ssam 85104476Ssam/***** Decryption Function *****/ 86104476Ssam 87104476Ssamvoid cast_decrypt(cast_key* key, u_int8_t* inblock, u_int8_t* outblock) 88104476Ssam{ 89104476Ssamu_int32_t t, l, r; 90104476Ssam 91104476Ssam /* Get inblock into l,r */ 92104476Ssam r = ((u_int32_t)inblock[0] << 24) | ((u_int32_t)inblock[1] << 16) | 93104476Ssam ((u_int32_t)inblock[2] << 8) | (u_int32_t)inblock[3]; 94104476Ssam l = ((u_int32_t)inblock[4] << 24) | ((u_int32_t)inblock[5] << 16) | 95104476Ssam ((u_int32_t)inblock[6] << 8) | (u_int32_t)inblock[7]; 96104476Ssam /* Do the work */ 97104476Ssam /* Only do full 16 rounds if key length > 80 bits */ 98104476Ssam if (key->rounds > 12) { 99104476Ssam F1(r, l, 15); 100104476Ssam F3(l, r, 14); 101104476Ssam F2(r, l, 13); 102104476Ssam F1(l, r, 12); 103104476Ssam } 104104476Ssam F3(r, l, 11); 105104476Ssam F2(l, r, 10); 106104476Ssam F1(r, l, 9); 107104476Ssam F3(l, r, 8); 108104476Ssam F2(r, l, 7); 109104476Ssam F1(l, r, 6); 110104476Ssam F3(r, l, 5); 111104476Ssam F2(l, r, 4); 112104476Ssam F1(r, l, 3); 113104476Ssam F3(l, r, 2); 114104476Ssam F2(r, l, 1); 115104476Ssam F1(l, r, 0); 116104476Ssam /* Put l,r into outblock */ 117104476Ssam outblock[0] = U_INT8_Ta(l); 118104476Ssam outblock[1] = U_INT8_Tb(l); 119104476Ssam outblock[2] = U_INT8_Tc(l); 120104476Ssam outblock[3] = U_INT8_Td(l); 121104476Ssam outblock[4] = U_INT8_Ta(r); 122104476Ssam outblock[5] = U_INT8_Tb(r); 123104476Ssam outblock[6] = U_INT8_Tc(r); 124104476Ssam outblock[7] = U_INT8_Td(r); 125104476Ssam /* Wipe clean */ 126104476Ssam t = l = r = 0; 127104476Ssam} 128104476Ssam 129104476Ssam 130299202Spfg/***** Key Schedule *****/ 131104476Ssam 132104476Ssamvoid cast_setkey(cast_key* key, u_int8_t* rawkey, int keybytes) 133104476Ssam{ 134171238Speteru_int32_t t[4] = {0, 0, 0, 0}, z[4] = {0, 0, 0, 0}, x[4]; 135104476Ssamint i; 136104476Ssam 137104476Ssam /* Set number of rounds to 12 or 16, depending on key length */ 138104476Ssam key->rounds = (keybytes <= 10 ? 12 : 16); 139104476Ssam 140104476Ssam /* Copy key to workspace x */ 141104476Ssam for (i = 0; i < 4; i++) { 142104476Ssam x[i] = 0; 143104476Ssam if ((i*4+0) < keybytes) x[i] = (u_int32_t)rawkey[i*4+0] << 24; 144104476Ssam if ((i*4+1) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+1] << 16; 145104476Ssam if ((i*4+2) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+2] << 8; 146104476Ssam if ((i*4+3) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+3]; 147104476Ssam } 148104476Ssam /* Generate 32 subkeys, four at a time */ 149104476Ssam for (i = 0; i < 32; i+=4) { 150104476Ssam switch (i & 4) { 151104476Ssam case 0: 152104476Ssam t[0] = z[0] = x[0] ^ cast_sbox5[U_INT8_Tb(x[3])] ^ 153104476Ssam cast_sbox6[U_INT8_Td(x[3])] ^ cast_sbox7[U_INT8_Ta(x[3])] ^ 154104476Ssam cast_sbox8[U_INT8_Tc(x[3])] ^ cast_sbox7[U_INT8_Ta(x[2])]; 155104476Ssam t[1] = z[1] = x[2] ^ cast_sbox5[U_INT8_Ta(z[0])] ^ 156104476Ssam cast_sbox6[U_INT8_Tc(z[0])] ^ cast_sbox7[U_INT8_Tb(z[0])] ^ 157104476Ssam cast_sbox8[U_INT8_Td(z[0])] ^ cast_sbox8[U_INT8_Tc(x[2])]; 158104476Ssam t[2] = z[2] = x[3] ^ cast_sbox5[U_INT8_Td(z[1])] ^ 159104476Ssam cast_sbox6[U_INT8_Tc(z[1])] ^ cast_sbox7[U_INT8_Tb(z[1])] ^ 160104476Ssam cast_sbox8[U_INT8_Ta(z[1])] ^ cast_sbox5[U_INT8_Tb(x[2])]; 161104476Ssam t[3] = z[3] = x[1] ^ cast_sbox5[U_INT8_Tc(z[2])] ^ 162104476Ssam cast_sbox6[U_INT8_Tb(z[2])] ^ cast_sbox7[U_INT8_Td(z[2])] ^ 163104476Ssam cast_sbox8[U_INT8_Ta(z[2])] ^ cast_sbox6[U_INT8_Td(x[2])]; 164104476Ssam break; 165104476Ssam case 4: 166104476Ssam t[0] = x[0] = z[2] ^ cast_sbox5[U_INT8_Tb(z[1])] ^ 167104476Ssam cast_sbox6[U_INT8_Td(z[1])] ^ cast_sbox7[U_INT8_Ta(z[1])] ^ 168104476Ssam cast_sbox8[U_INT8_Tc(z[1])] ^ cast_sbox7[U_INT8_Ta(z[0])]; 169104476Ssam t[1] = x[1] = z[0] ^ cast_sbox5[U_INT8_Ta(x[0])] ^ 170104476Ssam cast_sbox6[U_INT8_Tc(x[0])] ^ cast_sbox7[U_INT8_Tb(x[0])] ^ 171104476Ssam cast_sbox8[U_INT8_Td(x[0])] ^ cast_sbox8[U_INT8_Tc(z[0])]; 172104476Ssam t[2] = x[2] = z[1] ^ cast_sbox5[U_INT8_Td(x[1])] ^ 173104476Ssam cast_sbox6[U_INT8_Tc(x[1])] ^ cast_sbox7[U_INT8_Tb(x[1])] ^ 174104476Ssam cast_sbox8[U_INT8_Ta(x[1])] ^ cast_sbox5[U_INT8_Tb(z[0])]; 175104476Ssam t[3] = x[3] = z[3] ^ cast_sbox5[U_INT8_Tc(x[2])] ^ 176104476Ssam cast_sbox6[U_INT8_Tb(x[2])] ^ cast_sbox7[U_INT8_Td(x[2])] ^ 177104476Ssam cast_sbox8[U_INT8_Ta(x[2])] ^ cast_sbox6[U_INT8_Td(z[0])]; 178104476Ssam break; 179104476Ssam } 180104476Ssam switch (i & 12) { 181104476Ssam case 0: 182104476Ssam case 12: 183104476Ssam key->xkey[i+0] = cast_sbox5[U_INT8_Ta(t[2])] ^ cast_sbox6[U_INT8_Tb(t[2])] ^ 184104476Ssam cast_sbox7[U_INT8_Td(t[1])] ^ cast_sbox8[U_INT8_Tc(t[1])]; 185104476Ssam key->xkey[i+1] = cast_sbox5[U_INT8_Tc(t[2])] ^ cast_sbox6[U_INT8_Td(t[2])] ^ 186104476Ssam cast_sbox7[U_INT8_Tb(t[1])] ^ cast_sbox8[U_INT8_Ta(t[1])]; 187104476Ssam key->xkey[i+2] = cast_sbox5[U_INT8_Ta(t[3])] ^ cast_sbox6[U_INT8_Tb(t[3])] ^ 188104476Ssam cast_sbox7[U_INT8_Td(t[0])] ^ cast_sbox8[U_INT8_Tc(t[0])]; 189104476Ssam key->xkey[i+3] = cast_sbox5[U_INT8_Tc(t[3])] ^ cast_sbox6[U_INT8_Td(t[3])] ^ 190104476Ssam cast_sbox7[U_INT8_Tb(t[0])] ^ cast_sbox8[U_INT8_Ta(t[0])]; 191104476Ssam break; 192104476Ssam case 4: 193104476Ssam case 8: 194104476Ssam key->xkey[i+0] = cast_sbox5[U_INT8_Td(t[0])] ^ cast_sbox6[U_INT8_Tc(t[0])] ^ 195104476Ssam cast_sbox7[U_INT8_Ta(t[3])] ^ cast_sbox8[U_INT8_Tb(t[3])]; 196104476Ssam key->xkey[i+1] = cast_sbox5[U_INT8_Tb(t[0])] ^ cast_sbox6[U_INT8_Ta(t[0])] ^ 197104476Ssam cast_sbox7[U_INT8_Tc(t[3])] ^ cast_sbox8[U_INT8_Td(t[3])]; 198104476Ssam key->xkey[i+2] = cast_sbox5[U_INT8_Td(t[1])] ^ cast_sbox6[U_INT8_Tc(t[1])] ^ 199104476Ssam cast_sbox7[U_INT8_Ta(t[2])] ^ cast_sbox8[U_INT8_Tb(t[2])]; 200104476Ssam key->xkey[i+3] = cast_sbox5[U_INT8_Tb(t[1])] ^ cast_sbox6[U_INT8_Ta(t[1])] ^ 201104476Ssam cast_sbox7[U_INT8_Tc(t[2])] ^ cast_sbox8[U_INT8_Td(t[2])]; 202104476Ssam break; 203104476Ssam } 204104476Ssam switch (i & 12) { 205104476Ssam case 0: 206104476Ssam key->xkey[i+0] ^= cast_sbox5[U_INT8_Tc(z[0])]; 207104476Ssam key->xkey[i+1] ^= cast_sbox6[U_INT8_Tc(z[1])]; 208104476Ssam key->xkey[i+2] ^= cast_sbox7[U_INT8_Tb(z[2])]; 209104476Ssam key->xkey[i+3] ^= cast_sbox8[U_INT8_Ta(z[3])]; 210104476Ssam break; 211104476Ssam case 4: 212104476Ssam key->xkey[i+0] ^= cast_sbox5[U_INT8_Ta(x[2])]; 213104476Ssam key->xkey[i+1] ^= cast_sbox6[U_INT8_Tb(x[3])]; 214104476Ssam key->xkey[i+2] ^= cast_sbox7[U_INT8_Td(x[0])]; 215104476Ssam key->xkey[i+3] ^= cast_sbox8[U_INT8_Td(x[1])]; 216104476Ssam break; 217104476Ssam case 8: 218104476Ssam key->xkey[i+0] ^= cast_sbox5[U_INT8_Tb(z[2])]; 219104476Ssam key->xkey[i+1] ^= cast_sbox6[U_INT8_Ta(z[3])]; 220104476Ssam key->xkey[i+2] ^= cast_sbox7[U_INT8_Tc(z[0])]; 221104476Ssam key->xkey[i+3] ^= cast_sbox8[U_INT8_Tc(z[1])]; 222104476Ssam break; 223104476Ssam case 12: 224104476Ssam key->xkey[i+0] ^= cast_sbox5[U_INT8_Td(x[0])]; 225104476Ssam key->xkey[i+1] ^= cast_sbox6[U_INT8_Td(x[1])]; 226104476Ssam key->xkey[i+2] ^= cast_sbox7[U_INT8_Ta(x[2])]; 227104476Ssam key->xkey[i+3] ^= cast_sbox8[U_INT8_Tb(x[3])]; 228104476Ssam break; 229104476Ssam } 230104476Ssam if (i >= 16) { 231104476Ssam key->xkey[i+0] &= 31; 232104476Ssam key->xkey[i+1] &= 31; 233104476Ssam key->xkey[i+2] &= 31; 234104476Ssam key->xkey[i+3] &= 31; 235104476Ssam } 236104476Ssam } 237104476Ssam /* Wipe clean */ 238104476Ssam for (i = 0; i < 4; i++) { 239104476Ssam t[i] = x[i] = z[i] = 0; 240104476Ssam } 241104476Ssam} 242104476Ssam 243104476Ssam/* Made in Canada */ 244104476Ssam 245