Enigma/makewheel.c
From Teknologisk videncenter
/**************************************************************************
# #
## ## ###### ##### #### ## # # ##### ###### ####
# # # # # # # # # # # ## # # # # #
# # # ##### # # # # # # # # # ##### #
# # # ##### # ###### # # # # # #
# # # # # # # # # # ## # # # #
# # ###### # # #### # # # # # ###### ####
***************************************************************************
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 */
}