/* Copyright (c) 2007 Sam Trenholme * * TERMS * * 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 'as is' with no guarantees of correctness or * fitness for purpose. */ /* This is a tiny implementation of the Radio Gatun hash function/ * stream cipher */ /* This determines the word size we use for this particular Radio Gatun * implementation; DWR_WORDSIZE needs to be a multiple of 8 */ #define DWR_WORD uint32_t #define DWR_WORDSIZE 32 /* These are hard coded in the Radio Gatun specification */ #define DWR_MILLSIZE 19 #define DWR_BELTROWS 3 #define DWR_BELTCOL 13 #define DWR_BELTFEED 12 #include #include #include void dwr_mill(DWR_WORD *a) { DWR_WORD A[DWR_MILLSIZE]; DWR_WORD x; int i = 0; int y = 0; int r = 0; int z = 0; int q = 0; for(i = 0; i < DWR_MILLSIZE ; i++) { y = (i * 7) % DWR_MILLSIZE; r = ((i * (i + 1)) / 2) % DWR_WORDSIZE; x = a[y] ^ (a[ ((y + 1) % DWR_MILLSIZE) ] | (~a[ ((y + 2) % DWR_MILLSIZE) ])); A[i] = (x >> r) | (x << (DWR_WORDSIZE - r)); } for(i = 0; i < DWR_MILLSIZE ; i++) { y = i; z = (i + 1) % DWR_MILLSIZE; q = (i + 4) % DWR_MILLSIZE; a[i] = A[y] ^ A[z] ^ A[q]; } a[0] ^= 1; } void dwr_belt(DWR_WORD *a, DWR_WORD *b) { DWR_WORD q[DWR_BELTROWS]; int s = 0; int i = 0; int v = 0; for(s = 0; s < DWR_BELTROWS ; s++) { q[s] = b[((s * DWR_BELTCOL) + DWR_BELTCOL - 1)]; } for(i = DWR_BELTCOL - 1; i > 0; i--) { for(s = 0; s < DWR_BELTROWS ; s++) { v = i - 1; if(v < 0) { v = DWR_BELTCOL - 1; } b[((s * DWR_BELTCOL) + i)] = b[((s * DWR_BELTCOL) + v)]; } } for(s = 0; s < DWR_BELTROWS; s++) { b[(s * DWR_BELTCOL)] = q[s]; } for(i = 0; i < DWR_BELTFEED ; i++) { s = (i + 1) + ((i % DWR_BELTROWS) * DWR_BELTCOL); b[s] ^= a[(i + 1)]; } dwr_mill(a); for(i = 0; i < DWR_BELTROWS; i++) { a[(i + DWR_BELTCOL)] ^= q[i]; } } /* Convert a null-terminated string in to a Radio Gatun state */ void dwr_input_map(DWR_WORD *a, DWR_WORD *b, uint8_t *v) { DWR_WORD p[3]; int q = 0; int c = 0; int r = 0; int done = 0; for(;;) { p[0] = p[1] = p[2] = 0; for(r = 0; r < 3; r++) { for(q = 0; q < DWR_WORDSIZE / 8; q++) { int x = 0; x = (int)*v; v++; x &= 0xff; if(x == 0) { done = 1; x = 1; /* Append with single byte * w/ value of 1 */ } p[r] |= x << (q * 8); if(done == 1) { for(c = 0; c < 3; c++) { b[c * 13] ^= p[c]; a[16 + c] ^= p[c]; } dwr_belt(a,b); return; } } } for(c = 0; c < 3; c++) { b[c * 13] ^= p[c]; a[16 + c] ^= p[c]; } dwr_belt(a,b); } } main(int argc, char **argv) { DWR_WORD a[DWR_MILLSIZE], b[DWR_BELTROWS * DWR_BELTCOL]; int c = 0; if(argc != 2) { printf("Usage: rg32 {input to hash}\n"); exit(1); } for(c = 0; c < DWR_MILLSIZE; c++) { a[c] = 0; } for(c = 0; c < DWR_BELTROWS * DWR_BELTCOL; c++) { b[c] = 0; } dwr_input_map(a,b,argv[1]); for(c = 0; c < 16; c++) { dwr_belt(a,b); } for(c = 0; c < 20; c++) { uint8_t d = 0, e = 0, f = 0; DWR_WORD g; dwr_belt(a,b); for(f = 1; f <= 2; f++) { g = a[f]; for(e = 0; e < DWR_WORDSIZE / 8; e++) { d = g & 0xff; g >>= 8; printf("%02x",d); } printf(" "); } } printf("\n"); }