/* MAA Message Authenticator Algorithm */ /* compiled and run under Turbo C++ version 1.01 */ #include #include #include #define BIT31 0x80000000L #define FFFF 0xFFFFL unsigned long a,b,c,d,l,m,s,t,u,v,w,x,y,z,pat,sum,t4,t5,v0,x0,y0; int menu1() { int m; printf("\n 1 Test small functions (Tables 1, 2)\n"); printf(" 2 Test prelude (Table 3)\n"); printf(" 3 Test main (Table 4)\n"); printf(" 4 Test prelude + main + coda (Table 5)\n"); printf(" 5 Test and timing of repeated message blocks (Table 6)\n"); printf(" 6 Quit \n"); scanf("%d", &m); return(m); } /* menu1 */ void mul32(a, b) unsigned long a, b; /* unsigned 64 bit product in u (upper) and l (lower) */ { unsigned long p1, p2, p3, sum; p1 = (a & FFFF) * (b & FFFF); p2 = (a & FFFF) * (b >> 16); p3 = (a >> 16) * (b & FFFF); sum = (p1 >> 16) + (p2 & FFFF) + (p3 & FFFF); l = (p1 & FFFF) + (sum << 16); u = (sum >> 16) + (p2 >> 16) + (p3 >> 16) + ( (a >> 16) * (b >> 16) ); } /* mul32 */ unsigned long mul1(a, b) unsigned long a, b; { unsigned long s, car; mul32(a, b); s = u + l; car = ( (u ^ l) & BIT31) ? !(s & BIT31) : (u & BIT31) != 0; return(s + car); } /* mul1 */ unsigned long mul2(a, b) unsigned long a, b; { unsigned long d, f, s, car; mul32(a, b); d = u + u; car = (u & BIT31) != 0; f = d + car + car; s = f + l; car = ( (f ^ l) & BIT31) ? !(s & BIT31) : (f & BIT31) != 0; return(s + car + car); } /* mul2 */ unsigned long mul2a(a, b) unsigned long a, b; { unsigned long d, s, car; mul32(a, b); d = u + u; s = d + l; car = ( (d ^ l) & BIT31) ? !(s & BIT31) : (d & BIT31) != 0; return(s + car + car); } /* mul2a */ void byt(x, y) unsigned long x, y; { unsigned long p; int i, b[8]; for(i = 3; i >= 0; i--) { b[i] = x & 255; b[i + 4] = y & 255; x = x >> 8; y = y >> 8; } p = 0; for(i = 0; i < 8; i++) { p = p + p; if (b[i] == 0) {p += 1; b[i] = p;} else if (b[i] == 255) {p += 1; b[i] = 255 - p;} } pat = p; x = 0; y = 0; for (i = 0; i < 4; i++) {x = (x << 8) + b[i]; y = (y << 8) + b[i + 4];} u = x; l = y; } /* byt */ void prelude(x, y, test) unsigned long x, y; int test; { unsigned long j1[10], j2[10], k1[10], k2[10], h[10]; unsigned long p, q; byt(x, y); j1[0] = u; k1[0] = l; p = pat; if (test > 0) { j1[0] = x; k1[0] = y; printf(" Enter P (2 hex): "); scanf("%X", &p); } q = (p + 1) * (p + 1); j1[2] = mul1(j1[0], j1[0]); j2[2] = mul2(j1[0], j1[0]); j1[4] = mul1(j1[2], j1[2]); j2[4] = mul2(j2[2], j2[2]); j1[6] = mul1(j1[2], j1[4]); j2[6] = mul2(j2[2], j2[4]); j1[8] = mul1(j1[2], j1[6]); j2[8] = mul2(j2[2], j2[6]); h[4] = j1[4] ^ j2[4]; h[6] = j1[6] ^ j2[6]; h[8] = j1[8] ^ j2[8]; printf("H4= %08lX \n", h[4]); printf("H6= %08lX \n", h[6]); printf("H8= %08lX \n", h[8]); k1[2] = mul1(k1[0], k1[0]); k2[2] = mul2(k1[0], k1[0]); k1[4] = mul1(k1[2], k1[2]); k2[4] = mul2(k2[2], k2[2]); k1[5] = mul1(k1[0], k1[4]); k2[5] = mul2(k1[0], k2[4]); k1[7] = mul1(k1[2], k1[5]); k2[7] = mul2(k2[2], k2[5]); k1[9] = mul1(k1[2], k1[7]); k2[9] = mul2(k2[2], k2[7]); h[0] = k1[5] ^ k2[5]; h[5] = mul2(h[0], q); h[7] = k1[7] ^ k2[7]; h[9] = k1[9] ^ k2[9]; printf("H0= %08lX \n", h[0]); printf("H5= %08lX \n", h[5]); printf("H7= %08lX \n", h[7]); printf("H9= %08lX \n", h[9]); byt(h[4], h[5]); x0 = u; y0 = l; printf("X0= %08lX", x0); printf(" Y0= %08lX", y0); printf(" PAT= %08lX \n", pat); byt(h[6], h[7]); v0 = u; w = l; printf("V0= %08lX", v0); printf(" W= %08lX", w); printf(" PAT= %08lX \n", pat); byt(h[8], h[9]); s = u; t = l; printf(" S= %08lX", s); printf(" T= %08lX", t); printf(" PAT= %08lX \n", pat); } /* prelude */ void abcd() { a = 0x02040801L; b = 0x00804021L; c = 0xBFEF7FDFL; d = 0x7DFEFBFFL; printf("A= %08lX \n", a); printf("B= %08lX \n", b); printf("C= %08lX \n", c); printf("D= %08lX \n", d); } /* abcd */ void inmain() { abcd(); printf("Press 1 to enter A, B, C, D, V, W, X0, Y0, M "); printf("else for standard ABCD\n"); if ( ( getch() ) == '1' ) { printf("Enter A (8 hex): "); scanf("%lX", &a); printf("Enter B (8 hex): "); scanf("%lX", &b); printf("~(8)=FFFFFFF7, ~(4)=FFFFFFFB, ~(6)=FFFFFFF9, ~(3)=FFFFFFFC \n"); printf("~(1)=FFFFFFFE, ~(2*)=7FFFFFFD, ~(2)=FFFFFFFD \n"); printf("Enter C (8 hex): "); scanf("%lX", &c); printf("Enter D (8 hex): "); scanf("%lX", &d); printf("Enter V (8 hex): "); scanf("%lX", &v); printf("Enter W (8 hex): "); scanf("%lX", &w); printf("Enter X0 (8 hex): "); scanf("%lX", &x); printf("Enter Y0 (8 hex): "); scanf("%lX", &y); printf("Enter M (8 hex): "); scanf("%lX", &m); } } /* inmain */ void mainloop1(m) unsigned long m; { unsigned long e, f, g; printf("Results are in hexadecimal \n"); v = (v & BIT31)? (v << 1) | 1L: v << 1; /* v = cyc(v); */ printf("V= %08lX \n", v); e = v ^ w; printf("E= %08lX \n", e); x = x ^ m; printf("X= %08lX ", x); y = y ^ m; printf(" Y= %08lX \n", y); f = e + y; printf("F= %08lX ", f); g = e + x; printf(" G= %08lX \n", g); f = f | a; printf("F= %08lX ", f); g = g | b; printf(" G= %08lX \n", g); f = f & c; printf("F= %08lX ", f); g = g & d; printf(" G= %08lX \n", g); x = mul1(x, f); printf("X= %08lX ", x); y = mul2(y, g); printf(" Y= %08lX \n", y); } /* mainloop1 */ void mainloop2(m) unsigned long m; /* as mainloop1 without printf. Mul1, Mul2a copied to save time */ { unsigned long e, f, g, s; int car; v = (v & BIT31)? (v << 1) | 1L: v << 1; /* v = cyc(v); */ e = v ^ w; x = x ^ m; y = y ^ m; f = e + y; g = e + x; f = f | a; g = g | b; f = f & c; g = g & d; /* x = mul1(x, f); */ mul32(x, f); s = u + l; car = ((u ^ l) & BIT31)? !(s & BIT31) : (u & BIT31) != 0; x = (car) ? s + 1L : s; /* y = mul2a(y, g); */ mul32(y, g); g = u + u; s = g + l; car = ((g ^ l) & BIT31)? !(s & BIT31) : (g & BIT31) != 0; y = (car)? s + 2L : s; } /* mainloop2 */ /* NOTE. Time measurement is not standard C, hence may not be portable. Guesstime + fracsec uses the 1 second clock of MS-DOS. Works with Turbo and Zorland compilers. */ unsigned long fracsec() { unsigned long i; i = 0; t5 = time(NULL); do i++; /* count while waiting for next second */ while (time(NULL) == t5); return(i); } /* fracsec */ float guesstime() /* Uses fracsec and time (which counts whole seconds). Probably most portable, may be least accurate if interrupted. OK for Turbo and Zorland versions 1 and 2. */ { unsigned long i, j, secs; t4 = t5; i = fracsec(); secs = t5 - t4 - 1; j = fracsec(); if (i > j) i = j; return(secs + (j - i)/(float) j); } /* guesstime */ void main() { unsigned long i, t1, t2; long ti; int nn, ii, choice, disp, car; float tf; t5 = 0; do { choice = menu1(); printf("Note all results (except time) are in hexadecimal \n"); switch(choice) { case 1: { printf(" Enter X (8 hex): "); scanf("%lX", &x); printf(" Enter Y (8 hex): "); scanf("%lX", &y); sum = x + y; printf("Sum= %08lX", sum); car = ((x ^ y) & BIT31) ? !(sum & BIT31) : (x & BIT31) != 0; printf(" Carry= %X \n", car); sum = x + x; car = (x & BIT31) != 0; printf("2*X= %08lX", sum); printf(" Carry= %X \n", car); printf("Product= %08lX\n", x * y); mul32(x, y); printf("mul32 upper= %08lX", u); printf(" mul32 lower= %08lX\n", l); printf(" cyc= %08lX\n", ((x << 1) | ((x & BIT31) >> 31)) ); printf(" mul1= %08lX\n", mul1(x, y) ); printf(" mul2= %08lX\n", mul2(x, y) ); printf("mul2a= %08lX\n", mul2a(x, y) ); byt(x, y); printf("byt upper= %08lX", u); printf(" byt lower= %08lX\n", l); printf(" pat= %X\n", pat); }; break; case 2: { printf(" Enter J1 (8 hex): "); scanf("%lX", &x); printf(" Enter K1 (8 hex): "); scanf("%lX", &y); prelude(x, y, 1); }; break; case 3: { inmain(); mainloop1(m); z = x ^ y; printf("Z= %08lX\n", z); }; break; case 4: { printf(" Enter J (8 hex): "); scanf("%lX", &x); printf(" Enter K (8 hex): "); scanf("%lX", &y); prelude(x, y, 0); x = x0; y = y0; v = v0; abcd(); do { printf(" Enter M (8 hex): "); scanf("%lX", &m); mainloop2(m); printf("X= %08lX", x); printf(" Y= %08lX\n", y); printf("Press 1 for coda else for another message \n"); } while ( (getch() ) != '1' ); mainloop2(s); printf("X= %08lX", x); printf(" Y= %08lX\n", y); mainloop2(t); printf("X= %08lX", x); printf(" Y= %08lX\n", y); z = x ^ y; printf("Z= %08lX\n", z); }; break; case 5: { printf(" Enter J (8 hex): "); scanf("%lX", &x); printf(" Enter K (8 hex): "); scanf("%lX", &y); prelude(x, y, 0); x = x0; y = y0; v = v0; abcd(); printf(" Enter M (8 hex): "); scanf("%lX", &m); printf(" Enter number of repeated message blocks: "); scanf("%d", &nn); printf(" Press 1 to display X, Y values else to measure time\n"); disp = getch(); if (disp == '1') { for (ii = 1; ii <= nn; ii++) { mainloop2(m); printf("X= %08lX", x); printf(" Y= %08lX\n", y); } printf(" Press a key to proceed \n"); disp = getch(); } else { i = fracsec(); for (ii = 1; ii <= nn; ii++) { mainloop2(m); } tf = guesstime(); printf("Seconds in mainloop (guesstime)= %6.2f\n", tf); i = i; printf(" Milliseconds per message block= %6.2f\n", tf * 1000.0 / nn); } printf("X= %08lX", x); printf(" Y= %08lX\n", y); mainloop2(s); printf("X= %08lX", x); printf(" Y= %08lX\n", y); mainloop2(t); printf("X= %08lX", x); printf(" Y= %08lX\n", y); z = x ^ y; printf("Z= %08lX \n", z); }; break; } } while (choice != 6); } /* main */