#define _GNU_SOURCE #include #include #include #include #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 ecbscryptogen -h > helptext.txt but there are quoted * strings that will cause syntax errors if not escaped when moving * back to C code. Therefore 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 four spaces followed by a newline. That * makes it easy to grep and modify, and easy to read on the screen for * the user. * grep '^" ' ecbscryptogen.c > ecbscryptogen.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 '^" ' ecbscryptogen.c | snip "\"" | snip "\",$" > helptext.txt * Otherwise, just use search and delete in vi or do whatever. Then, * edit and make it match whatever you need it to say. * 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. * If you change the name of this program, you have to search and replace * each instance, and you MAY have to change the hardcoded strncomp value * to the new length of the filename. You have to use the g for global * switch for the search and replace. I do it like this. (You don't * normally have to change the ".c" parti). * :%s/ecbscryptogen/newprogname/g * That will leave you on the last instance. Now copy the full filename * including the .c at the end, and search for that. You will find one * of two instances of fprintf or sscanf or something that requires the * length in bytes, not including the terminating 0. */ #define HELPLINECOUNT 90 char *helplines[HELPLINECOUNT] = { " ", " ecbscryptogen - encrypt and decrypt files.", " ", " Usage: ecbscryptogen -E|-D -f filename -r[4-255] keyfile \"keydata\"", " ", " Usage: ecbscryptogen", " ", " ecbscryptogen is a cipher program based on ecbs64 PRNG. ecbscryptogen", " uses multiple rounds of a feistel structure, operating on 64 bit", " blocks of data.", " ", " There are two modes of operation. You can provide command line options", " or if run without options, ecbscryptogen will prompt for the options.", " When prompting interactively, you enter any key parts seperately", " instead of one big long line. For example, on the command line,", " you can specify a string, followed by a filename followed by another", " string. In interactive mode each CLI argument has to be entered in", " a line by itself and followed by the return key. Also, interactive", " mode does not strip double quotes, or backslashes like the shell", " does with CLI arguments. But if you are aware of that you can make", " sure the key date works the same either way.", " ", " In CLI command mode, either -E or -D for encrypt or decrypt, a filename", " to work on, the secret key. The secret key can be composed of", " multiple CLI arguments which may be readable files or just strings", " of key text", " ", " The file will be ciphered and a new output file will be created.", " The newly created filename will have \".enc\" appended if it is for", " encrypt, and for decrypt, \".dec\" will be appeneded, unless the", " file ends with \".enc\" in which case it is changed from enc to dec.", " The secret key can be a file or any CLI input, quoted and backspaced", " as needed to pass through the command shell. If any CLI argument is", " NOT -D, -E, -r, or -f, then it is checked for being a readable file,", " and if so, up to 65536 bytes are read from the file to seed the PRNG.", " If the CLI argument was not a readable file, then, the argument", " itself is used to seed the PRNG. If the file contents are used, then", " the filename itself is not used.", " ", " Usage: ecbscryptogen -E|-D -f filename -r[4-255] keydata ", " ", " -E Encrypts data read from the -f filename.", " For encryption, the filename specified is always appended with", " \".enc\" to create the output filename.", " ", " -D Decrypts data read from the -f filename.", " For decryption, the filename specified is appended with", " \".dec\" to create the output filename, UNLESS the filename", " ends with \".enc\" in which case enc is changed to dec.", " ", " -f filename File specifification, the file to encrypt or decrypt.", " ", " -r rounds Rounds to use on each block of input data.", " The default is 4. Rounds are expensive, 8 rounds takes", " twice as long as 4 rounds. Must be at least 1 and < 256", " ", " -v Prints a signature number and exits.", " Since any ecbs program is not always the exact same algorithm,", " version numbers don't matter if its incompatible because it's", " been modified and recompiled. The signature provides a way to", " see the output of a standard initial state consisting of", " lfsralen = MAXLEN-1", " adders 1-4 = 0;", " lfsra[0] - lfsra[MAXLEN-1] = their index value", " shift = 63", " After 2*MAXLEN iterations, two 64 numbers are generated and", " printed to stderr in zero padded HEX. This is the only way", " you can confirm that one copy of the program will produce", " the same results as another copy, whether they look identical", " or not. You don't have to remember or compare a hash checksum.", " The signature function is also called if no CLI arguments are", " given.", " ", " The secret key data must be at least 34 bytes. There is no upper", " limit but only 65536 bytes are read from any CLI specified file.", " ", " This file generates one of approximately 131787103329300240138240000", " possible variants of ecbs64(). See the readme file, howitworks.html", " for algorithm discussion and the special -g option.", " ", " If you use -g on the command line, the generated files are left in", " place. The generated program ecbscryptog cannot be used by itself.", " It must be executed by ecbscryptogen because ecbscryptogen passes", " the IV to the newly generated program using a hidden shared memory.", " You can save the output files but they won't work, unless you edit", " and recompile ecbscryptogen.c to prevent it from deleting the shared", " memory by the shmctl() function call.", " ", " Last Update: Sun 11 Sep 08:52:03 PDT 2022", " " }; /*#### END char *helplines[HELPLINECOUNT] = { ####*/ /* This is here so you can just grep ^comp and cut and paste to recompile compile gcc -o ecbscryptogen -Wall -Wno-format-overflow -O3 ecbscryptogen.c compile clang -o ecbscryptogen -Wall -O3 ecbscryptogen.c compile The -Wno-format-overflow turns off useless warnings from sprintf. compile If the user filename > 1000 bytes it SHOULD crash and burn. */ /* 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 for the taps. It's already considered too big anyway. */ /* We can't depend on cycling through 256 unsigned char values */ /* to avoid compare and reset because we have variable length, */ /* so we always have to set a max tap value that we either compare */ /* to or set the taps to. I might revisit this and just always */ /* compare to lfsralen and simply not use element 255. */ /* MINLEN could just as well be 64, but we want to require at least */ /* MINLEN + 4 bytes of seed and 68 bytes is dammed near a book. */ /* You could change the seed algorithm to split out the bits and */ /* spread them around, but I haven't gotten that far yet. */ #define MAXINP 65536 #define MAXOUT 65536 #define MAXLEN 128 #define MINLEN 32 /* FUNCTIONS */ void signal_handler(int signo); void ecbs64setsize(unsigned char thenewsize); unsigned long long int ecbs64 (void); void restorestate(void); void savestate(void); int create(char * myfile); uint64_t fdecrypt(long long unsigned int plaintext); uint64_t fencrypt(long long unsigned int plaintext); void getsignature(void); int writestate(); /* These are global so signal handler can use them */ unsigned int myuid; uid_t uid; char myfile[1024]; char mycompile[1024]; char myexe[1024]; char command[1024]; int destroyshmid = 0; /* * 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 don't use the high bit, it only indicates * overflow. So I don't count the overflow bit. 2^8446 is a decimal * number with 2579 digits. It's really big. * */ long long unsigned int signature[2]; /* Raw signature, see getsignature() */ 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)*/ unsigned char x; /* exponent for shuffle tap values */ unsigned int swapa, swapb; /* the elements to swap in shuffle */ int rounds = 4; /* How many loops through feistel code */ static unsigned char busy = 0; /* This is here to disable reset while */ /* encrypting nonce to keep length 127 */ FILE *INP; /* For reading files */ FILE *OUT; /* For reading files */ FILE *SYSINP; /* For reading /devv/urandom */ FILE *CRYPTO; /* For writing generated program */ unsigned char sindex = 0; /* index when filling lfsra from CLI */ /* fills adders first, then lfsra and */ /* cycles back to adders. */ unsigned char sindexshift = 0; /* shift seed bytes this many bits left */ /* when sindex cycles, sindexshift is */ /* incremented by 8. When it reachs 64 */ /* it cycles back to 0. */ unsigned char savefiles = 0; /* set by -g option to not delete files */ int32_t dumpstate (void); /* Dumps full or partial state to STDOUT */ int32_t dumpstateerr (void); /* Dumps full or partial state to STDERR */ unsigned int totalseedchars; /* How much seed data we got in bytes */ unsigned int dump = 0; /* Dumplevel, 0 is off, 1 is min, 2 is max */ unsigned int setsize = 0; /* binary flag and value > 0 is length */ 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 */ unsigned char shmprojid = 0; char shmfilename[256]; char infile[1024]; /* The file to be encrypted or decrypted */ char outfile[1024]; /* The encrypted or decrypted output file */ /***************************************************************************/ 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 */ char curargv[MAXINP]; /* for reading in CLI arguments */ int32_t curargc = 1; /* The current CLI argument we are working on */ char seedbuffer[MAXINP]; /* buffer for urandom seed data */ 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; /* for various things, length of filename */ int showsig = 0; /* flag to display signature */ int namelen; int myargc; int gotfile = 0; /* Set up the signal handler function. The function signal_handler is defined above. Code execution starts at first statement in main(). */ if (signal(SIGINT, signal_handler) == SIG_ERR) { printf("\ncan't catch SIGINT\n"); } /* 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 1) && (strncmp(argv[1], "-h", 2) == 0)) { for (i=0; i 1) && (strncmp(argv[1], "-v", 2) == 0)) { fprintf(stderr, "%08llX%08llX\n", signature[0], signature[1]); return(0); } myargc = argc; if (argc < 2) { for (i=0; i<1024; i++) { seedbuffer[i] = 0; } i = 0; while ((seedbuffer[0] != 'E') && (seedbuffer[0] != 'D')) { printf("Enter E for Encrypt or D for Decrypt: "); fgets(seedbuffer, 1024, stdin); if (i == 3) { printf("Look, we're not getting anywhere here.\n"); printf("Please press the E key or the D key followed by return key.\n"); } if (i == 6) { printf("You are misbehaving. This is not working.\n"); exit(0); } ++i; } if (seedbuffer[0] == 'E') { ENCRYPT = 1; } else { DECRYPT = 1; } gotfile = 0; while (!gotfile) { if (ENCRYPT) { printf("Enter the filename to encrypt: "); } else { printf("Enter the filename to decrypt: "); } fgets(infile, 1024, stdin); namelen = strlen(infile); if (namelen < 2) { printf("I need a filename to work on.\n"); } else { infile[namelen] = 0; infile[namelen-1] = 0; gotfile = 1; } } printf("Enter the number of rounds or press return for default 4 rounds: "); fgets(seedbuffer, 1024, stdin); if (seedbuffer[0] != '\n') { rounds = 0; while ((seedbuffer[i] >= 48) && (seedbuffer[i] <= 57) && (seedbuffer[i] != 0)) { rounds = (rounds*10) + (seedbuffer[i]-48); ++i; } if (rounds > 255) { rounds = 255; } if (rounds < 1) { rounds = 1; } } else { rounds = 4; } myargc = argc; seedbuffer[0] = '0'; printf("Enter the key data below, one item per line.\n"); printf("Key data can be readable filenames or strings of characters\n"); printf("Key data is read as input. Do not enclose in quotes or use\n"); printf("backslashes to escape characters. There is no shell processing.\n\n"); printf("Press return only with no other characters to end input.\n"); while (seedbuffer[0] != '\n') { fgets(seedbuffer, 1024, stdin); namelen = strlen(seedbuffer); if (namelen > 1) { seedbuffer[namelen] = 0; seedbuffer[namelen-1] = 0; --namelen; argv[myargc] = malloc(namelen); strncpy(argv[myargc], seedbuffer, namelen); ++myargc; seedbuffer[0] = 0; } printf("Press return only with no other characters to end input.\n"); } printf("I got\n"); if (ENCRYPT) { printf("Encrypt %s using %d rounds\n", infile, rounds); } else { printf("Decrypt %s using %d rounds\n", infile, rounds); } printf("argc = %d myargc = %d\n", argc, myargc); for (i=argc; 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; } if ((strncmp(curargv, "-f", 2) == 0) && (!gotfile)) { readcount = strlen(curargv); if (readcount > 2) { memccpy(infile, &curargv[2], 0, 80); } else { /* If the filename was provided with a space after the "-f" then we have to */ /* get the next CLI argument and check that its a valid filename. If we are */ /* already on the last CLI argument then the filename is missing. */ ++curargc; if (curargc > argc) { printf("Error: file name not specified for -f CLI option.\n"); return(0); } memccpy(infile, argv[curargc-1], 0, 80); } ++curargc; continue; } /* * If it gets down here, all the CLI options have already been checked * so its seed data. If it happens to be a readable file, then read it, * otherwise, use the CLI argument itself as seed data. */ 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 (showsig) { fprintf(stderr, "%08llX%08llX\n", signature[0], signature[1]); return(0); } /* * 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 anything about it. * Unlike the PRNG, we can't generate seed. For crypto the user has to * specify it. Actually we could, but then anybody with the same program * can decrypt it. On the other hand, any modification to ecbs64() in * this program will make it unique and it could be used without a secret * key. But anybody who gets a copy of that program would be able to use * it to decrypt all your bases are belong to me. */ 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); } /* * This is the initial mixing of user seed data. Notice we always use * MAXLEN-1. That's to make sure all the upper elements get mixed in. */ ecbs64setsize(MAXLEN-1); adder1 += ecbs64(); adder2 += ecbs64(); adder3 += ecbs64(); adder4 += ecbs64(); ecbs64setsize(MAXLEN-1); /* No CLI option for this, but it's here in case you want to use it. */ if (dump) { dumpstate(); return(0); } tmp = strlen(infile); if ((tmp < 1) && (DECRYPT || ENCRYPT)) { printf("Error: I need a file to work on. Specify the filename with -f option.\n"); return(0); } errno = 0; SYSINP = fopen("/dev/urandom", "r"); if (errno == 0) { readcount = fread(noncebuffer, sizeof(unsigned long long int), 1, SYSINP); if (readcount != 1) { printf("You should never see this but I couldn't read 1 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 1 numbers from dev/urandom.\n"); printf("Exiting on error. Can't read /dev/urandom to get seed values.\n"); exit(0); } fclose(SYSINP); /* This gets our shared memory. */ shmprojid = noncebuffer[1] & 255; /*fprintf(stderr, "%d\n", shmprojid);*/ if (ENCRYPT) { /*dumpstateerr();*/ errno = 0; INP = fopen(infile, "r"); if (errno != 0) { printf("I couldn't open %s for reading. Exiting now.\n", infile); exit(0); } fclose(INP); memccpy(outfile, infile, 0, tmp); outfile[tmp] = '.'; outfile[tmp+1] = 'e'; outfile[tmp+2] = 'n'; outfile[tmp+3] = 'c'; outfile[tmp+4] = 0; errno = 0; OUT = fopen(outfile, "w"); if (errno != 0) { printf("I couldn't open %s for reading. Exiting now.\n", outfile); exit(0); } 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); } fclose(SYSINP); /* * busy = 1 means the ecbs64setsize function will not run. * This is so the ecbs64setsize function will NOT be executed until we * reload the LFSR elements and start over with new taps to encrypt the * message. After that the algorithm can change size but this ensures it * does not change until we finish using it to encrypt the nonces. */ busy = 1; fwrite(noncebuffer, 8, 5, OUT); fclose(OUT); noncebuffer[0] = fencrypt(noncebuffer[0]); noncebuffer[1] = fencrypt(noncebuffer[1]); noncebuffer[2] = fencrypt(noncebuffer[2]); noncebuffer[3] = fencrypt(noncebuffer[3]); adder1b = noncebuffer[0]; adder2b = noncebuffer[1]; adder3b = noncebuffer[2]; adder4b = noncebuffer[3]; for (i=0; i<128; i+=4) { noncebuffer[0] = fencrypt(noncebuffer[0]); noncebuffer[1] = fencrypt(noncebuffer[1]); noncebuffer[2] = fencrypt(noncebuffer[2]); noncebuffer[3] = fencrypt(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] = fencrypt(noncebuffer[2]); swapa = (swapa + noncebuffer[2]) & x; } while (swapb >= lfsralen) { noncebuffer[3] = fencrypt(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]; /* * This loads the encrypted nonce lfsrb values into lfsra so we use * the new state from now on. This state was derived from the user * seed used to encrypt the noncebuffers which are stored in the alternate * state, lfsrb, tapb1 and so on. restorestate() just copies all the * lfsrb stuff into lfsra, adders, shift, everything. */ restorestate(); /* Now we are not prohibiting resize anymore. */ busy = 0; for (i=0; i<1024; i++) { myfile[i] = 0; mycompile[i] = 0; myexe[i] = 0; command[i] = 0; } /* Now find the best place to create the new program. */ uid = getuid(); myuid = (unsigned int) uid; sprintf(myfile, "/run/user/%d/ecbscryptog.c", myuid); sprintf(myexe, "/run/user/%d/ecbscryptog", myuid); sprintf(mycompile, "gcc -o %s -O3 %s", myexe, myfile); errno = 0; OUT = fopen(myfile, "w"); if (errno) { sprintf(myfile, "/dev/shm/ecbscryptog.c"); sprintf(myexe, "/dev/shm/ecbscryptog"); sprintf(mycompile, "gcc -o %s -O3 %s", myexe, myfile); errno = 0; OUT = fopen(myfile, "w"); if (errno) { sprintf(myfile, "ecbscryptog.c"); sprintf(myexe, "ecbscryptog"); sprintf(mycompile, "gcc -o %s -O3 %s", myexe, myfile); errno = 0; OUT = fopen(myfile, "w"); if (errno) { printf("Can't open %s for writing.\n", myfile); exit(0); } } } /* * Ok, we are using the user seed encrypted nonces to reseed the PRNG * and now we are using that encrypted nonce state to create the new * program. The original plaintext nonces are written to the output * file already. */ create(myfile); /* Create the commands and execute them. */ chmod(myfile, 384); system(mycompile); /*printf("%s\n", mycompile);*/ chmod(myexe, 448); sprintf(command, "%s", myexe); ecbs64setsize(MAXLEN-1); tmp = (ecbs64() & 1048575); tmp += 1048576; /* * These are really important. They mess up the whole thing. The adders * are the one thing we never mess with except for things like this. * We step ahead some PRNG number of times and reset the adders. Even * though the seed to give the generated program is part of the user * seed extension, it's not the same seed the user initially provided. * This puts us somewhere hard to guess. */ adder1b = ecbs64() ^ ecbs64(); adder2b = ecbs64() ^ ecbs64(); adder3b = ecbs64() ^ ecbs64(); adder4b = ecbs64() ^ ecbs64(); adder1 = adder1b; adder2 = adder2b; adder3 = adder3b; adder4 = adder4b; for (i=0; i= lfsralen) { noncebuffer[2] = fencrypt(noncebuffer[2]); swapa = (swapa + noncebuffer[2]) & x; } while (swapb >= lfsralen) { noncebuffer[3] = fencrypt(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; fclose(INP); fclose(OUT); /*dumpstateerr();*/ for (i=0; i<1024; i++) { myfile[i] = 0; mycompile[i] = 0; myexe[i] = 0; command[i] = 0; } uid = getuid(); myuid = (unsigned int) uid; sprintf(myfile, "/run/user/%d/ecbscryptog.c", myuid); sprintf(myexe, "/run/user/%d/ecbscryptog", myuid); sprintf(mycompile, "gcc -o %s -O3 %s", myexe, myfile); errno = 0; OUT = fopen(myfile, "w"); if (errno) { sprintf(myfile, "/dev/shm/ecbscryptog.c"); sprintf(myexe, "/dev/shm/ecbscryptog"); sprintf(mycompile, "gcc -o %s -O3 %s", myexe, myfile); errno = 0; OUT = fopen(myfile, "w"); if (errno) { sprintf(myfile, "ecbscryptog.c"); sprintf(myexe, "ecbscryptog"); sprintf(mycompile, "gcc -o %s -O3 %s", myexe, myfile); errno = 0; OUT = fopen(myfile, "w"); if (errno) { printf("Can't open %s for writing.\n", myfile); exit(0); } } } create(myfile); chmod(myfile, 384); system(mycompile); /*printf("%s\n", mycompile);*/ chmod(myexe, 448); /*printf("%s\n", command);*/ sprintf(command, "%s", myexe); ecbs64setsize(MAXLEN-1); tmp = (ecbs64() & 1048575); tmp += 1048576; /* * These are really important. They mess up the whole thing. The adders * are the one thing we never mess with except for things like this. * We step ahead some PRNG number of times and reset the adders. Even * though the seed to give the generated program is part of the user * seed extension, it's not the same seed the user initially provided. * This puts us somewhere hard to guess. */ adder1b = ecbs64() ^ ecbs64(); adder2b = ecbs64() ^ ecbs64(); adder3b = ecbs64() ^ ecbs64(); adder4b = ecbs64() ^ ecbs64(); adder1 = adder1b; adder2 = adder2b; adder3 = adder3b; adder4 = adder4b; for (i=0; i MINLEN) && (thenewsize < MAXLEN)) { newsize = thenewsize; busy = 1; /* Now we assign the taps array their index values to be shuffled */ for (i=0; i= newsize */ x = 1; while (x <= (newsize)) { x <<= 1; } x -= 1; /* Now swap the tmp taps array for a few cycles */ /* We are still using the previous lfsra and taps and adders */ 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; } /* We will start using the new taps right now. */ 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; /* * All the lfsr elements are still the same, but the taps are changed * and the lfsr length is changed. Now we cycle using the new taps, and * thus changing the lfsr elements. If we later resize to a larger size * those extra elements will still be whatever they were when we last * used them. */ 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]; /* * Thought about running a few times around the lfsr elements here, * but I think what happens above is good enough really. */ busy = 0; } /* fprintf(stderr, "SETSIZE RETURNING lfsralen %d\n", lfsralen); */ } /* END ecbs64setsize */ /* * This is the main PRNG. It requires the adders to work, but even so * may run into short periods. Short is relative. I don't know * how short they might be because I can't find them in a reasonable * time. But I strongly suspect they exist. But regardless, the * adders guarantee minimum 2**32 period because they essentially * amount to stepping into a different cycle each time. So if you * do hit a short cyle, you'll most likely be out of it on the next * call. If not, probably the next one, but in any case, sooner or * later, and thats not more than a few calls at most. */ 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; } } } lfsra[tapa2] += adder1; lfsra[tapa3] += adder2; lfsra[tapa6] += adder3; lfsra[tapa7] += adder4; lfsra[tapa1] = ((lfsra[tapa1] ^ (lfsra[tapa2] * (lfsra[tapa3]|1))) + lfsra[tapa4]); --shift; if (shift == 0) { shift = (lfsra[1] & 63); if (shift == 0) { shift = 63; } } lfsra[tapa1] = ((lfsra[tapa1] >> shift) | (lfsra[tapa1] << (64-shift))); swap = (lfsra[tapa2] ^ 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; } lfsra[tapa5] = ((lfsra[tapa5] ^ (lfsra[tapa6] * (lfsra[tapa7]|1))) + lfsra[tapa8]); --shift; if (shift == 0) { shift = (lfsra[9] & 63); if (shift == 0) { shift = 63; } } lfsra[tapa5] = ((lfsra[tapa5] >> shift) | (lfsra[tapa5] << (64-shift))); if ((lfsra[tapa2] & 16777215LLU) == 734551LLU) { setsize = ( lfsra[tapa8] & (MAXLEN-1) ); setsize |= (MAXLEN/2); ecbs64setsize(setsize); } return(lfsra[tapa2] ^ lfsra[tapa6]); } /* END ecbs64 */ uint64_t fencrypt(long long unsigned int plaintext) { uint64_t rnum; uint32_t random32[1024]; uint32_t right, left, tmp; int i, j; for (i=0; i<(rounds*4); i+=2) { rnum = ecbs64(); random32[i] = (uint32_t) rnum & (4294967295LLU); rnum >>= 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); } /* * This is where we output a new program to compile and run. It's pretty * easy to read the fprintfs and see the underlying code, but for debugging * you have to leave the generated file and look at it to see the error * and then find the place in the fprintf's. It's really hard to get it * right the first time around. * * We first calculate a bunch of variables that we will use to fill * in the blanks when we get to that point in the file. We need to * generate many different variables for the taps to use in each position, * the operations to use, and for the formula lines, there is a multiplication * that has to be separately parenthesized to AND with 1. For paranthesis, * i just figured out five possibilities and put them in a switch to * select and print out that format with those parthensis and the chosen * tap values and operations. For somth things For the reuse taps that * are also updated by adders and used for the taps swap and shift updates, * I have to use a list so I dont' reuse the same taps twice. Also we have * to use all the taps, but we need two more than we have so two of them * have to used twice outside the formula lines, and tapa1 and tapa5 * can't be used for anything other than the formula lines. So this required * a little bit of manipulation. */ int create(char *myfile) { FILE *CRYPTO; char addertaps[8][16]; char formtaps[8][16]; /* tapa1 */ int tapsindex[8]; int formtapsindex[8]; char ops[4]; int opsindex[4]; int tmp1, tmp2, i, swap; int choice; CRYPTO = fopen(myfile, "w"); if (errno != 0) { fclose(INP); fclose(OUT); printf("I couldn't open myfile for writing. Exiting now.\n"); exit(0); } /* Just create the basic variable names here for when we need to print them */ /* These are for the formula lines. */ memccpy(formtaps[0], "lfsra[tapa1]", 0, 12); memccpy(formtaps[1], "lfsra[tapa2]", 0, 12); memccpy(formtaps[2], "lfsra[tapa3]", 0, 12); memccpy(formtaps[3], "lfsra[tapa4]", 0, 12); memccpy(formtaps[4], "lfsra[tapa5]", 0, 12); memccpy(formtaps[5], "lfsra[tapa6]", 0, 12); memccpy(formtaps[6], "lfsra[tapa7]", 0, 12); memccpy(formtaps[7], "lfsra[tapa8]", 0, 12); /* * These are for everything else other than formula lines. I named them * addertaos because thats the first thing they are used for. This list * excludes tapa1 and tapa5. */ memccpy(addertaps[0], "lfsra[tapa2]", 0, 12); memccpy(addertaps[1], "lfsra[tapa3]", 0, 12); memccpy(addertaps[2], "lfsra[tapa4]", 0, 12); memccpy(addertaps[3], "lfsra[tapa6]", 0, 12); memccpy(addertaps[4], "lfsra[tapa7]", 0, 12); memccpy(addertaps[5], "lfsra[tapa8]", 0, 12); /* * I have 6 available taps. I need 8, so I have to reuse two of them. * Select them randomly from the first 6 in the list and add them to * the end of the list. The list goes from 0 - 7 but we only filled * in 0 - 5 above. Now I select two from the first 6 and just add * them to the last two slots, making sure they are not the same * tap. */ tmp1 = ecbs64() & 7; while (tmp1 > 5) { tmp1 = ecbs64() & 7; } memccpy(addertaps[6], addertaps[tmp1], 0, 12); tmp2 = ecbs64() & 7; while ((tmp2 > 5) || (tmp2 == tmp1)) { tmp2 = ecbs64() & 7; } memccpy(addertaps[7], addertaps[tmp2], 0, 12); /* Make sure they are all zero terminated */ for (i=0; i<8; i++) { addertaps[i][12] = 0; addertaps[i][13] = 0; tapsindex[i] = i; } /* Now swap the tapsindex around to get them all mixed up */ for (i=7; i>1; i--) { swap = ecbs64() & 7; while (swap >= i) { swap = ecbs64() & 7; } tmp1 = tapsindex[i]; tapsindex[i] = tapsindex[swap]; tapsindex[swap] = tmp1; } tmp1 = tapsindex[1]; tapsindex[1] = tapsindex[0]; tapsindex[0] = tmp1; /* Same thing here, just smush it around a bit. */ for (i=0; i<8; i++) { formtaps[i][12] = 0; formtapsindex[i] = i; } for (i=3; i>1; i--) { swap = ecbs64() & 7; while (swap >= i) { swap = ecbs64() & 7; } tmp1 = formtapsindex[i]; formtapsindex[i] = formtapsindex[swap]; formtapsindex[swap] = tmp1; } tmp1 = formtapsindex[1]; formtapsindex[1] = formtapsindex[0]; formtapsindex[0] = tmp1; /* * We have to do them seperately, first formula line above * and second one below. */ for (i=7; i>4; i--) { swap = ecbs64() & 7; while ((swap >= i) || (swap <= 3)) { swap = ecbs64() & 7; } tmp1 = formtapsindex[i]; formtapsindex[i] = formtapsindex[swap]; formtapsindex[swap] = tmp1; } tmp1 = formtapsindex[5]; formtapsindex[5] = formtapsindex[4]; formtapsindex[4] = tmp1; /* for (i=0; i<8; i++) { printf("%s\n", formtaps[formtapsindex[i]]); } printf("\n"); */ /* Leaves ops[3] untouched so use ops 3 - 1, in any order. */ ops[0] = '^'; ops[1] = '+'; ops[2] = '-'; ops[3] = '^'; for (i=0; i<4; i++) { opsindex[i] = ecbs64() & 3; } /* * These will update the feistel cipher to insert feedback into * ecbs64 lfsr elements. These are just integers that will specify * which elements to be used for feedback in the ENCRYPT and DECRYPT * sections. The AND chops off the numbers so that they will always * range from 0 to MINLEN - 1, which is 2 less than the actual * minimum lfsra length. This makes sure that the feedback is always * used regardless what the lfsr length is set to. */ int feedback1 = ecbs64() & (MINLEN-1); int feedback2 = ecbs64() & (MINLEN-1); int feedback3 = ecbs64() & (MINLEN-1); fprintf(CRYPTO, "#define _GNU_SOURCE\n"); fprintf(CRYPTO, "#include \n"); fprintf(CRYPTO, "#include \n"); fprintf(CRYPTO, "#include \n"); fprintf(CRYPTO, "#include \n"); fprintf(CRYPTO, "#include \n"); fprintf(CRYPTO, "#include \n"); fprintf(CRYPTO, "#include \n"); fprintf(CRYPTO, "#include \n"); fprintf(CRYPTO, "#include \n"); fprintf(CRYPTO, "#include \n"); fprintf(CRYPTO, "#include \n"); fprintf(CRYPTO, "#include \n"); fprintf(CRYPTO, "/* Not required, optimizes x86-64 ASM */\n"); fprintf(CRYPTO, "#include \n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "#define MAXINP 65536\n"); fprintf(CRYPTO, "#define MAXOUT 65536\n"); fprintf(CRYPTO, "#define MAXLEN 128 \n"); fprintf(CRYPTO, "#define MINLEN 32 \n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "void signal_handler(int signo);\n"); fprintf(CRYPTO, "void ecbs64setsize(unsigned char thenewsize);\n"); fprintf(CRYPTO, "unsigned long long int ecbs64 (void);\n"); fprintf(CRYPTO, "void savestate(void);\n"); fprintf(CRYPTO, "void restorestate(void);\n"); fprintf(CRYPTO, "uint64_t fdecrypt(long long unsigned int plaintext);\n"); fprintf(CRYPTO, "uint64_t fencrypt(long long unsigned int plaintext);\n"); fprintf(CRYPTO, "int readstate(void);\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "unsigned long long int adder1 = 0;\n"); fprintf(CRYPTO, "unsigned long long int adder2 = 0;\n"); fprintf(CRYPTO, "unsigned long long int adder3 = 0;\n"); fprintf(CRYPTO, "unsigned long long int adder4 = 0;\n"); fprintf(CRYPTO, "unsigned long long int adder1b = 0;\n"); fprintf(CRYPTO, "unsigned long long int adder2b = 0;\n"); fprintf(CRYPTO, "unsigned long long int adder3b = 0;\n"); fprintf(CRYPTO, "unsigned long long int adder4b = 0;\n"); fprintf(CRYPTO, "unsigned char lfsralen = MINLEN+1;\n"); fprintf(CRYPTO, "unsigned char lfsrblen = MINLEN+1;\n"); fprintf(CRYPTO, "unsigned char shift = 63;\n"); fprintf(CRYPTO, "unsigned char shiftb = 63;\n"); fprintf(CRYPTO, "unsigned char maxtap = MINLEN;\n"); fprintf(CRYPTO, "unsigned long long int lfsra[MAXLEN];\n"); fprintf(CRYPTO, "unsigned long long int lfsrb[MAXLEN];\n"); fprintf(CRYPTO, "unsigned char tapa1 = 0;\n"); fprintf(CRYPTO, "unsigned char tapa2 = 1;\n"); fprintf(CRYPTO, "unsigned char tapa4 = 2;\n"); fprintf(CRYPTO, "unsigned char tapa3 = 3;\n"); fprintf(CRYPTO, "unsigned char tapa5 = 4;\n"); fprintf(CRYPTO, "unsigned char tapa6 = 5;\n"); fprintf(CRYPTO, "unsigned char tapa7 = 6;\n"); fprintf(CRYPTO, "unsigned char tapa8 = 7;\n"); fprintf(CRYPTO, "unsigned char tapb1 = 0;\n"); fprintf(CRYPTO, "unsigned char tapb2 = 1;\n"); fprintf(CRYPTO, "unsigned char tapb4 = 2;\n"); fprintf(CRYPTO, "unsigned char tapb3 = 3;\n"); fprintf(CRYPTO, "unsigned char tapb5 = 4;\n"); fprintf(CRYPTO, "unsigned char tapb6 = 5;\n"); fprintf(CRYPTO, "unsigned char tapb7 = 6;\n"); fprintf(CRYPTO, "unsigned char tapb8 = 7;\n"); fprintf(CRYPTO, "unsigned char taps[MAXLEN];\n"); fprintf(CRYPTO, "int rounds = 4;\n"); fprintf(CRYPTO, "unsigned char sindex = 0;\n"); fprintf(CRYPTO, "unsigned int setsize = 0;\n"); fprintf(CRYPTO, "unsigned char busy = 0;\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "key_t key = 0;\n"); fprintf(CRYPTO, "int shmid;\n"); fprintf(CRYPTO, "char *str;\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "int32_t dumpstateerr (void); /* Dumps full or partial state to STDERR */\n"); fprintf(CRYPTO, "unsigned int totalseedchars; /* How much seed data we got in bytes */\n"); fprintf(CRYPTO, "unsigned int dump = 0; /* Dump level, 0 is minimal. */\n"); fprintf(CRYPTO, "unsigned char ENCRYPT = 0; /* Encrypt data flag, needs to read stdin */\n"); fprintf(CRYPTO, "unsigned char DECRYPT = 0; /* Decrypt data flag, requires stdin */\n"); fprintf(CRYPTO, "char infile[1024]; /* The file to be encrypted or decrypted */\n"); fprintf(CRYPTO, "char outfile[1024]; /* The encrypted or decrypted output file */\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "/***************************************************************************/\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "int32_t main(int32_t argc, char ** argv) {\n"); fprintf(CRYPTO, "int32_t i = 0;\n"); /*printf("int32_t j = 0;\n");*/ fprintf(CRYPTO, "int32_t readcount = 0;\n"); fprintf(CRYPTO, "long long unsigned int lastreadcount = 0LLU;\n"); fprintf(CRYPTO, "long long unsigned int plaintext;\n"); fprintf(CRYPTO, "long long unsigned int lastplaintext;\n"); fprintf(CRYPTO, "long long unsigned int * plaintextptr;\n"); fprintf(CRYPTO, "char curargv[MAXINP];\n"); fprintf(CRYPTO, "int32_t curargc = 1;\n"); fprintf(CRYPTO, "FILE *SYSINP;\n"); fprintf(CRYPTO, "FILE *INP;\n"); fprintf(CRYPTO, "FILE *OUT;\n"); fprintf(CRYPTO, "unsigned char seedbuffer[MAXINP];\n"); fprintf(CRYPTO, "unsigned long long int outbuffer[MAXOUT];\n"); fprintf(CRYPTO, "unsigned long long int noncebuffer[8];\n"); fprintf(CRYPTO, "int readcount1;\n"); fprintf(CRYPTO, "int readcount2;\n"); fprintf(CRYPTO, "int readcount3;\n"); fprintf(CRYPTO, "unsigned char seedbuffer1[8];\n"); fprintf(CRYPTO, "unsigned char seedbuffer2[8];\n"); fprintf(CRYPTO, "unsigned char seedbuffer3[8];\n"); fprintf(CRYPTO, "char line[1024];\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " for (i=0; i 8) {\n"); fprintf(CRYPTO, " outbuffer[1] = 8;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " fwrite(outbuffer, 1, outbuffer[1], OUT);\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " return(0);\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " while (1) {\n"); fprintf(CRYPTO, " for (i=0; i MINLEN) && (thenewsize < MAXLEN)) {\n"); fprintf(CRYPTO, " newsize = thenewsize;\n"); fprintf(CRYPTO, " busy = 1;\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " for (i=0; i= newsize) {\n"); fprintf(CRYPTO, " swapa = (swapa + ecbs64()) & x;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " while (swapb >= newsize) {\n"); fprintf(CRYPTO, " swapb = (swapb + ecbs64()) & x;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " tmp = taps[swapa];\n"); fprintf(CRYPTO, " taps[swapa] = taps[swapb];\n"); fprintf(CRYPTO, " taps[swapb] = tmp;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " tapa1 = taps[0];\n"); fprintf(CRYPTO, " tapa2 = taps[1];\n"); fprintf(CRYPTO, " tapa3 = taps[2];\n"); fprintf(CRYPTO, " tapa4 = taps[3];\n"); fprintf(CRYPTO, " tapa5 = taps[4];\n"); fprintf(CRYPTO, " tapa6 = taps[5];\n"); fprintf(CRYPTO, " tapa7 = taps[6];\n"); fprintf(CRYPTO, " tapa8 = taps[7];\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " lfsralen = newsize;\n"); fprintf(CRYPTO, " maxtap = lfsralen - 1;\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " for (i=0; i<(MAXLEN+lfsralen); i++) {\n"); fprintf(CRYPTO, " swapa = ecbs64() & x;\n"); fprintf(CRYPTO, " swapb = ecbs64() & x;\n"); fprintf(CRYPTO, " while (swapa >= newsize) {\n"); fprintf(CRYPTO, " swapa = (swapa + ecbs64()) & x;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " while (swapb >= newsize) {\n"); fprintf(CRYPTO, " swapb = (swapb + ecbs64()) & x;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " tmp = taps[swapa];\n"); fprintf(CRYPTO, " taps[swapa] = taps[swapb];\n"); fprintf(CRYPTO, " taps[swapb] = tmp;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " tapa1 = taps[0];\n"); fprintf(CRYPTO, " tapa2 = taps[1];\n"); fprintf(CRYPTO, " tapa3 = taps[2];\n"); fprintf(CRYPTO, " tapa4 = taps[3];\n"); fprintf(CRYPTO, " tapa5 = taps[4];\n"); fprintf(CRYPTO, " tapa6 = taps[5];\n"); fprintf(CRYPTO, " tapa7 = taps[6];\n"); fprintf(CRYPTO, " tapa8 = taps[7];\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " busy = 0;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "} /* END ecbs64setsize */\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "unsigned long long int ecbs64 (void) {\n"); fprintf(CRYPTO, "unsigned long long int swap;\n"); fprintf(CRYPTO, "unsigned long long int tmp;\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " --tapa1;\n"); fprintf(CRYPTO, " if (tapa1 > maxtap) {\n"); fprintf(CRYPTO, " tapa1 = maxtap;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " --tapa2;\n"); fprintf(CRYPTO, " if (tapa2 > maxtap) {\n"); fprintf(CRYPTO, " tapa2 = maxtap;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " --tapa3;\n"); fprintf(CRYPTO, " if (tapa3 > maxtap) {\n"); fprintf(CRYPTO, " tapa3 = maxtap;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " --tapa4;\n"); fprintf(CRYPTO, " if (tapa4 > maxtap) {\n"); fprintf(CRYPTO, " tapa4 = maxtap;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " --tapa5;\n"); fprintf(CRYPTO, " if (tapa5 > maxtap) {\n"); fprintf(CRYPTO, " tapa5 = maxtap;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " --tapa6;\n"); fprintf(CRYPTO, " if (tapa6 > maxtap) {\n"); fprintf(CRYPTO, " tapa6 = maxtap;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " --tapa7;\n"); fprintf(CRYPTO, " if (tapa7 > maxtap) {\n"); fprintf(CRYPTO, " tapa7 = maxtap;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " --tapa8;\n"); fprintf(CRYPTO, " if (tapa8 > maxtap) {\n"); fprintf(CRYPTO, " tapa8 = maxtap;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " ++adder1;\n"); fprintf(CRYPTO, " if (adder1 == 0) {\n"); fprintf(CRYPTO, " ++adder2;\n"); fprintf(CRYPTO, " if (adder2 == 0) {\n"); fprintf(CRYPTO, " ++adder3;\n"); fprintf(CRYPTO, " if (adder3 == 0) {\n"); fprintf(CRYPTO, " ++adder4;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "/* # 1 Select 4 most unused taps and operations */\n"); fprintf(CRYPTO, "\n"); /* # 1 */ tmp1 = ecbs64() & 3; fprintf(CRYPTO, " %s %c= adder1;\n", addertaps[tapsindex[0]], ops[tmp1]); tmp1 = ecbs64() & 3; fprintf(CRYPTO, " %s %c= adder2;\n", addertaps[tapsindex[1]], ops[tmp1]); tmp1 = ecbs64() & 3; fprintf(CRYPTO, " %s %c= adder3;\n", addertaps[tapsindex[2]], ops[tmp1]); tmp1 = ecbs64() & 3; fprintf(CRYPTO, " %s %c= adder4;\n", addertaps[tapsindex[3]], ops[tmp1]); /* printf(" lfsra[tapa2] += adder1;\n"); printf(" lfsra[tapa3] += adder2;\n"); printf(" lfsra[tapa6] += adder3;\n"); printf(" lfsra[tapa7] += adder4;\n"); */ fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "/* # 2 select taps 1-4, unique ops including * and parenthesis */\n"); /* Leaves ops[3] untouched so use ops 3 - 1, in any order. */ ops[0] = '*'; ops[1] = '^'; if (ecbs64() & 1) { ops[2] = '+'; } else { ops[2] = '-'; } for (i=0; i<3; i++) { opsindex[i] = i; } /* first scramble the first 3 not including the last element */ for (i=2; i>1; i--) { swap = ecbs64() & 3; while (swap >= i) { swap = ecbs64() & 3; } tmp1 = opsindex[i]; opsindex[i] = opsindex[swap]; opsindex[swap] = tmp1; } tmp1 = opsindex[1]; opsindex[1] = opsindex[0]; opsindex[0] = tmp1; choice = ecbs64() & 7; while (choice > 4) { choice = ecbs64() & 7; } /* # 2 */ if (ops[opsindex[0]] == '*') { switch (choice) { case 0: fprintf(CRYPTO, " lfsra[tapa1] = ((%s %c (%s|1)) %c (%s %c %s));\n", formtaps[formtapsindex[0]], ops[opsindex[0]], formtaps[formtapsindex[1]], ops[opsindex[1]], formtaps[formtapsindex[2]], ops[opsindex[2]], formtaps[formtapsindex[3]]); break; case 1: fprintf(CRYPTO, " lfsra[tapa1] = ((%s|1) %c ((%s %c %s) %c %s));\n", formtaps[formtapsindex[0]], ops[opsindex[0]], formtaps[formtapsindex[1]], ops[opsindex[1]], formtaps[formtapsindex[2]], ops[opsindex[2]], formtaps[formtapsindex[3]]); break; case 2: fprintf(CRYPTO, " lfsra[tapa1] = (((%s|1) %c (%s %c %s)) %c %s);\n", formtaps[formtapsindex[0]], ops[opsindex[0]], formtaps[formtapsindex[1]], ops[opsindex[1]], formtaps[formtapsindex[2]], ops[opsindex[2]], formtaps[formtapsindex[3]]); break; case 3: fprintf(CRYPTO, " lfsra[tapa1] = ((%s|1) %c (%s %c (%s %c %s)));\n", formtaps[formtapsindex[0]], ops[opsindex[0]], formtaps[formtapsindex[1]], ops[opsindex[1]], formtaps[formtapsindex[2]], ops[opsindex[2]], formtaps[formtapsindex[3]]); break; case 4: fprintf(CRYPTO, " lfsra[tapa1] = (((%s %c (%s|1)) %c %s) %c %s);\n", formtaps[formtapsindex[0]], ops[opsindex[0]], formtaps[formtapsindex[1]], ops[opsindex[1]], formtaps[formtapsindex[2]], ops[opsindex[2]], formtaps[formtapsindex[3]]); break; default: break; } } if (ops[opsindex[1]] == '*') { switch (choice) { case 0: fprintf(CRYPTO, " lfsra[tapa1] = ((%s %c %s) %c ((%s %c %s)|1));\n", formtaps[formtapsindex[0]], ops[opsindex[0]], formtaps[formtapsindex[1]], ops[opsindex[1]], formtaps[formtapsindex[2]], ops[opsindex[2]], formtaps[formtapsindex[3]]); break; case 1: fprintf(CRYPTO, " lfsra[tapa1] = (%s %c ((%s %c (%s|1)) %c %s));\n", formtaps[formtapsindex[0]], ops[opsindex[0]], formtaps[formtapsindex[1]], ops[opsindex[1]], formtaps[formtapsindex[2]], ops[opsindex[2]], formtaps[formtapsindex[3]]); break; case 2: fprintf(CRYPTO, " lfsra[tapa1] = ((%s %c (%s %c (%s|1))) %c %s);\n", formtaps[formtapsindex[0]], ops[opsindex[0]], formtaps[formtapsindex[1]], ops[opsindex[1]], formtaps[formtapsindex[2]], ops[opsindex[2]], formtaps[formtapsindex[3]]); break; case 3: fprintf(CRYPTO, " lfsra[tapa1] = (%s %c ((%s|1) %c (%s %c %s)));\n", formtaps[formtapsindex[0]], ops[opsindex[0]], formtaps[formtapsindex[1]], ops[opsindex[1]], formtaps[formtapsindex[2]], ops[opsindex[2]], formtaps[formtapsindex[3]]); break; case 4: fprintf(CRYPTO, " lfsra[tapa1] = (((%s %c %s) %c (%s|1)) %c %s);\n", formtaps[formtapsindex[0]], ops[opsindex[0]], formtaps[formtapsindex[1]], ops[opsindex[1]], formtaps[formtapsindex[2]], ops[opsindex[2]], formtaps[formtapsindex[3]]); break; default: break; } } if (ops[opsindex[2]] == '*') { switch (choice) { case 0: fprintf(CRYPTO, " lfsra[tapa1] = ((%s %c %s) %c (%s %c (%s|1)));\n", formtaps[formtapsindex[0]], ops[opsindex[0]], formtaps[formtapsindex[1]], ops[opsindex[1]], formtaps[formtapsindex[2]], ops[opsindex[2]], formtaps[formtapsindex[3]]); break; case 1: fprintf(CRYPTO, " lfsra[tapa1] = (%s %c ((%s %c %s) %c (%s|1)));\n", formtaps[formtapsindex[0]], ops[opsindex[0]], formtaps[formtapsindex[1]], ops[opsindex[1]], formtaps[formtapsindex[2]], ops[opsindex[2]], formtaps[formtapsindex[3]]); break; case 2: fprintf(CRYPTO, " lfsra[tapa1] = ((%s %c (%s %c %s)) %c (%s|1));\n", formtaps[formtapsindex[0]], ops[opsindex[0]], formtaps[formtapsindex[1]], ops[opsindex[1]], formtaps[formtapsindex[2]], ops[opsindex[2]], formtaps[formtapsindex[3]]); break; case 3: fprintf(CRYPTO, " lfsra[tapa1] = (%s %c (%s %c (%s %c (%s|1))));\n", formtaps[formtapsindex[0]], ops[opsindex[0]], formtaps[formtapsindex[1]], ops[opsindex[1]], formtaps[formtapsindex[2]], ops[opsindex[2]], formtaps[formtapsindex[3]]); break; case 4: fprintf(CRYPTO, " lfsra[tapa1] = (((%s %c %s) %c %s) %c (%s|1));\n", formtaps[formtapsindex[0]], ops[opsindex[0]], formtaps[formtapsindex[1]], ops[opsindex[1]], formtaps[formtapsindex[2]], ops[opsindex[2]], formtaps[formtapsindex[3]]); break; default: break; } } /* printf(" lfsra[tapa1] = ((lfsra[tapa1] ^ (lfsra[tapa2] * (lfsra[tapa3]|1))) + lfsra[tapa4]);\n"); */ choice = ecbs64() & 63; fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " --shift;\n"); fprintf(CRYPTO, " if (shift == 0) {\n"); fprintf(CRYPTO, " shift = (lfsra[%d] & 63);\n", choice); fprintf(CRYPTO, " if (shift == 0) {\n"); fprintf(CRYPTO, " shift = 63;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " lfsra[tapa1] = ((lfsra[tapa1] >> shift) | (lfsra[tapa1] << (64-shift)));\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "/* # 3 select two most unused taps and operation 6 * 3 = 18 */\n"); /* # 3 */ fprintf(CRYPTO, " swap = (%s ^ %s) & 7;\n", addertaps[tapsindex[4]], addertaps[tapsindex[5]]); /* printf(" swap = (lfsra[tapa2] ^ lfsra[tapa3]) & 7;\n"); */ fprintf(CRYPTO, " switch (swap) {\n"); fprintf(CRYPTO, " case 0: tmp = tapa1;\n"); fprintf(CRYPTO, " tapa1 = tapa2;\n"); fprintf(CRYPTO, " tapa2 = tmp;\n"); fprintf(CRYPTO, " break;\n"); fprintf(CRYPTO, " case 1: tmp = tapa2;\n"); fprintf(CRYPTO, " tapa2 = tapa3;\n"); fprintf(CRYPTO, " tapa3 = tmp;\n"); fprintf(CRYPTO, " break;\n"); fprintf(CRYPTO, " case 2: tmp = tapa3;\n"); fprintf(CRYPTO, " tapa3 = tapa4;\n"); fprintf(CRYPTO, " tapa4 = tmp;\n"); fprintf(CRYPTO, " break;\n"); fprintf(CRYPTO, " case 3: tmp = tapa4;\n"); fprintf(CRYPTO, " tapa4 = tapa5;\n"); fprintf(CRYPTO, " tapa5 = tmp;\n"); fprintf(CRYPTO, " break;\n"); fprintf(CRYPTO, " case 4: tmp = tapa5;\n"); fprintf(CRYPTO, " tapa5 = tapa6;\n"); fprintf(CRYPTO, " tapa6 = tmp;\n"); fprintf(CRYPTO, " break;\n"); fprintf(CRYPTO, " case 5: tmp = tapa6;\n"); fprintf(CRYPTO, " tapa6 = tapa7;\n"); fprintf(CRYPTO, " tapa7 = tmp;\n"); fprintf(CRYPTO, " break;\n"); fprintf(CRYPTO, " case 6: tmp = tapa7;\n"); fprintf(CRYPTO, " tapa7 = tapa8;\n"); fprintf(CRYPTO, " tapa8 = tmp;\n"); fprintf(CRYPTO, " break;\n"); fprintf(CRYPTO, " case 7: tmp = tapa8;\n"); fprintf(CRYPTO, " tapa8 = tapa1;\n"); fprintf(CRYPTO, " tapa1 = tmp;\n"); fprintf(CRYPTO, " break;\n"); fprintf(CRYPTO, " default: break;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "/* # 4 select taps 5 - 8, unique ops including * and parenthesis # 4*3*2*6*6 = 864 */\n"); /* Now scramble the first three elements which will include the * element */ for (i=2; i>1; i--) { swap = ecbs64() & 3; while (swap >= i) { swap = ecbs64() & 3; } tmp1 = opsindex[i]; opsindex[i] = opsindex[swap]; opsindex[swap] = tmp1; } tmp1 = opsindex[1]; opsindex[1] = opsindex[0]; opsindex[0] = tmp1; choice = ecbs64() & 7; while (choice > 4) { choice = ecbs64() & 7; } /* # 4 */ if (ops[opsindex[0]] == '*') { switch (choice) { case 0: fprintf(CRYPTO, " lfsra[tapa5] = ((%s %c (%s|1)) %c (%s %c %s));\n", formtaps[formtapsindex[4]], ops[opsindex[0]], formtaps[formtapsindex[5]], ops[opsindex[1]], formtaps[formtapsindex[6]], ops[opsindex[2]], formtaps[formtapsindex[7]]); break; case 1: fprintf(CRYPTO, " lfsra[tapa5] = ((%s|1) %c ((%s %c %s) %c %s));\n", formtaps[formtapsindex[4]], ops[opsindex[0]], formtaps[formtapsindex[5]], ops[opsindex[1]], formtaps[formtapsindex[6]], ops[opsindex[2]], formtaps[formtapsindex[7]]); break; case 2: fprintf(CRYPTO, " lfsra[tapa5] = (((%s|1) %c (%s %c %s)) %c %s);\n", formtaps[formtapsindex[4]], ops[opsindex[0]], formtaps[formtapsindex[5]], ops[opsindex[1]], formtaps[formtapsindex[6]], ops[opsindex[2]], formtaps[formtapsindex[7]]); break; case 3: fprintf(CRYPTO, " lfsra[tapa5] = ((%s|1) %c (%s %c (%s %c %s)));\n", formtaps[formtapsindex[4]], ops[opsindex[0]], formtaps[formtapsindex[5]], ops[opsindex[1]], formtaps[formtapsindex[6]], ops[opsindex[2]], formtaps[formtapsindex[7]]); break; case 4: fprintf(CRYPTO, " lfsra[tapa5] = (((%s %c (%s|1)) %c %s) %c %s);\n", formtaps[formtapsindex[4]], ops[opsindex[0]], formtaps[formtapsindex[5]], ops[opsindex[1]], formtaps[formtapsindex[6]], ops[opsindex[2]], formtaps[formtapsindex[7]]); break; default: break; } } if (ops[opsindex[1]] == '*') { switch (choice) { case 0: fprintf(CRYPTO, " lfsra[tapa5] = ((%s %c %s) %c ((%s %c %s)|1));\n", formtaps[formtapsindex[4]], ops[opsindex[0]], formtaps[formtapsindex[5]], ops[opsindex[1]], formtaps[formtapsindex[6]], ops[opsindex[2]], formtaps[formtapsindex[7]]); break; case 1: fprintf(CRYPTO, " lfsra[tapa5] = (%s %c ((%s %c (%s|1)) %c %s));\n", formtaps[formtapsindex[4]], ops[opsindex[0]], formtaps[formtapsindex[5]], ops[opsindex[1]], formtaps[formtapsindex[6]], ops[opsindex[2]], formtaps[formtapsindex[7]]); break; case 2: fprintf(CRYPTO, " lfsra[tapa5] = ((%s %c (%s %c (%s|1))) %c %s);\n", formtaps[formtapsindex[4]], ops[opsindex[0]], formtaps[formtapsindex[5]], ops[opsindex[1]], formtaps[formtapsindex[6]], ops[opsindex[2]], formtaps[formtapsindex[7]]); break; case 3: fprintf(CRYPTO, " lfsra[tapa5] = (%s %c ((%s|1) %c (%s %c %s)));\n", formtaps[formtapsindex[4]], ops[opsindex[0]], formtaps[formtapsindex[5]], ops[opsindex[1]], formtaps[formtapsindex[6]], ops[opsindex[2]], formtaps[formtapsindex[7]]); break; case 4: fprintf(CRYPTO, " lfsra[tapa5] = (((%s %c %s) %c (%s|1)) %c %s);\n", formtaps[formtapsindex[4]], ops[opsindex[0]], formtaps[formtapsindex[5]], ops[opsindex[1]], formtaps[formtapsindex[6]], ops[opsindex[2]], formtaps[formtapsindex[7]]); break; default: break; } } if (ops[opsindex[2]] == '*') { switch (choice) { case 0: fprintf(CRYPTO, " lfsra[tapa5] = ((%s %c %s) %c (%s %c (%s|1)));\n", formtaps[formtapsindex[4]], ops[opsindex[0]], formtaps[formtapsindex[5]], ops[opsindex[1]], formtaps[formtapsindex[6]], ops[opsindex[2]], formtaps[formtapsindex[7]]); break; case 1: fprintf(CRYPTO, " lfsra[tapa5] = (%s %c ((%s %c %s) %c (%s|1)));\n", formtaps[formtapsindex[4]], ops[opsindex[0]], formtaps[formtapsindex[5]], ops[opsindex[1]], formtaps[formtapsindex[6]], ops[opsindex[2]], formtaps[formtapsindex[7]]); break; case 2: fprintf(CRYPTO, " lfsra[tapa5] = ((%s %c (%s %c %s)) %c (%s|1));\n", formtaps[formtapsindex[4]], ops[opsindex[0]], formtaps[formtapsindex[5]], ops[opsindex[1]], formtaps[formtapsindex[6]], ops[opsindex[2]], formtaps[formtapsindex[7]]); break; case 3: fprintf(CRYPTO, " lfsra[tapa5] = (%s %c (%s %c (%s %c (%s|1))));\n", formtaps[formtapsindex[4]], ops[opsindex[0]], formtaps[formtapsindex[5]], ops[opsindex[1]], formtaps[formtapsindex[6]], ops[opsindex[2]], formtaps[formtapsindex[7]]); break; case 4: fprintf(CRYPTO, " lfsra[tapa5] = (((%s %c %s) %c %s) %c (%s|1));\n", formtaps[formtapsindex[4]], ops[opsindex[0]], formtaps[formtapsindex[5]], ops[opsindex[1]], formtaps[formtapsindex[6]], ops[opsindex[2]], formtaps[formtapsindex[7]]); break; default: break; } } /* printf(" lfsra[tapa5] = ((lfsra[tapa5] ^ (lfsra[tapa6] * (lfsra[tapa7]|1))) + lfsra[tapa8]);\n"); */ choice = ecbs64() & 63; fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " --shift;\n"); fprintf(CRYPTO, " if (shift == 0) {\n"); fprintf(CRYPTO, " shift = (lfsra[%d] & 63);\n", choice); fprintf(CRYPTO, " if (shift == 0) {\n"); fprintf(CRYPTO, " shift = 63;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " lfsra[tapa5] = ((lfsra[tapa5] >> shift) | (lfsra[tapa5] << (64-shift)));\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "/* # 5 select one most unused tap and number from 0 to 1048575 # 6 * 1048576 */\n"); /* # 5 */ tmp1 = ecbs64() & 1048575; fprintf(CRYPTO, " if ((%s & 1048575LLU) == %uLLU) {\n", addertaps[tapsindex[6]], tmp1); /* printf(" if ((lfsra[tapa2] & 16777215LLU) == 734551LLU) {\n"); */ fprintf(CRYPTO, "/* # 6 select one most unused tap 6 */\n"); /* # 6 */ fprintf(CRYPTO, " setsize = ( %s & (MAXLEN-1) );\n", addertaps[tapsindex[7]]); /* printf(" setsize = ( lfsra[tapa8] & (MAXLEN-1) );\n"); */ fprintf(CRYPTO, " setsize |= (MAXLEN/2);\n"); fprintf(CRYPTO, " ecbs64setsize(setsize);\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " return(lfsra[tapa2] ^ lfsra[tapa6]);\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "} /* END ecbs64 */\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "void savestate(void) {\n"); fprintf(CRYPTO, "int i;\n"); fprintf(CRYPTO, " lfsrblen = lfsralen;\n"); fprintf(CRYPTO, " for (i=0; i>= 32;\n"); fprintf(CRYPTO, " random32[i+1] = (uint32_t) rnum & (4294967295LLU);\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " i = 0;\n"); fprintf(CRYPTO, " right = (uint32_t) (plaintext & 4294967295LLU);\n"); fprintf(CRYPTO, " plaintext >>= 32;\n"); fprintf(CRYPTO, " left = (uint32_t) (plaintext & 4294967295LLU);\n"); fprintf(CRYPTO, " for (j=0; j>= 32;\n"); fprintf(CRYPTO, " random32[i+1] = (uint32_t) rnum & (4294967295LLU);\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " i = (rounds * 4) - 1;\n"); fprintf(CRYPTO, " right = (uint32_t) (plaintext & 4294967295LLU);\n"); fprintf(CRYPTO, " plaintext >>= 32;\n"); fprintf(CRYPTO, " left = (uint32_t) (plaintext & 4294967295LLU);\n"); fprintf(CRYPTO, " for (j=(rounds-1); j>=0; j--) {\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " left ^= right;\n"); fprintf(CRYPTO, " left ^= random32[i];\n"); fprintf(CRYPTO, " --i;\n"); fprintf(CRYPTO, " tmp = right;\n"); fprintf(CRYPTO, " right = left;\n"); fprintf(CRYPTO, " left = tmp;\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " left ^= right;\n"); fprintf(CRYPTO, " left += random32[i];\n"); fprintf(CRYPTO, " --i;\n"); fprintf(CRYPTO, " tmp = right;\n"); fprintf(CRYPTO, " right = left;\n"); fprintf(CRYPTO, " left = tmp;\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " left ^= right;\n"); fprintf(CRYPTO, " left ^= random32[i];\n"); fprintf(CRYPTO, " --i;\n"); fprintf(CRYPTO, " tmp = right;\n"); fprintf(CRYPTO, " right = left;\n"); fprintf(CRYPTO, " left = tmp;\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " left ^= right;\n"); fprintf(CRYPTO, " left -= random32[i];\n"); fprintf(CRYPTO, " --i;\n"); fprintf(CRYPTO, " tmp = right;\n"); fprintf(CRYPTO, " right = left;\n"); fprintf(CRYPTO, " left = tmp;\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " rnum = left;\n"); fprintf(CRYPTO, " rnum <<= 32;\n"); fprintf(CRYPTO, " rnum += right;\n"); fprintf(CRYPTO, " return(rnum);\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "}\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "int readstate() {\n"); fprintf(CRYPTO, "char direction = 0;\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "/* ftok to generate unique key */\n"); fprintf(CRYPTO, " key = ftok(\"/dev/shm/shmfile\", %d);\n", shmprojid); fprintf(CRYPTO, "/* shmget returns an identifier in shmid */\n"); fprintf(CRYPTO, " shmid = shmget(key,2048,0666|IPC_CREAT);\n"); fprintf(CRYPTO, "/* shmat to attach to shared memory */\n"); fprintf(CRYPTO, " str = (char*) shmat(shmid,(void*)0,0);\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " mempcpy( lfsra, str, 8*128);\n"); fprintf(CRYPTO, " str += 8*128;\n"); fprintf(CRYPTO, " mempcpy( &adder1,str, 8);\n"); fprintf(CRYPTO, " str += 8;\n"); fprintf(CRYPTO, " mempcpy( &adder2, str, 8);\n"); fprintf(CRYPTO, " str += 8;\n"); fprintf(CRYPTO, " mempcpy( &adder3, str, 8);\n"); fprintf(CRYPTO, " str += 8;\n"); fprintf(CRYPTO, " mempcpy( &adder4, str, 8);\n"); fprintf(CRYPTO, " str += 8;\n"); fprintf(CRYPTO, " mempcpy( &tapa1, str, 1);\n"); fprintf(CRYPTO, " str += 1;\n"); fprintf(CRYPTO, " mempcpy( &tapa2, str, 1);\n"); fprintf(CRYPTO, " str += 1;\n"); fprintf(CRYPTO, " mempcpy( &tapa3, str, 1);\n"); fprintf(CRYPTO, " str += 1;\n"); fprintf(CRYPTO, " mempcpy( &tapa4, str, 1);\n"); fprintf(CRYPTO, " str += 1;\n"); fprintf(CRYPTO, " mempcpy( &tapa5, str, 1);\n"); fprintf(CRYPTO, " str += 1;\n"); fprintf(CRYPTO, " mempcpy( &tapa6, str, 1);\n"); fprintf(CRYPTO, " str += 1;\n"); fprintf(CRYPTO, " mempcpy( &tapa7, str, 1);\n"); fprintf(CRYPTO, " str += 1;\n"); fprintf(CRYPTO, " mempcpy( &tapa8, str, 1);\n"); fprintf(CRYPTO, " str += 1;\n"); fprintf(CRYPTO, " mempcpy( &lfsralen, str, 1);\n"); fprintf(CRYPTO, " str += 1;\n"); fprintf(CRYPTO, " mempcpy( &shift, str, 1);\n"); fprintf(CRYPTO, " str += 1;\n"); fprintf(CRYPTO, " mempcpy( &direction, str, 1);\n"); fprintf(CRYPTO, " str += 1;\n"); fprintf(CRYPTO, " mempcpy( &rounds, str, 1);\n"); fprintf(CRYPTO, " str += 1;\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " if (direction == 'E') {\n"); fprintf(CRYPTO, " ENCRYPT = 1;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, " else {\n"); fprintf(CRYPTO, " DECRYPT = 1;\n"); fprintf(CRYPTO, " }\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " maxtap = lfsralen - 1;\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "int inlen;\n"); fprintf(CRYPTO, " mempcpy( &inlen, str, 1);\n"); fprintf(CRYPTO, " str += 1;\n"); fprintf(CRYPTO, " mempcpy( infile, str, inlen);\n"); fprintf(CRYPTO, " str += inlen;\n"); fprintf(CRYPTO, " infile[inlen] = 0;\n"); fprintf(CRYPTO, "int outlen;\n"); fprintf(CRYPTO, " mempcpy( &outlen, str, 1);\n"); fprintf(CRYPTO, " str += 1;\n"); fprintf(CRYPTO, " mempcpy( outfile, str, outlen);\n"); fprintf(CRYPTO, " str += outlen;\n"); fprintf(CRYPTO, " outfile[outlen] = 0;\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "/* detach from shared memory because we are done with it */\n"); fprintf(CRYPTO, " shmdt(str);\n"); fprintf(CRYPTO, "/* destroy the shared memory */\n"); fprintf(CRYPTO, " shmctl(shmid,IPC_RMID,NULL);\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, " return 0;\n"); fprintf(CRYPTO, "}\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fprintf(CRYPTO, "\n"); fclose(CRYPTO); return(0); } /* END create() */ void restorestate(void) { int i; lfsralen = lfsrblen; maxtap = lfsralen-1; for (i=0; i