#include #include #include #include #include #include #include #include #include #include /* Not required, optimizes x86-64 ASM */ /*#include */ /* * To rebuild the helptext do this. Use your new filename if its renamed. * You could just do ecbscrypto -h > helptext.txt but there are quoted * strings that will cause syntax errors if not escaped when moving * back to C code. Therefor you need to extract the HELPLINEs text, then * edit, preverving and using backslashed quotes when wanted for output * of the -h option. And then surround each line with quotes, and end * each line with a comma to make it C source code. Then use wc -l to * find the helpline count to update in the source code. I always have * at least two spaces before each line of helptext, even blank lines * in the help output are really two spaces followed by a newline. That * makes iut easy to grep and modify, and easy to read on the screen for * the user. * grep '^" ' ecbscrypto.c > ecbscrypto.helptext * Next, I remove all the open double quotes, and the close quote and * comma at EOL. Then edit the document and make it look pretty, * * If you have snip, you can strip off the C syntax in one step, like this * grep '^" ' ecbscrypto.c | snip "\"" | snip "\",$" > helptext.txt * Otherwise, just use search and delete in vi or do whatever. Then, * edit and make it match reality or whatever you want. * When finished, add the C syntax back like this. * cat helptext.txt | snip "^" "\" " | snip "$" "\"," > helptext.c * Or, just use vi and insert '" ' (doublequote space space), and at * the end of line add '",' (doublequote comma). * Find the number of lines with wc -l helptext.c * Then include it in this file by deleting HELPCOUNT lins below the * helplines declaration and read in the new file. * DONT FORGET TO UPDATE HELPLINECOUNT with the new value. * DONT FORGET TO ESCAPE QUOTEs as needed. */ #define HELPLINECOUNT 28 char *helplines[HELPLINECOUNT] = { " ", " ecbscrypto is a cipher program based on ecbs64 PRNG. ecbscrypto", " uses multiple rounds of a feistel structure, operating on 64 bit", " blocks of data. This program reads input data from STDIN and", " writes to STDOUT. This means you must use OS redirects to read", " and write files.", " ", " Usage: cat inputfile | ecbscrypto -E|-D -r[0-255] key > outputfile ", " ", " -E encrypts data read from STDIN and writes to STDOUT.", " ", " -D Decrypts data read from STDIN and writes to STDOUT.", " ", " -r sets the number reounds to use on each block of input data.", " The default is 4.", " ", " All other CLI provided input is checked for being a readable", " file and if so, opened and read for seed input. If the CLI", " argument is not a valid control option and not a readable file,", " then the ascii values are used as seed data. The secret key data", " must be at least 34 bytes. There is no upper limit. Up to 65536", " bytes are read from any file opened for input.", " ", " See the readme file, ecbscrypto.readme for more algorithm", " discussion.", " ", " Last Update: Thu 11 Aug 13:21:48 PDT 2022", " " }; /*#### END char *helplines[HELPLINECOUNT] = { ####*/ /* This is here so you can just grep ^comp and cut and paste to recompile compile gcc -o ecbscrypto -Wall -O3 ecbscrypto.c */ /* All these must be powers of 2. MAXLEN must be >= MINLEN * 2. You could use different hardcoded values really, but for ease of debugging I can check these and know that things are fairly normal after all the typo's and off by one errors. These restrictions are just a convenience, all you really need for the algorithm is the data structures and fairly random data. For integrity of the output, I restrict the minimum lfsr length to MINLEN+1 to ensure it is always at least one greater than a power of 2. This will introduce a slight bias towards lfsralen = MINLEN+1 twice as often as any other length. I take steps to counter that bias below. Any length from MINLEN+1 to MAXLEN-1 is valid. MINLEN and MAXLEN are not allowed as lfsralen values. Thats to avoid needing one extra byte for the single largest possible length if MAXLEN were 256 or 65536. The larger the state the longer the period and the longer it takes to diffuse. The shortest state is the fastest diffusion but the period will not be long enough. In the 8 bit version we could use length = 9. But that will be too easy for the cryptographer. So I allow much longer lengths to make the state just that much harder to crack. MAXINP and MAXOUT technically don't have to be powers of 2, but for ease of programming and efficiency, I force the requirement arbitrarily. If you want to change that, you would have to review the code for all power of 2 dependencies, and there are quite a few. My preferred values are #define MAXINP 65536 #define MAXOUT 65536 #define MAXLEN 128 #define MINLEN 32 */ /* MAXLEN can't be more than 128 because we use unsigned char */ /* values based on these. It's already considered too big anyway. */ #define MAXINP 65536 #define MAXOUT 65536 #define MAXLEN 128 #define MINLEN 32 /* functions */ void ecbs64setsize(unsigned char thenewsize); unsigned long long int ecbs64 (void); void savestate(void); void restorestate(void); uint64_t decrypt(long long unsigned int plaintext); uint64_t encrypt(long long unsigned int plaintext); /* * STATE STORAGE variables. These need file scope * so all functions can see them. These are all used by ecbs64(), so * we want them to be as small as possible to fit into cache. * The number of state bits is 127*64+64*4+6+7+49 = 8446 = 2^8446 * possible starting states. The 49 is the taps and minimum possible * states because taps must be unique so we dont use all combinations * of the 56 tap bite. * */ unsigned long long int adder1 = 0; /* These are the counters. */ unsigned long long int adder2 = 0; unsigned long long int adder3 = 0; unsigned long long int adder4 = 0; unsigned long long int adder1b = 0; /* These are the alternate counters. */ unsigned long long int adder2b = 0; unsigned long long int adder3b = 0; unsigned long long int adder4b = 0; unsigned char lfsralen = MINLEN+1; /* length to be strictly controlled */ unsigned char lfsrblen = MINLEN+1; /* length to be strictly controlled */ unsigned char shift = 63; /* Must be initialized correctly */ unsigned char shiftb = 63; /* Must be initialized correctly */ unsigned char maxtap = MINLEN; /* always set to lfsralen - 1 */ unsigned long long int lfsra[MAXLEN]; /* This is the main state storage */ unsigned long long int lfsrb[MAXLEN]; /* This is the main state storage */ unsigned char tapa1 = 0; /* Each tap has to be unique. */ unsigned char tapa2 = 1; /* No two taps can have the same value */ unsigned char tapa4 = 2; /* we have to start with known values */ unsigned char tapa3 = 3; /* We use unsigned 8bit integers */ unsigned char tapa5 = 4; /* We could use signed ints too */ unsigned char tapa6 = 5; /* I used unsigned and maxtap for */ unsigned char tapa7 = 6; /* easy to understand code. */ unsigned char tapa8 = 7; /* */ unsigned char tapb1 = 0; /* Each tap has to be unique. */ unsigned char tapb2 = 1; /* No two taps can have the same value */ unsigned char tapb4 = 2; /* we have to start with known values */ unsigned char tapb3 = 3; /* We use unsigned 8bit integers */ unsigned char tapb5 = 4; /* We could use signed ints too */ unsigned char tapb6 = 5; /* I used unsigned and maxtap for */ unsigned char tapb7 = 6; /* easy to understand code. */ unsigned char tapb8 = 7; /* */ unsigned char taps[MAXLEN]; /* Shuffle tap values in ecbs64setsize(n)*/ struct timespec curtime; /* Get entropy from getttime() */ unsigned long long int ns = 0; /* nanoseconds for adding entropy */ unsigned long long int seconds = 0; /* seconds - poor mans entropy */ unsigned long long int lastns = 0; /* use last results for current update */ unsigned long long int lastseconds = 0; /* for delay in adding endrypy */ int entropyflag = 0; /* flag to add entropy */ /* Below are for testing and seeding, not really part of the algorithm. */ unsigned char sindex = 0; /* index when filling lfsra from CLI */ unsigned char sindexshift = 0; /* index when filling lfsra from CLI */ unsigned char resetflag = 0; /* For use with zeroflag only */ /* * All these are just for testing ecbs64. They have nothing to do with * the algorithm. These are global for convenience, so you can put a * logstate() anywhere, and things like that. ecbs64 function is modified * to use these where it needs to be. All the 0 or 1 flags are as you * expect, 0 means off, and 1 means on. */ unsigned long long int adders[4]; /* For sscanf to read < 8 bit numbers */ int32_t dumpstate (void); /* Dumps full or partial state to STDOUT */ int32_t dumpstateerr (void); /* Dumps full or partial state to STDERR */ int32_t logstate(void); /* Dumps full state to file ecbscrypto.log */ unsigned int totalseedchars; /* How much seed data we got in bytes */ unsigned int dump = 0; /* Dump level, 0 is minimal. */ unsigned int logging = 0; /* Default is to never log state */ unsigned int setsize = 0; /* binary flag and value > 0 is length */ unsigned char zeroflag = 0; /* Tells us to zero out adders and lfsra */ unsigned char ENCRYPT = 0; /* Encrypt data flag, needs to read stdin */ unsigned char DECRYPT = 0; /* Decrypt data flag, requires stdin */ unsigned char lastchar = 0; /* Needed by encrypt and decrypt */ int tapsint[MAXLEN]; /* Used to read values from dump file */ unsigned char x; /* exponent for shuffle tap values */ unsigned int swapa, swapb; /* the elements to swao in shuffle */ int rounds = 4; /* How many loops through feistel code */ static unsigned char busy = 0; /* This is here to disable reset while */ /* Everything above has to be global file scope. */ /***************************************************************************/ int32_t main(int32_t argc, char ** argv) { int32_t i = 0; /* primary loop counter */ int32_t j = 0; /* secondary loop counter */ int32_t readcount = 0; /* bytes read from last input file or CLI string */ long long unsigned int lastreadcount = 0LLU; long long unsigned int plaintext; long long unsigned int lastplaintext; long long unsigned int * plaintextptr; char curargv[MAXINP]; /* for reading in CLI arguments */ int32_t curargc = 1; /* The current CLI argument we are working on */ FILE *INP; /* For reading files */ FILE *SYSINP; unsigned char seedbuffer[MAXINP]; /* buffer for urandom seed data */ unsigned char seedbuffer1[MAXINP]; /* buffer for urandom seed data */ unsigned char seedbuffer2[MAXINP]; /* buffer for urandom seed data */ unsigned char seedbuffer3[MAXINP]; /* buffer for urandom seed data */ int32_t readcount1 = 0; /* bytes read from last input file or CLI string */ int32_t readcount2 = 0; /* bytes read from last input file or CLI string */ int32_t readcount3 = 0; /* bytes read from last input file or CLI string */ unsigned long long int outbuffer[MAXOUT]; /* for binay output data */ unsigned long long int noncebuffer[8]; /* for binay output data */ uint32_t maxbytesok = 0; /* for self test that #defines are valid */ uint32_t maxoutok = 0; /* for self test that #defines are valid */ uint32_t maxlenok = 0; /* for self test that #defines are valid */ uint32_t minlenok = 0; /* for self test that #defines are valid */ char line[1024]; /* used to read in the config file line by line */ int tmp; /* used for swapping taps */ /* Quick check to make sure the defined sizes are powers of 2 */ j = 1; for (i=3; i<24; i++) { if (MAXINP == (j<= MINLEN*2 %u\n", MAXLEN, (MINLEN*2)); exit(1); } for (i=0; i 2) { memccpy(line, &curargv[2], 0, 80); } else { ++curargc; if (curargc > argc) { printf("Error: Rounds number not given. Last CLI\n"); return(0); } memccpy(line, argv[curargc-1], 0, 80); if ((line[0] < 48) || (line[0] > 57)) { printf("Error: Rounds number not given.\n"); return(0); } } i = 0; rounds = 0; while ((line[i] >= 48) && (line[i] <= 57) && (line[i] != 0)) { rounds = (rounds*10) + (line[i]-48); ++i; } if (rounds > 255) { rounds = 255; } if (rounds < 1) { rounds = 1; } ++curargc; continue; } errno = 0; INP = fopen(curargv, "r"); if (errno == 0) { /* If the file is readable, read in a chunk and add it to the LFSR. */ readcount = fread(seedbuffer, 1, (MAXINP), INP); if (readcount > 0) { /*fprintf(stderr, "readount = %d sindex = %d\n", readcount, sindex);*/ totalseedchars += readcount; for (i=0; i= 64) { sindexshift = 0; } ecbs64setsize(MAXLEN-1); adder1 += ecbs64(); adder2 += ecbs64(); adder3 += ecbs64(); adder4 += ecbs64(); } } fclose(INP); } else { /* If its an empty file, then use the filename string as seed data */ fclose(INP); readcount = strlen(curargv); totalseedchars += readcount; for (i=0; i= 64) { sindexshift = 0; } ecbs64setsize(MAXLEN-1); adder1 += ecbs64(); adder2 += ecbs64(); adder3 += ecbs64(); adder4 += ecbs64(); } } } } else { /* If its not a readable file, then use the string as seed data */ readcount = strlen(curargv); totalseedchars += readcount; for (i=0; i= 64) { sindexshift = 0; } ecbs64setsize(MAXLEN-1); adder1 += ecbs64(); adder2 += ecbs64(); adder3 += ecbs64(); adder4 += ecbs64(); } } } ++curargc; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* END of CLI option processing. We have all the CLI data now. */ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* * If we got seed characters we need at least MINLEN characters. So if we * got less than needed, its an error and we can't do anytrhing about it. * If we had gotten 0 seed bytes then we know the user just wanted to use * the system PRNG for seed, but since he gave us a feeble attempt at * seeding, we think he really meant to use his own seed data. */ if (totalseedchars < (MINLEN+4)) { i = (MINLEN+4); printf("Error: Only got %d seed bytes. I need at least %d bytes.\n", totalseedchars, i); return(0); } ecbs64setsize(MAXLEN-1); adder1 += ecbs64(); adder2 += ecbs64(); adder3 += ecbs64(); adder4 += ecbs64(); ecbs64setsize(MAXLEN-1); if (dump) { dumpstateerr(); return(0); } if (ENCRYPT) { errno = 0; SYSINP = fopen("/dev/urandom", "r"); if (errno == 0) { readcount = fread(noncebuffer, sizeof(unsigned long long int), 5, SYSINP); if (readcount != 5) { printf("You should never see this but I couldn't read 5 numbers from dev/urandom.\n"); printf("Exiting on error. Can't read /dev/urandom to get seed values.\n"); exit(0); } } else { printf("You should never see this but I couldn't read 5 numbers from dev/urandom.\n"); printf("Exiting on error. Can't read /dev/urandom to get seed values.\n"); exit(0); } busy = 1; fwrite(noncebuffer, 8, 5, stdout); noncebuffer[0] = encrypt(noncebuffer[0]); noncebuffer[1] = encrypt(noncebuffer[1]); noncebuffer[2] = encrypt(noncebuffer[2]); noncebuffer[3] = encrypt(noncebuffer[3]); adder1b = noncebuffer[0]; adder2b = noncebuffer[1]; adder3b = noncebuffer[2]; adder4b = noncebuffer[3]; for (i=0; i<128; i+=4) { noncebuffer[0] = encrypt(noncebuffer[0]); noncebuffer[1] = encrypt(noncebuffer[1]); noncebuffer[2] = encrypt(noncebuffer[2]); noncebuffer[3] = encrypt(noncebuffer[3]); lfsrb[i] = noncebuffer[0]; lfsrb[i+1] = noncebuffer[1]; lfsrb[i+2] = noncebuffer[2]; lfsrb[i+3] = noncebuffer[3]; } lfsrblen = lfsralen; shiftb = shift; /* Before we get started I want to scramble the taps again. */ /* This could be changed to use the Fisher-Yates. */ for (i=0; i= lfsralen) { noncebuffer[2] = encrypt(noncebuffer[2]); swapa = (swapa + noncebuffer[2]) & x; } while (swapb >= lfsralen) { noncebuffer[3] = encrypt(noncebuffer[3]); swapb = (swapb + noncebuffer[3]) & x; } tmp = taps[swapa]; taps[swapa] = taps[swapb]; taps[swapb] = tmp; } tapb1 = taps[0]; tapb2 = taps[1]; tapb3 = taps[2]; tapb4 = taps[3]; tapb5 = taps[4]; tapb6 = taps[5]; tapb7 = taps[6]; tapb8 = taps[7]; restorestate(); busy = 0; if (dump) { dumpstateerr(); } lastplaintext = encrypt(noncebuffer[4]); adder3 += lastplaintext; readcount = fread(seedbuffer, 1, 8, stdin); while (readcount) { if (readcount == 8) { plaintextptr = (long long unsigned int *) seedbuffer; plaintext = *plaintextptr; plaintext ^= lastplaintext; lastplaintext = *plaintextptr; outbuffer[0] = encrypt(plaintext); adder3 += plaintext; } else { if (readcount) { for (i=readcount; i<8; i++) { seedbuffer[i] = 0; } plaintextptr = (long long unsigned int *) seedbuffer; plaintext = *plaintextptr; plaintext ^= lastplaintext; lastplaintext = *plaintextptr; outbuffer[0] = encrypt(plaintext); adder3 += plaintext; } } lastreadcount = (long long unsigned int) readcount; fwrite(outbuffer, 8, 1, stdout); readcount = fread(seedbuffer, 1, 8, stdin); } noncebuffer[4] = encrypt(noncebuffer[4]); lastreadcount ^= noncebuffer[4]; outbuffer[0] = encrypt(lastreadcount); fwrite(outbuffer, 8, 1, stdout); if (dump) { dumpstateerr(); } return(0); } if (DECRYPT) { fread(noncebuffer, 8, 5, stdin); busy = 1; noncebuffer[0] = encrypt(noncebuffer[0]); noncebuffer[1] = encrypt(noncebuffer[1]); noncebuffer[2] = encrypt(noncebuffer[2]); noncebuffer[3] = encrypt(noncebuffer[3]); adder1b = noncebuffer[0]; adder2b = noncebuffer[1]; adder3b = noncebuffer[2]; adder4b = noncebuffer[3]; for (i=0; i<128; i+=4) { noncebuffer[0] = encrypt(noncebuffer[0]); noncebuffer[1] = encrypt(noncebuffer[1]); noncebuffer[2] = encrypt(noncebuffer[2]); noncebuffer[3] = encrypt(noncebuffer[3]); lfsrb[i] = noncebuffer[0]; lfsrb[i+1] = noncebuffer[1]; lfsrb[i+2] = noncebuffer[2]; lfsrb[i+3] = noncebuffer[3]; } lfsrblen = lfsralen; shiftb = shift; for (i=0; i= lfsralen) { noncebuffer[2] = encrypt(noncebuffer[2]); swapa = (swapa + noncebuffer[2]) & x; } while (swapb >= lfsralen) { noncebuffer[3] = encrypt(noncebuffer[3]); swapb = (swapb + noncebuffer[3]) & x; } tmp = taps[swapa]; taps[swapa] = taps[swapb]; taps[swapb] = tmp; } tapb1 = taps[0]; tapb2 = taps[1]; tapb3 = taps[2]; tapb4 = taps[3]; tapb5 = taps[4]; tapb6 = taps[5]; tapb7 = taps[6]; tapb8 = taps[7]; restorestate(); busy = 0; lastplaintext = encrypt(noncebuffer[4]); adder3 += lastplaintext; readcount1 = fread(seedbuffer1, 1, 8, stdin); readcount2 = fread(seedbuffer2, 1, 8, stdin); readcount3 = fread(seedbuffer3, 1, 8, stdin); while (readcount3) { plaintextptr = (long long unsigned int *) seedbuffer1; plaintext = *plaintextptr; outbuffer[0] = decrypt(plaintext); adder3 += outbuffer[0]; outbuffer[0] ^= lastplaintext; lastplaintext = outbuffer[0]; fwrite(outbuffer, 8, 1, stdout); for (i=0; i<8; i++) { seedbuffer1[i] = seedbuffer2[i]; seedbuffer2[i] = seedbuffer3[i]; } readcount3 = fread(seedbuffer3, 1, 8, stdin); } if (readcount1 && readcount2) { plaintextptr = (long long unsigned int *) seedbuffer1; plaintext = *plaintextptr; outbuffer[0] = decrypt(plaintext); adder3 += outbuffer[0]; outbuffer[0] ^= lastplaintext; lastplaintext = outbuffer[0]; plaintextptr = (long long unsigned int *) seedbuffer2; plaintext = *plaintextptr; outbuffer[1] ^= lastplaintext; lastplaintext = outbuffer[1]; noncebuffer[4] = encrypt(noncebuffer[4]); outbuffer[1] = decrypt(plaintext); outbuffer[1] ^= noncebuffer[4]; if (outbuffer[1] > 8) { outbuffer[1] = 8; } fwrite(outbuffer, 1, outbuffer[1], stdout); } return(0); } while (1) { for (i=0; i MINLEN) && (thenewsize < MAXLEN)) { newsize = thenewsize; busy = 1; for (i=0; i= newsize) { swapa = (swapa + ecbs64()) & x; } while (swapb >= newsize) { swapb = (swapb + ecbs64()) & x; } tmp = taps[swapa]; taps[swapa] = taps[swapb]; taps[swapb] = tmp; } tapa1 = taps[0]; tapa2 = taps[1]; tapa3 = taps[2]; tapa4 = taps[3]; tapa5 = taps[4]; tapa6 = taps[5]; tapa7 = taps[6]; tapa8 = taps[7]; lfsralen = newsize; maxtap = lfsralen - 1; for (i=0; i<(MAXLEN+lfsralen); i++) { swapa = ecbs64() & x; swapb = ecbs64() & x; while (swapa >= newsize) { swapa = (swapa + ecbs64()) & x; } while (swapb >= newsize) { swapb = (swapb + ecbs64()) & x; } tmp = taps[swapa]; taps[swapa] = taps[swapb]; taps[swapb] = tmp; } tapa1 = taps[0]; tapa2 = taps[1]; tapa3 = taps[2]; tapa4 = taps[3]; tapa5 = taps[4]; tapa6 = taps[5]; tapa7 = taps[6]; tapa8 = taps[7]; busy = 0; } } /* END ecbs64setsize */ unsigned long long int ecbs64 (void) { unsigned long long int swap; unsigned long long int tmp; --tapa1; if (tapa1 > maxtap) { tapa1 = maxtap; } --tapa2; if (tapa2 > maxtap) { tapa2 = maxtap; } --tapa3; if (tapa3 > maxtap) { tapa3 = maxtap; } --tapa4; if (tapa4 > maxtap) { tapa4 = maxtap; } --tapa5; if (tapa5 > maxtap) { tapa5 = maxtap; } --tapa6; if (tapa6 > maxtap) { tapa6 = maxtap; } --tapa7; if (tapa7 > maxtap) { tapa7 = maxtap; } --tapa8; if (tapa8 > maxtap) { tapa8 = maxtap; } ++adder1; if (adder1 == 0) { ++adder2; if (adder2 == 0) { ++adder3; if (adder3 == 0) { ++adder4; } } } /* # 1 Select 4 most unused taps and operations */ lfsra[tapa6] += adder1; lfsra[tapa2] -= adder2; lfsra[tapa8] ^= adder3; lfsra[tapa7] ^= adder4; /* # 2 select taps 1-4, unique ops including * and parenthesis # 4*3*2*6*6 = 864 */ lfsra[tapa1] = ((lfsra[tapa3] - lfsra[tapa1]) * ((lfsra[tapa4] ^ lfsra[tapa2])|1)); --shift; if (shift == 0) { shift = 63; } lfsra[tapa1] = ((lfsra[tapa1] >> shift) | (lfsra[tapa1] << (64-shift))); /* # 3 select two most unused taps and operation 6 * 3 = 18 */ swap = (lfsra[tapa4] ^ lfsra[tapa3]) & 7; switch (swap) { case 0: tmp = tapa1; tapa1 = tapa2; tapa2 = tmp; break; case 1: tmp = tapa2; tapa2 = tapa3; tapa3 = tmp; break; case 2: tmp = tapa3; tapa3 = tapa4; tapa4 = tmp; break; case 3: tmp = tapa4; tapa4 = tapa5; tapa5 = tmp; break; case 4: tmp = tapa5; tapa5 = tapa6; tapa6 = tmp; break; case 5: tmp = tapa6; tapa6 = tapa7; tapa7 = tmp; break; case 6: tmp = tapa7; tapa7 = tapa8; tapa8 = tmp; break; case 7: tmp = tapa8; tapa8 = tapa1; tapa1 = tmp; break; default: break; } /* # 4 select taps 5 - 8, unique ops including * and parenthesis # 4*3*2*6*6 = 864 */ lfsra[tapa5] = (lfsra[tapa8] ^ ((lfsra[tapa7] - lfsra[tapa6]) * (lfsra[tapa5]|1))); --shift; if (shift == 0) { shift = 63; } lfsra[tapa5] = ((lfsra[tapa5] >> shift) | (lfsra[tapa5] << (64-shift))); /* # 5 select one most unused tap and number from 0 to 1048575 # 6 * 1048576 */ if ((lfsra[tapa7] & 1048575LLU) == 74414LLU) { /* # 6 select one most unused tap 6 */ setsize = ( lfsra[tapa2] & (MAXLEN-1) ); setsize |= (MAXLEN/2); ecbs64setsize(setsize); } return(lfsra[tapa1] ^ lfsra[tapa5]); } /* END ecbs64 */ void savestate(void) { int i; lfsrblen = lfsralen; for (i=0; i>= 32; random32[i+1] = (uint32_t) rnum & (4294967295LLU); } i = 0; right = (uint32_t) (plaintext & 4294967295LLU); plaintext >>= 32; left = (uint32_t) (plaintext & 4294967295LLU); for (j=0; j>= 32; random32[i+1] = (uint32_t) rnum & (4294967295LLU); } i = (rounds * 4) - 1; right = (uint32_t) (plaintext & 4294967295LLU); plaintext >>= 32; left = (uint32_t) (plaintext & 4294967295LLU); for (j=(rounds-1); j>=0; j--) { left ^= right; left ^= random32[i]; --i; tmp = right; right = left; left = tmp; left ^= right; left += random32[i]; --i; tmp = right; right = left; left = tmp; left ^= right; left ^= random32[i]; --i; tmp = right; right = left; left = tmp; left ^= right; left -= random32[i]; --i; tmp = right; right = left; left = tmp; } rnum = left; rnum <<= 32; rnum += right; return(rnum); }