Enigma/makewheel.c

From Teknologisk videncenter
Jump to: navigation, search
/**************************************************************************
  #     #
  ##   ##  ######  #####    ####     ##    #    #   #####  ######   ####
  # # # #  #       #    #  #    #   #  #   ##   #     #    #       #    #
  #  #  #  #####   #    #  #       #    #  # #  #     #    #####   #
  #     #  #       #####   #       ######  #  # #     #    #       #
  #     #  #       #   #   #    #  #    #  #   ##     #    #       #    #
  #     #  ######  #    #   ####   #    #  #    #     #    ######   ####

***************************************************************************
Author..: Henrik Thomsen heth@mercantec.dk
Company.: House of Technology at Mercantec ( http://www.mercantec.dk )
date....: 2010 Nov. 27
***************************************************************************
Abstract: Makewheel makes wheels/rotors for a byte stream crypting/
          encryption engine. Makewhell makes a C header file with
          "random" chosen wheels, reverse wheels and rotor reflector.
Purpose.: To be used for fun to challenge our students making multithreaded
          solutions to break the codes.
***************************************************************************
Cavets..: Real lousy solution generating random numbers with rand()
          Real lousy solution solving missing hits in sub rr. missing
          randomness.
          This program was written in C after years of no C-coding, so
          the generel structure is quite messy.
          It's purpose however is to challenge students so perhaps they
          will improve it.
***************************************************************************
Modification log:
***************************************************************************
License:  Free open software but WITHOUT ANY WARRANTY.
Terms..:  see http://www.gnu.org/licenses
***************************************************************************/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/timeb.h>

char *progname;

unsigned int makeseed() {
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);
        int sec = (int) ts.tv_sec;
        long nano = (int) ts.tv_nsec;
        nano = (nano*nano*nano)/sec;
        return(nano);
}
void usage( void ) {
        printf("Usage:\n%s: Number_of_wheels filename\n",progname);
        printf("\nNumber_of_wheels must be between 1 and 1.000.000\n");
        exit(1);
}

void err(char *txt, int e) {
        char *lErrString        = strerror(e);
        if (lErrString == NULL)
        {
                lErrString      = "Unknown";
        }
        fprintf(stderr,"ERROR: %s - errno %i: %s\n", txt, e, lErrString);
}




/* Make reversewhell used from reflector and back */
void reversewhell( FILE *fptmp, int *p, int curwhe, int wheels ) {
        int i,j;

        if ( curwhe == 0 ) {
                fprintf(fptmp,"\nbyte rwheel[%i][256] = {\n",wheels);
        }

        fprintf(fptmp,"/* Reverse wheel %i */",curwhe + 1);
        for (i=0; i <= 255 ; i++) {
                for (j=0; j <= 255 ; j++) {
                        if ( *(p+j) == i ) {
                                if ( i == 255 ) {
                                        if ( (curwhe + 1 ) < wheels ) {
                                                fprintf(fptmp,"%3i},\n",j);
                                        } else {
                                                fprintf(fptmp,"%3i}\n",j);
                                        }
                                } else {
                                        if ( i % 16 == 0 ) {
                                                if ( i == 0 ) {
                                                        fprintf(fptmp,"\n       {");
                                                } else {
                                                        fprintf(fptmp,"\n        ");
                                                }
                                        }
                                        fprintf(fptmp,"%3i, ",j);
                                }
                        }
                }
        }
        if ( (curwhe + 1) == wheels ) { /*End of array */
                fprintf(fptmp,"\n};\n");
        } /*else {
                fprintf(fptmp,",");
        }*/
}

void makeRandomArray(int *w, int size) {
        int i,j;
        int *p;

        p = malloc(sizeof(int) * size );
        if ( p == NULL ) {
                err("Can't allocate memory for p in makeRandomArray.",errno);
                exit(2);
        }
        /* Now to work */
        for ( i=0;i < size ; i++) {
                p[i] = rand();
        }

        /* Find the position of the biggest random number in p[]
           and make the lowest number in w[]. etc...
                After w[] array will contain all numbers from 0..255
                in random sequence
        */
        for ( i=0;i < size ; i++) {
                int big=0,nr;
                for (j=0; j < size ; j++ ) {
                        /* Sort wheel posistion and number can't be the same*/
                        if ( (p[j] > big) && (j != i) ) {
                                big = p[j];
                                nr = j;
                        }
                }
                p[nr] = 0; /* Ude af tabellen nu */
                *(w+i)=nr;

                if (i == nr ) { /* Cant be the same */
                        printf("Samme tal i samme nr %i\n",nr);
                }
        }
        free(p);
}
/* Rotor reflector is symmetrical if fx. 17 points to 87
   then 87 must point to 17 */
void rr(FILE *fpfile) {
        int r[256];
        int p[256];
        int i,j;

        /* initialize array p to -1 */
        for (i=0; i < 256; i++) { p[i] = -1; }

        /* Initialize array with random number */
        makeRandomArray(&r[0],256);

        for (i=0; i < 256; i++) {
                if ( p[i] == -1 ) {
                        if ( p[r[i]] == -1 ) {
                                p[i] = r[i];
                                p[r[i]] = i;
                        }
                }
        }
        /* Find remaing and pair them. Has to be even number */
        for (i=0; i < 256; i++) {
                if ( p[i] == -1 ) {
                        for (j=i+1; (j < 256) && (p[j] != -1); j++) {};
                        if ( (p[i] != -1) && (p[j] != -1)) {
                                fprintf(stderr,"Error 1 in subrouting rr. Odd number of misses\n");
                        }
                        p[i] = j;
                        p[j] = i;
                }
        }

        /* Print array to header file */
        fprintf(fpfile,"\n/* Rotor reflector*/\n");
        fprintf(fpfile,"byte rr[256] = {");
        for (i=0; i < 256; i++) {
                if ( i == 255 ) {
                        fprintf(fpfile,"%3i};\n\n",p[i]);
                } else {
                        if ( i % 16 == 0 ) {
                                fprintf(fpfile,"\n        ");
                        }
                        fprintf(fpfile,"%3i, ",p[i]);
                }

        }
}


int main( int argc, char *argv[] ) {
        int i,j;
        int w[256];  /*To store random numbers for wheel*/
        int wheels;  /*Number of wheels in h file */
        int curwhe;  /* To contain current wheel in for loop */
        char *filename; /*Filename of h file */
        char *filetmp; /* Temporary file for inverse wheel */
        int *notch;     /*Where is the notch in each wheel*/
        progname = argv[0];
        if ( argc != 3 ) { /* Wheel name appended */
                usage();
        }

        wheels = atoi(argv[1]);
        if ( wheels < 1 || wheels > 1000000 ) {
                usage();
        }

        filename = malloc(sizeof(argv[2]));
        if ( filename == NULL ) {
                err("Can't allocate memory for filename.",errno);
                exit(2);
        }
        strcpy(filename,argv[2]);

        notch = malloc( (wheels * sizeof( int )) + sizeof(int) + 80);

        filetmp = malloc(sizeof(argv[2]+4));
        if ( filename == NULL ) {
                err("Can't allocate memory for filetmp.",errno);
                exit(2);
        }
        sprintf(filetmp,"%s.tmp",argv[2]);

        if ( notch == NULL ) {
                err("Can't allocate memory for notch.",errno);
                exit(2);
        }
        FILE *fp;
        FILE *fptmp;
        size_t count;

        fp = fopen(filename, "w");
        if(fp == NULL) {
                err("Can't open file for writing",errno);
                fprintf(stderr,"failed to open file %s\n",filename);
                exit(1);
        }
        fptmp = fopen(filetmp, "w+");
        if(fp == NULL) {
                err("Can't open file for reading and writing",errno);
                fprintf(stderr,"failed to open file %s\n",filetmp);
                exit(1);
        }


        /* Seed random */
        unsigned int seed = makeseed();
        srand(seed);

        /* Make header in h file */
        fprintf(fp,"/* Header file for enigma-like wheels\n");
        fprintf(fp," contact: heth@mercantec.dk\n*/\n");
        fprintf(fp,"#define WHEELS %i\n",wheels);
        fprintf(fp,"typedef unsigned char byte;\n");
        fprintf(fp,"byte wheel[%i][256] = {",wheels);

        /* Loop number of wheels */
        for (curwhe = 0; curwhe < wheels; curwhe++) {
                /* Init p array with random numbers*/
                makeRandomArray(&w[0],256);
                /* Print Char array for permuation */
                for ( i=0;i < 255 ; i++) {
                        if ( i % 16 == 0 ) {
                                if ( i != 0) {
                                        fprintf(fp,"\n        ");
                                } else {
                                        fprintf(fp,"\n/* Wheel %i */\n       {",curwhe+1);
                                }
                        }
                        fprintf(fp,"%3i, ",w[i]);
                }
                /* Is it the last wheel?*/
                if (curwhe == wheels-1) {
                        fprintf(fp,"%3i}\n};",w[255]);
                } else {
                        fprintf(fp,"%3i},",w[255]);
                }
                reversewhell(fptmp, &w[0], curwhe, wheels);
                /*Find random notch for wheel and put in array */
                *(notch+curwhe)=rand() % 256;

        }
        /* Make notch array in h file */
        fprintf(fp,"\n\n/* Notch array for wheels*/\n");
        fprintf(fp,"byte wheel_notch[%i] = {",wheels);

        /* Loop number of wheels */
        for ( i=0;i < wheels ; i++) {
                if ( i % 16 == 0 ) {
                                        fprintf(fp,"\n        ");
                }
                if (i == (wheels-1)) {
                        fprintf(fp,"%i};\n",*(notch+i));
                } else {
                        fprintf(fp,"%i, ",*(notch+i));
                }
        }
        /* Copy tmp file with reverse to end of file */
        if ( fflush(fptmp) != 0 ) {
                err("Can't flush tmp file",errno);
                fprintf(stderr,"Cannot flush file %s\n",filetmp);
                exit(3);
        }
        rewind(fptmp);
        while ((i = fgetc(fptmp)) != EOF) {
                fputc( i, fp);
        }
        /* Make Rotor Reflector */
        rr(fp);
        /* Done writing file - shut down */

        if ( fclose(fptmp) != 0 ) {
                err("Can't close tmp file",errno);
                fprintf(stderr,"Cannot close file %s\n",filetmp);
                exit(4);
        }
        if ( fclose(fp) != 0 ) {
                err("Can't close file",errno);
                fprintf(stderr,"Cannot close file %s\n",filename);
                exit(5);
        }
        /* Delete tmp file */
        if ( remove(filetmp) != 0 ) {
                err("Can't delete temporary file",errno);
                fprintf(stderr,"Cannot delete file %s\n",filetmp);
                exit(6);
        }
        free(filename);
        free(filetmp);
        free(notch);
        exit(0); /* Succes */
}