/* * cave/draw.c version 20060614 * D. J. Bernstein * Public domain. */ #define GRAPHWIDTH 664 #define GRAPHHEIGHT 350 #define BIGGRAPHHEIGHT 600 #define GRAPHLEFT 50 #define GRAPHBOTTOM 700 #define GRAPHRIGHT (GRAPHLEFT + GRAPHWIDTH) #define GRAPHTOP (GRAPHBOTTOM - GRAPHHEIGHT) int graphwidth = GRAPHWIDTH; int graphheight = GRAPHHEIGHT; int graphleft = GRAPHLEFT; int graphbottom = GRAPHBOTTOM; int graphright = GRAPHLEFT + GRAPHWIDTH; int graphtop = GRAPHBOTTOM - GRAPHHEIGHT; int desiredgraphheight = GRAPHHEIGHT; #include #include #include #include #include #include "window.h" char line[65536]; long long numbatmanversionnames; char **batmanversionnames; long long numcomputernames; char **computernames; long long numbatnames; char **batnames; long long numbatversionnames; char **batversionnames; long long numparamnames; char **paramnames; long long nummessagelengths; char **messagelengthnames; long long *messagelengths; long long numobjects; char **objects; long long numpoints; struct point { double x; double y; int source; } *points; struct point selectedpoint; struct { long long batmanversion; long long computer; long long bat; long long batversion; long long param; long long intmeasures[5]; long long logmeasures[5]; long long *msgmeasures[6]; double *chances[3]; } *z; #define patentclaims intmeasures[0] #define copyrightclaims intmeasures[1] #define timingattacks intmeasures[2] #define fakekeyattacks intmeasures[3] #define ccattacks intmeasures[4] #define keypaircycles logmeasures[0] #define secretkeybytes logmeasures[1] #define publickeybytes logmeasures[2] #define sharedsecretcycles logmeasures[3] #define sharedsecretbytes logmeasures[4] #define ciphertextcycles msgmeasures[0] #define ciphertextbytes msgmeasures[1] #define plaintextcycles msgmeasures[2] #define signedmessagecycles msgmeasures[3] #define signedmessagebytes msgmeasures[4] #define messagesignedcycles msgmeasures[5] #define distinguishingchance chances[0] #define forgerychance chances[1] #define cdhchance chances[2] void nomem(void) { exit(111); } void readerror(void) { exit(110); } void readstrings(long long *num,char ***x) { int i; if (scanf("%lld",num) != 1) readerror(); if (*num > 1000000) nomem(); x[0] = malloc(*num * sizeof(char *)); if (!x[0]) nomem(); for (i = 0;i < *num;++i) { if (scanf("%200s",line) != 1) readerror(); x[0][i] = strdup(line); if (!x[0][i]) nomem(); } } double *allocatedouble(long long n) { double *x; long long i; if (n > 1000000) nomem(); x = malloc(n * sizeof(double)); if (!x) nomem(); for (i = 0;i < n;++i) x[i] = -1; return x; } long long *allocatelonglong(long long n) { long long *x; long long i; if (n > 1000000) nomem(); x = malloc(n * sizeof(long long)); if (!x) nomem(); for (i = 0;i < n;++i) x[i] = -1; return x; } void readz(void) { long long i; long long j; double d; z = malloc(numobjects * sizeof(*z)); if (!z) nomem(); for (i = 0;i < numobjects;++i) { if (sscanf(objects[i],"%lld,%lld,%lld,%lld,%lld" ,&z[i].batmanversion ,&z[i].computer ,&z[i].bat ,&z[i].batversion ,&z[i].param ) < 5) readerror(); if (z[i].batmanversion < 0) readerror(); if (z[i].batmanversion >= numbatmanversionnames) readerror(); if (z[i].computer < 0) readerror(); if (z[i].computer >= numcomputernames) readerror(); if (z[i].bat < 0) readerror(); if (z[i].bat >= numbatnames) readerror(); if (z[i].batversion < 0) readerror(); if (z[i].batversion >= numbatversionnames) readerror(); if (z[i].param < 0) readerror(); if (z[i].param >= numparamnames) readerror(); z[i].patentclaims = -1; z[i].copyrightclaims = -1; z[i].timingattacks = -1; z[i].fakekeyattacks = -1; z[i].ccattacks = -1; z[i].keypaircycles = -1; z[i].secretkeybytes = -1; z[i].publickeybytes = -1; z[i].sharedsecretcycles = -1; z[i].sharedsecretbytes = -1; z[i].ciphertextcycles = allocatelonglong(nummessagelengths); z[i].ciphertextbytes = allocatelonglong(nummessagelengths); z[i].plaintextcycles = allocatelonglong(nummessagelengths); z[i].signedmessagecycles = allocatelonglong(nummessagelengths); z[i].signedmessagebytes = allocatelonglong(nummessagelengths); z[i].messagesignedcycles = allocatelonglong(nummessagelengths); z[i].distinguishingchance = allocatedouble(41 * 21 * 11); z[i].forgerychance = allocatedouble(41 * 21 * 11); z[i].cdhchance = allocatedouble(41 * 21 * 11); } while (scanf("%lld",&i) == 1) { if (i >= numobjects) readerror(); if (i < 0) readerror(); if (scanf("%lld",&z[i].patentclaims) < 1) readerror(); if (scanf("%lld",&z[i].copyrightclaims) < 1) readerror(); if (scanf("%lld",&z[i].timingattacks) < 1) readerror(); if (scanf("%lld",&z[i].fakekeyattacks) < 1) readerror(); if (scanf("%lld",&z[i].ccattacks) < 1) readerror(); if (scanf("%lld",&z[i].keypaircycles) < 1) readerror(); if (scanf("%lld",&z[i].secretkeybytes) < 1) readerror(); if (scanf("%lld",&z[i].publickeybytes) < 1) readerror(); if (scanf("%lld",&z[i].sharedsecretcycles) < 1) readerror(); if (scanf("%lld",&z[i].sharedsecretbytes) < 1) readerror(); for (j = 0;j < nummessagelengths;++j) if (scanf("%lld",&z[i].ciphertextcycles[j]) < 1) readerror(); for (j = 0;j < nummessagelengths;++j) if (scanf("%lld",&z[i].ciphertextbytes[j]) < 1) readerror(); for (j = 0;j < nummessagelengths;++j) if (scanf("%lld",&z[i].plaintextcycles[j]) < 1) readerror(); for (j = 0;j < nummessagelengths;++j) if (scanf("%lld",&z[i].signedmessagecycles[j]) < 1) readerror(); for (j = 0;j < nummessagelengths;++j) if (scanf("%lld",&z[i].signedmessagebytes[j]) < 1) readerror(); for (j = 0;j < nummessagelengths;++j) if (scanf("%lld",&z[i].messagesignedcycles[j]) < 1) readerror(); for (j = 0;j < 41 * 21 * 11;++j) { if (scanf("%lf",&d) < 1) readerror(); if (d >= 0) d = exp(log(0.5) * d / 256.0); z[i].distinguishingchance[j] = d; } for (j = 0;j < 41 * 21 * 11;++j) { if (scanf("%lf",&d) < 1) readerror(); if (d >= 0) d = exp(log(0.5) * d / 256.0); z[i].forgerychance[j] = d; } for (j = 0;j < 41 * 21 * 11;++j) { if (scanf("%lf",&d) < 1) readerror(); if (d >= 0) d = exp(log(0.5) * d / 256.0); z[i].cdhchance[j] = d; } } if (ferror(stdin)) readerror(); points = malloc(numobjects * nummessagelengths * sizeof(*points)); if (!points) nomem(); } void parsemessagelengths(void) { long long i; messagelengths = allocatelonglong(nummessagelengths); for (i = 0;i < nummessagelengths;++i) sscanf(messagelengthnames[i],"%lld",&messagelengths[i]); } void readdata(void) { readstrings(&numbatmanversionnames,&batmanversionnames); readstrings(&numcomputernames,&computernames); readstrings(&numbatnames,&batnames); readstrings(&numbatversionnames,&batversionnames); readstrings(&numparamnames,¶mnames); readstrings(&nummessagelengths,&messagelengthnames); parsemessagelengths(); readstrings(&numobjects,&objects); readz(); } #define NUMFEATURES 28 struct { long long macro; long long label; long long fixed; long long hidden; long long logmeasure; long long intmeasure; long long msgmeasure; long long chance; long long class; char *name; double min; double max; } features[NUMFEATURES] = { #define FBMV 0 { FBMV, 0, 0, 0, -1, -1, -1, -1, 1, "BATMAN version" } #define FCNA 1 , { FCNA, 0, 0, 0, -1, -1, -1, -1, 1, "Computer name" } #define FBNA 2 , { FBNA, 0, 0, 0, -1, -1, -1, -1, 1, "BAT name" } #define FBVE 3 , { FBVE, 0, 0, 0, -1, -1, -1, -1, 1, "BAT version" } #define FBPA 4 , { FBPA, 0, 0, 0, -1, -1, -1, -1, 1, "BAT parameters" } #define FOMB 5 , { FOMB, 0, 0, 0, -1, -1, -1, -1, 2, "Original-message bytes" } #define FCTB 6 , { FCTB, 0, 0, 0, -1, -1, 1, -1, 2, "Ciphertext bytes" } #define FCTC 7 , { FCTC, 0, 0, 0, -1, -1, 0, -1, 3, "Encryption cycles" } #define FPTC 8 , { FPTC, 0, 0, 0, -1, -1, 2, -1, 3, "Decryption cycles" } #define FSMB 9 , { FSMB, 0, 0, 0, -1, -1, 4, -1, 2, "Signed-message bytes" } #define FSMC 10 , { FSMC, 0, 0, 0, -1, -1, 3, -1, 3, "Signing cycles" } #define FMSC 11 , { FMSC, 0, 0, 0, -1, -1, 5, -1, 3, "Verification cycles" } #define FPAT 12 , { FPAT, 0, 0, 0, -1, 0, -1, -1, 4, "Patent claims" } #define FCOP 13 , { FCOP, 0, 0, 0, -1, 1, -1, -1, 4, "Copyright claims" } #define FKPC 14 , { FKPC, 0, 0, 0, 0, -1, -1, -1, 3, "Key-generation cycles" } #define FPKB 15 , { FPKB, 0, 0, 0, 2, -1, -1, -1, 2, "Public-key bytes" } #define FSKB 16 , { FSKB, 0, 0, 0, 1, -1, -1, -1, 2, "Secret-key bytes" } #define FSSC 17 , { FSSC, 0, 0, 0, 3, -1, -1, -1, 3, "Shared-secret cycles" } #define FSSB 18 , { FSSB, 0, 0, 0, 4, -1, -1, -1, 2, "Shared-secret bytes" } #define FASE 19 , { FASE, 0, 0, 0, -1, -1, -1, -1, 5, "Attack seconds = 2 ^" } #define FAEU 20 , { FAEU, 0, 0, 0, -1, -1, -1, -1, 5, "Attack euros = 2 ^" } #define FKAT 21 , { FKAT, 0, 0, 0, -1, -1, -1, -1, 5, "Keys attacked = 2 ^" } #define FDIC 22 , { FDIC, 0, 0, 0, -1, -1, -1, 0, 6, "Distinguishing chance" } #define FCCA 23 , { FCCA, 0, 0, 0, -1, 4, -1, -1, 7, "Chosen-ciphertext attacks" } #define FFOC 24 , { FFOC, 0, 0, 0, -1, -1, -1, 1, 6, "Forgery chance" } #define FDHC 25 , { FDHC, 0, 0, 0, -1, -1, -1, 2, 6, "CDH chance" } #define FFKA 26 , { FFKA, 0, 0, 0, -1, 3, -1, -1, 7, "Fake-key attacks" } #define FTIA 27 , { FTIA, 0, 0, 0, -1, 2, -1, -1, 7, "Timing attacks" } } ; long long keygenheight = GRAPHTOP + GRAPHHEIGHT / 2 + 22; long long desiredkeygenheight = GRAPHTOP + GRAPHHEIGHT / 2 + 22; long long selectedobject; long long selectedmessagelength = 1; long long selectedelog = 30; long long selectedklog = 40; long long selectedslog = 30; long long selectedfeature = FSKB; long long xfeature = FPKB; long long yfeature = FKPC; double zoom = 1; double desiredzoom = 1; double xshift = 0.5; double desiredxshift = 0.5; double yshift = 0.5; double desiredyshift = 0.5; int background(void) { int result = 0; if (zoom < desiredzoom) { zoom *= 1.15; if (zoom >= desiredzoom) zoom = desiredzoom; result = 1; } if (zoom > desiredzoom) { zoom *= 0.86956; if (zoom <= desiredzoom) zoom = desiredzoom; result = 1; } if (yshift < desiredyshift) { yshift += 0.05 * zoom; if (yshift >= desiredyshift) yshift = desiredyshift; result = 1; } if (yshift >= desiredyshift) { yshift -= 0.05 * zoom; if (yshift <= desiredyshift) yshift = desiredyshift; result = 1; } if (xshift < desiredxshift) { xshift += 0.05 * zoom; if (xshift >= desiredxshift) xshift = desiredxshift; result = 1; } if (xshift >= desiredxshift) { xshift -= 0.05 * zoom; if (xshift <= desiredxshift) xshift = desiredxshift; result = 1; } if (graphheight != desiredgraphheight) { if (graphheight < desiredgraphheight) { graphheight += 10; if (graphheight > desiredgraphheight) graphheight = desiredgraphheight; } if (graphheight > desiredgraphheight) { graphheight -= 10; if (graphheight < desiredgraphheight) graphheight = desiredgraphheight; } graphtop = graphbottom - graphheight; if (desiredkeygenheight < graphtop + graphheight / 8 || desiredkeygenheight > graphbottom - graphheight / 8) desiredkeygenheight = graphtop + graphheight / 2; result = 1; } if (keygenheight != desiredkeygenheight) { if (keygenheight < desiredkeygenheight) ++keygenheight; if (keygenheight > desiredkeygenheight) --keygenheight; result = 1; } return result; } int keypress(long long k) { if (k == 'z') { if (desiredzoom > 0.015625) desiredzoom *= 0.5; if (desiredxshift < 0.5 * desiredzoom) desiredxshift = 0.5 * desiredzoom; if (desiredyshift < 0.5 * desiredzoom) desiredyshift = 0.5 * desiredzoom; if (desiredxshift >= 1 - 0.5 * desiredzoom) desiredxshift = 1 - 0.5 * desiredzoom; if (desiredyshift >= 1 - 0.5 * desiredzoom) desiredyshift = 1 - 0.5 * desiredzoom; return 0; } if (k == 'a') { if (desiredzoom < 1) desiredzoom *= 2; if (desiredxshift < 0.5 * desiredzoom) desiredxshift = 0.5 * desiredzoom; if (desiredyshift < 0.5 * desiredzoom) desiredyshift = 0.5 * desiredzoom; if (desiredxshift >= 1 - 0.5 * desiredzoom) desiredxshift = 1 - 0.5 * desiredzoom; if (desiredyshift >= 1 - 0.5 * desiredzoom) desiredyshift = 1 - 0.5 * desiredzoom; return 0; } if (k == 0xff52) { /* up */ desiredyshift += 0.5 * desiredzoom; if (desiredyshift >= 1 - 0.5 * desiredzoom) desiredyshift = 1 - 0.5 * desiredzoom; return 0; } if (k == 0xff54) { /* down */ desiredyshift -= 0.5 * desiredzoom; if (desiredyshift < 0.5 * desiredzoom) desiredyshift = 0.5 * desiredzoom; return 0; } if (k == 0xff53 || k == 0xffe4) { /* right or rightctrl */ desiredxshift += 0.5 * desiredzoom; if (desiredxshift >= 1 - 0.5 * desiredzoom) desiredxshift = 1 - 0.5 * desiredzoom; return 0; } if (k == 0xff51 || k == 0xffe3) { /* left or leftctrl */ desiredxshift -= 0.5 * desiredzoom; if (desiredxshift < 0.5 * desiredzoom) desiredxshift = 0.5 * desiredzoom; return 0; } if (0) if (k == 'f') { if (desiredgraphheight == GRAPHHEIGHT) desiredgraphheight = BIGGRAPHHEIGHT; else desiredgraphheight = GRAPHHEIGHT; return 0; } if (k == 'x') { xfeature = selectedfeature; return 1; } if (k == 'y') { yfeature = selectedfeature; return 1; } if (k == 't') { features[selectedfeature].label = !features[selectedfeature].label; if (features[selectedfeature].label) features[selectedfeature].fixed = 0; return 1; } if (k == 'l') { features[selectedfeature].fixed = !features[selectedfeature].fixed; if (features[selectedfeature].fixed) features[selectedfeature].label = 0; return 1; } if (k == 'i') { features[selectedfeature].hidden = 1; return 1; } if (k == 'v') { features[selectedfeature].hidden = 0; return 1; } if (k == 'k') { if (selectedfeature > 0) --selectedfeature; return 1; } if (k == 'j') { if (selectedfeature < NUMFEATURES - 1) ++selectedfeature; return 1; } if (k == ']') { switch(selectedfeature) { case FOMB: if (selectedmessagelength < nummessagelengths - 1) selectedmessagelength += 1; break; case FASE: if (selectedslog < 40) selectedslog += 1; break; case FAEU: if (selectedelog < 40) selectedelog += 2; break; case FKAT: if (selectedklog < 40) selectedklog += 4; break; } return 1; } if (k == '[') { switch(selectedfeature) { case FOMB: if (selectedmessagelength > 1) selectedmessagelength -= 1; break; case FASE: if (selectedslog > 0) selectedslog -= 1; break; case FAEU: if (selectedelog > 0) selectedelog -= 2; break; case FKAT: if (selectedklog > 0) selectedklog -= 4; break; } return 1; } if (k == 1000000 + '[') { if (selectedobject > 0) --selectedobject; return 1; } if (k == 1000000 + ']') { if (selectedobject < numobjects - 1) ++selectedobject; return 1; } if (k == 113) return -1; return 0; } void printfeature(long long n,const char *featurevalue) { int x; int y; if (n < 14) { x = graphleft; y = 24 + 22 * n; } else { x = graphleft + 512; y = 24 + 22 * (n - 14); } if (n == xfeature) window_drawstring(x - 40,y,"x",2); else if (features[n].fixed) window_drawstring(x - 40,y,"l",2); else if (features[n].label) window_drawstring(x - 40,y,"t",2); if (n == yfeature) window_drawstring(x - 30,y,"y",2); if (n == selectedfeature) window_drawstring(x - 20,y,">",2); window_drawstring(x,y,features[n].name,features[n].hidden ? 6 : 4); window_drawstring(x + 260,y,featurevalue,features[n].hidden ? 6 : 0); } void printfeaturenum(long long n,long long featurevalue) { char buf[100]; if (n < 0) return; if (n >= NUMFEATURES) return; if (featurevalue >= 0) { sprintf(buf,"%lld",featurevalue); printfeature(n,buf); } else { printfeature(n,"-"); } } void printfeaturelog(long long n,double featurevalue) { char buf[100]; if (n < 0) return; if (n >= NUMFEATURES) return; if (featurevalue >= 0) { if (featurevalue > 1) sprintf(buf,"%.0f = 2^%.2f",featurevalue,log(featurevalue) / log(2)); else if (featurevalue == 1) sprintf(buf,"1"); else sprintf(buf,"1/2^%.2f",-log(featurevalue) / log(2)); printfeature(n,buf); } else { printfeature(n,"-"); } } char str[200]; void printlog(int x,int y,double n,int c) { sprintf(str,"%.0f = 2^%.2f",n,log(n) / log(2)); if (str[strlen(str) - 1] == '0') str[strlen(str) - 1] = 0; if (str[strlen(str) - 1] == '0') str[strlen(str) - 1] = 0; if (str[strlen(str) - 1] == '.') str[strlen(str) - 1] = 0; window_drawstring(x,y,str,c); } void printnum(int x,int y,double n,int c) { sprintf(str,"%.0f",n); window_drawstring(x,y,str,c); } int objectmatchesfixed(int i) { long long eks; if (features[FBMV].fixed) if (z[i].batmanversion != z[selectedobject].batmanversion) return 0; if (features[FCNA].fixed) if (z[i].computer != z[selectedobject].computer) return 0; if (features[FBNA].fixed) if (z[i].bat != z[selectedobject].bat) return 0; if (features[FBVE].fixed) if (z[i].batversion != z[selectedobject].batversion) return 0; if (features[FBPA].fixed) if (z[i].param != z[selectedobject].param) return 0; if (features[FPAT].fixed) if (z[i].patentclaims != z[selectedobject].patentclaims) return 0; if (features[FCOP].fixed) if (z[i].copyrightclaims != z[selectedobject].copyrightclaims) return 0; if (features[FKPC].fixed) if (z[i].keypaircycles != z[selectedobject].keypaircycles) return 0; if (features[FPKB].fixed) if (z[i].publickeybytes != z[selectedobject].publickeybytes) return 0; if (features[FSKB].fixed) if (z[i].secretkeybytes != z[selectedobject].secretkeybytes) return 0; if (features[FSSC].fixed) if (z[i].sharedsecretcycles != z[selectedobject].sharedsecretcycles) return 0; if (features[FSSB].fixed) if (z[i].sharedsecretbytes != z[selectedobject].sharedsecretbytes) return 0; if (features[FCCA].fixed) if (z[i].ccattacks != z[selectedobject].ccattacks) return 0; if (features[FFKA].fixed) if (z[i].fakekeyattacks != z[selectedobject].fakekeyattacks) return 0; if (features[FTIA].fixed) if (z[i].timingattacks != z[selectedobject].timingattacks) return 0; if (features[FOMB].fixed) ; /* XXX */ if (features[FCTB].fixed) ; /* XXX */ if (features[FCTC].fixed) ; /* XXX */ if (features[FPTC].fixed) ; /* XXX */ if (features[FSMB].fixed) ; /* XXX */ if (features[FSMC].fixed) ; /* XXX */ if (features[FPAT].fixed) ; /* XXX */ if (features[FASE].fixed) ; /* XXX */ if (features[FAEU].fixed) ; /* XXX */ if (features[FKAT].fixed) ; /* XXX */ eks = selectedslog + 41 * ((selectedklog / 4) + 11 * (selectedelog / 2)); /* XXX: allow user to select cutoff for 0.000001 here */ if (features[FDIC].fixed) if (z[i].distinguishingchance[eks] < 0 || z[i].distinguishingchance[eks] > 0.000001) return 0; if (features[FFOC].fixed) if (z[i].forgerychance[eks] < 0 || z[i].forgerychance[eks] > 0.000001) return 0; if (features[FDHC].fixed) if (z[i].cdhchance[eks] < 0 || z[i].cdhchance[eks] > 0.000001) return 0; return 1; } double besttwopower(double x) /* down to power of 2 */ { if (x >= 1 && x < 2) return 1; return exp(log(2) * floor(log(x) / log(2) - 0.5)); } void findminmax(void) { int n; long long i; long long j; double x; double min; double max; int haveminmax; haveminmax = 0; min = 0; max = 0; for (j = 0;j < nummessagelengths;++j) { x = messagelengths[j]; if (x < 1) continue; if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } for (i = 0;i < numobjects;++i) { x = z[i].publickeybytes; if (x >= 1) { if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } x = z[i].secretkeybytes; if (x >= 1) { if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } x = z[i].sharedsecretbytes; if (x >= 1) { if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } for (j = 0;j < nummessagelengths;++j) { x = z[i].ciphertextbytes[j]; if (x >= 1) { if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } x = z[i].signedmessagebytes[j]; if (x >= 1) { if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } } } min = besttwopower(min); max = 1 / besttwopower(1 / max); features[FOMB].min = min; features[FOMB].max = max; features[FPKB].min = min; features[FPKB].max = max; features[FSKB].min = min; features[FSKB].max = max; features[FCTB].min = min; features[FCTB].max = max; features[FSMB].min = min; features[FSMB].max = max; haveminmax = 0; min = 0; max = 0; for (i = 0;i < numobjects;++i) { x = z[i].keypaircycles; if (x >= 1) { if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } x = z[i].sharedsecretcycles; if (x >= 1) { if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } for (j = 0;j < nummessagelengths;++j) { x = z[i].ciphertextcycles[j]; if (x >= 1) { if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } x = z[i].plaintextcycles[j]; if (x >= 1) { if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } x = z[i].signedmessagecycles[j]; if (x >= 1) { if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } x = z[i].messagesignedcycles[j]; if (x >= 1) { if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } } } min = besttwopower(min); max = 1 / besttwopower(1 / max); features[FKPC].min = min; features[FKPC].max = max; features[FSSC].min = min; features[FSSC].max = max; features[FCTC].min = min; features[FCTC].max = max; features[FPTC].min = min; features[FPTC].max = max; features[FSMC].min = min; features[FSMC].max = max; features[FMSC].min = min; features[FMSC].max = max; haveminmax = 1; min = 0; max = 100; for (i = 0;i < numobjects;++i) { x = z[i].patentclaims; if (x >= 1) { if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } x = z[i].copyrightclaims; if (x >= 1) { if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } } features[FPAT].min = min; features[FPAT].max = max; features[FCOP].min = min; features[FCOP].max = max; haveminmax = 1; min = 0; max = 40; for (i = 0;i < numobjects;++i) { x = z[i].ccattacks; if (x >= 1) { if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } x = z[i].fakekeyattacks; if (x >= 1) { if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } x = z[i].timingattacks; if (x >= 1) { if (!haveminmax) { min = x; max = x; haveminmax = 1; } if (x < min) min = x; if (x > max) max = x; } } features[FCCA].min = min; features[FCCA].max = max; features[FFKA].min = min; features[FFKA].max = max; features[FTIA].min = min; features[FTIA].max = max; } void drawgraph(void) { int flagselected; int logarithmicx; int logarithmicy; long long i; long long j; double x; double y; double screenx; double screeny; double xmin; double ymin; double xmax; double ymax; double xscale; double yscale; double xoffset; double yoffset; if (xfeature < 0) return; if (xfeature >= NUMFEATURES) return; if (yfeature < 0) return; if (yfeature >= NUMFEATURES) return; window_fillrectangle(graphleft,graphtop,1,graphheight,6); window_fillrectangle(graphright,graphtop,1,graphheight,6); window_fillrectangle(graphleft,graphbottom,graphwidth,1,6); window_fillrectangle(graphleft,graphtop,graphwidth,1,6); window_drawstring(graphleft + graphwidth / 2 + 10,graphbottom + 44,features[xfeature].name,4); numpoints = 0; flagselected = 0; logarithmicx = 0; if (features[xfeature].logmeasure >= 0) logarithmicx = 1; if (features[xfeature].msgmeasure >= 0) logarithmicx = 1; if (features[xfeature].chance >= 0) logarithmicx = 1; if (xfeature == FOMB) logarithmicx = 1; logarithmicy = 0; if (features[yfeature].logmeasure >= 0) logarithmicy = 1; if (features[yfeature].msgmeasure >= 0) logarithmicy = 1; if (features[yfeature].chance >= 0) logarithmicy = 1; if (yfeature == FOMB) logarithmicy = 1; if (xfeature == FOMB && features[yfeature].msgmeasure >= 0) { for (i = 0;i < numobjects;++i) { if (!objectmatchesfixed(i)) continue; for (j = 0;j < nummessagelengths;++j) { x = messagelengths[j]; if (x < 1) continue; y = z[i].msgmeasures[features[yfeature].msgmeasure][j]; if (y < 1) continue; points[numpoints].x = x; points[numpoints].y = y; points[numpoints].source = i; if (i == selectedobject && j == selectedmessagelength) { selectedpoint = points[numpoints]; flagselected = 1; } ++numpoints; } } } else { for (i = 0;i < numobjects;++i) { if (!objectmatchesfixed(i)) continue; if (features[xfeature].logmeasure >= 0) { x = z[i].logmeasures[features[xfeature].logmeasure]; if (x < 1) continue; } else if (features[xfeature].intmeasure >= 0) { x = z[i].intmeasures[features[xfeature].intmeasure]; if (x < 0) continue; } else if (features[xfeature].msgmeasure >= 0) { x = z[i].msgmeasures[features[xfeature].msgmeasure][selectedmessagelength]; if (x < 1) continue; } else { goto unsupportedgraph; } if (features[yfeature].logmeasure >= 0) { y = z[i].logmeasures[features[yfeature].logmeasure]; if (y < 1) continue; } else if (features[yfeature].intmeasure >= 0) { y = z[i].intmeasures[features[yfeature].intmeasure]; if (y < 0) continue; } else if (features[yfeature].msgmeasure >= 0) { y = z[i].msgmeasures[features[yfeature].msgmeasure][selectedmessagelength]; if (y < 1) continue; } else { goto unsupportedgraph; } points[numpoints].x = x; points[numpoints].y = y; points[numpoints].source = i; if (i == selectedobject) { selectedpoint = points[numpoints]; flagselected = 1; } ++numpoints; } } if (!numpoints) { window_drawstring(graphright + 10,graphbottom - graphheight / 2 + 24,features[yfeature].name,4); window_drawstring(graphleft + 10,graphtop + 25,"No points to graph",2); return; unsupportedgraph: window_drawstring(graphright + 10,graphbottom - graphheight / 2 + 24,features[yfeature].name,4); window_drawstring(graphleft + 10,graphtop + 25,"Graph not supported yet; sorry!",2); return; } xmin = features[xfeature].min; xmax = features[xfeature].max; if (logarithmicx) { xmin = log(xmin); xmax = log(xmax); } xmax -= xmin; xmin += (xshift - 0.5 * zoom) * xmax; xmax = xmin + xmax * zoom; if (logarithmicx) { printlog(graphleft,graphbottom + 44,exp(log(2) * xmin),6); printlog(graphright,graphbottom + 44,exp(log(2) * xmax),6); } else { printnum(graphleft,graphbottom + 44,xmin,6); printnum(graphright,graphbottom + 44,xmax,6); } if (xmin == xmax) { xscale = 1; xoffset = graphleft + graphwidth / 2 - xmin; } else { xscale = graphwidth / (xmax - xmin); xoffset = graphleft - xmin * xscale; } ymin = features[yfeature].min; ymax = features[yfeature].max; if (logarithmicy) { ymin = log(ymin); ymax = log(ymax); } ymax -= ymin; ymin += (yshift - 0.5 * zoom) * ymax; ymax = ymin + ymax * zoom; if (logarithmicy) { printlog(graphright + 10,graphbottom + 22,exp(log(2) * ymin),6); printlog(graphright + 10,graphtop - 22,exp(log(2) * ymax),6); } else { printnum(graphright + 10,graphbottom + 22,ymin,6); printnum(graphright + 10,graphtop - 22,ymax,6); } if (ymin == ymax) { yscale = 1; yoffset = graphbottom - graphheight / 2 - ymin; } else { yscale = graphheight / (ymin - ymax); yoffset = graphbottom - ymin * yscale; } if (flagselected) { screenx = x = selectedpoint.x; screeny = y = selectedpoint.y; if (logarithmicx) screenx = log(screenx); if (logarithmicy) screeny = log(screeny); screenx = xoffset + xscale * screenx; screeny = yoffset + yscale * screeny; window_fillrectangle(screenx,graphtop,1,graphheight,0); window_fillrectangle(graphleft,screeny,graphwidth,1,0); if (screeny > graphbottom - 88) (logarithmicx ? printlog : printnum)(screenx,graphbottom + 22,x,0); else (logarithmicx ? printlog : printnum)(screenx + 5,graphbottom - 5,x,0); (logarithmicy ? printlog : printnum)(graphright + 10,screeny,y,0); if (screeny > desiredkeygenheight - 44 && screeny < desiredkeygenheight + 44) { if (screeny < desiredkeygenheight) desiredkeygenheight = screeny + 44; if (screeny > desiredkeygenheight) desiredkeygenheight = screeny - 44; if (desiredkeygenheight < graphtop + graphheight / 8 || desiredkeygenheight > graphbottom - graphheight / 8) desiredkeygenheight = graphtop + graphheight / 2; } window_drawstring(graphright + 10,keygenheight,features[yfeature].name,4); } else { window_drawstring(graphright + 10,keygenheight,features[yfeature].name,4); } for (i = 0;i < numpoints;++i) { screenx = points[i].x; screeny = points[i].y; if (logarithmicx) screenx = log(screenx); if (logarithmicy) screeny = log(screeny); screenx = xoffset + xscale * screenx; screeny = yoffset + yscale * screeny; window_fillrectangle(screenx - 2,screeny - 2,5,5,3); if (features[FCNA].label || features[FBNA].label || features[FBVE].label || features[FBPA].label) { sprintf(line,"%s%s%s%s%s%s%s%s" ,features[FCNA].label ? computernames[z[points[i].source].computer] : "" ,features[FCNA].label ? " " : "" ,features[FBNA].label ? batnames[z[points[i].source].bat] : "" ,features[FBNA].label ? " " : "" ,features[FBVE].label ? batversionnames[z[points[i].source].batversion] : "" ,features[FBVE].label ? " " : "" ,features[FBPA].label && strcmp(paramnames[z[points[i].source].param],"-") ? paramnames[z[points[i].source].param] : "" ,features[FBPA].label && strcmp(paramnames[z[points[i].source].param],"-") ? " " : "" ); if (screenx <= graphleft + graphwidth / 2 && screeny > graphtop + 66) window_drawstring(screenx + 5,screeny - 5,line,3); else window_drawstring(screenx + 5,screeny + 22,line,3); } } if (flagselected) { screenx = selectedpoint.x; screeny = selectedpoint.y; if (logarithmicx) screenx = log(screenx); if (logarithmicy) screeny = log(screeny); screenx = xoffset + xscale * screenx; screeny = yoffset + yscale * screeny; window_fillrectangle(screenx - 2,screeny - 2,5,5,0); sprintf(line,"%s %s-%s/%s %s" ,computernames[z[selectedobject].computer] ,batnames[z[selectedobject].bat] ,batversionnames[z[selectedobject].batversion] ,batmanversionnames[z[selectedobject].batmanversion] ,strcmp(paramnames[z[selectedobject].param],"-") ? paramnames[z[selectedobject].param] : "" ); if (screenx <= graphleft + graphwidth / 2 && screeny > graphtop + 66) window_drawstring(screenx + 5,screeny - 5,line,0); else window_drawstring(screenx + 5,screeny + 22,line,0); } } void redraw(void) { long long eks; if (graphheight == GRAPHHEIGHT) { printfeature(FBMV,batmanversionnames[z[selectedobject].batmanversion]); printfeature(FCNA,computernames[z[selectedobject].computer]); printfeature(FBNA,batnames[z[selectedobject].bat]); printfeature(FBVE,batversionnames[z[selectedobject].batversion]); printfeature(FBPA,paramnames[z[selectedobject].param]); printfeature(FOMB,messagelengthnames[selectedmessagelength]); printfeaturenum(FCTB,z[selectedobject].ciphertextbytes[selectedmessagelength]); printfeaturenum(FCTC,z[selectedobject].ciphertextcycles[selectedmessagelength]); printfeaturenum(FPTC,z[selectedobject].plaintextcycles[selectedmessagelength]); printfeaturenum(FSMB,z[selectedobject].signedmessagebytes[selectedmessagelength]); printfeaturenum(FSMC,z[selectedobject].signedmessagecycles[selectedmessagelength]); printfeaturenum(FMSC,z[selectedobject].messagesignedcycles[selectedmessagelength]); printfeaturelog(FKPC,z[selectedobject].keypaircycles); printfeaturelog(FPKB,z[selectedobject].publickeybytes); printfeaturelog(FSKB,z[selectedobject].secretkeybytes); printfeaturelog(FSSC,z[selectedobject].sharedsecretcycles); printfeaturelog(FSSB,z[selectedobject].sharedsecretbytes); printfeaturenum(FASE,selectedslog); printfeaturenum(FAEU,selectedelog); printfeaturenum(FKAT,selectedklog); eks = selectedslog + 41 * ((selectedklog / 4) + 11 * (selectedelog / 2)); printfeaturelog(FDIC,z[selectedobject].distinguishingchance[eks]); printfeaturelog(FFOC,z[selectedobject].forgerychance[eks]); printfeaturelog(FDHC,z[selectedobject].cdhchance[eks]); printfeaturenum(FTIA,z[selectedobject].timingattacks); printfeaturenum(FFKA,z[selectedobject].fakekeyattacks); printfeaturenum(FCCA,z[selectedobject].ccattacks); printfeaturenum(FPAT,z[selectedobject].patentclaims); printfeaturenum(FCOP,z[selectedobject].copyrightclaims); } window_drawstring(graphleft,24 + 11 * 29,"Features: jk. Axes: xy. Zoom: za, arrows. Text: t. Limit: l. More: {}[]q.",5); drawgraph(); } int main(int argc,char **argv) { readdata(); findminmax(); window_exec(argc,argv,redraw,keypress,background); }