void make_InvMixCol_Table(int num, FILE *file, PRUint8 m0, PRUint8 m1, PRUint8 m2, PRUint8 m3) { PRUint16 i; PRUint8 b0, b1, b2, b3; fprintf(file, "#ifdef IS_LITTLE_ENDIAN\n"); fprintf(file, "static const PRUint32 _IMXC%d[256] = \n{\n", num); for (i=0; i<256; i++) { b0 = gf_multiply(i, m0); b1 = gf_multiply(i, m1); b2 = gf_multiply(i, m2); b3 = gf_multiply(i, m3); fprintf(file, "0x%.2x%.2x%.2x%.2x%c%c", b3, b2, b1, b0, (i==255)?' ':',', (i%6==5)?'\n':' '); } fprintf(file, "\n};\n"); fprintf(file, "#else\n"); fprintf(file, "static const PRUint32 _IMXC%d[256] = \n{\n", num); for (i=0; i<256; i++) { b0 = gf_multiply(i, m0); b1 = gf_multiply(i, m1); b2 = gf_multiply(i, m2); b3 = gf_multiply(i, m3); fprintf(file, "0x%.2x%.2x%.2x%.2x%c%c", b0, b1, b2, b3, (i==255)?' ':',', (i%6==5)?'\n':' '); } fprintf(file, "\n};\n"); fprintf(file, "#endif\n\n"); }
void ec_add (ec_point *p, const ec_point *q) /* sets p := p + q */ { gf_point lambda, t, tx, ty, x3; /* first check if there is indeed work to do (q != 0): */ if (q->x[0] != 0 || q->y[0] != 0) { if (p->x[0] != 0 || p->y[0] != 0) { /* p != 0 and q != 0 */ if (gf_equal (p->x, q->x)) { /* either p == q or p == -q: */ if (gf_equal (p->y, q->y)) { /* points are equal; double p: */ ec_double (p); } else { /* must be inverse: result is zero */ /* (should assert that q->y = p->x + p->y) */ p->x[0] = p->y[0] = 0; } } else { /* p != 0, q != 0, p != q, p != -q */ /* evaluate lambda = (y1 + y2)/(x1 + x2): */ gf_add (ty, p->y, q->y); gf_add (tx, p->x, q->x); gf_invert (t, tx); gf_multiply (lambda, ty, t); /* evaluate x3 = lambda^2 + lambda + x1 + x2: */ gf_square (x3, lambda); gf_add (x3, x3, lambda); gf_add (x3, x3, tx); /* evaluate y3 = lambda*(x1 + x3) + x3 + y1: */ gf_add (tx, p->x, x3); gf_multiply (t, lambda, tx); gf_add (t, t, x3); gf_add (p->y, t, p->y); /* deposit the value of x3: */ gf_copy (p->x, x3); } } else { /* just copy q into p: */ gf_copy (p->x, q->x); gf_copy (p->y, q->y); } } } /* ec_add */
int ec_calcy (ec_point *p, int ybit) /* given the x coordinate of p, evaluate y such that y^2 + x*y = x^3 + EC_B */ { gf_point a, b, t; b[0] = 1; b[1] = EC_B; if (p->x[0] == 0) { /* elliptic equation reduces to y^2 = EC_B: */ gf_squareroot (p->y, EC_B); return 1; } /* evaluate alpha = x^3 + b = (x^2)*x + EC_B: */ gf_square (t, p->x); /* keep t = x^2 for beta evaluation */ gf_multiply (a, t, p->x); gf_add (a, a, b); /* now a == alpha */ if (a[0] == 0) { p->y[0] = 0; /* destroy potentially sensitive data: */ gf_clear (a); gf_clear (t); return 1; } /* evaluate beta = alpha/x^2 = x + EC_B/x^2 */ gf_smalldiv (t, EC_B); gf_invert (a, t); gf_add (a, p->x, a); /* now a == beta */ /* check if a solution exists: */ if (gf_trace (a) != 0) { /* destroy potentially sensitive data: */ gf_clear (a); gf_clear (t); return 0; /* no solution */ } /* solve equation t^2 + t + beta = 0 so that gf_ybit(t) == ybit: */ gf_quadsolve (t, a); if (gf_ybit (t) != ybit) { t[1] ^= 1; } /* compute y = x*t: */ gf_multiply (p->y, p->x, t); /* destroy potentially sensitive data: */ gf_clear (a); gf_clear (t); return 1; } /* ec_calcy */
void ec_double (ec_point *p) /* sets p := 2*p */ { gf_point lambda, t1, t2; /* evaluate lambda = x + y/x: */ gf_invert (t1, p->x); gf_multiply (lambda, p->y, t1); gf_add (lambda, lambda, p->x); /* evaluate x3 = lambda^2 + lambda: */ gf_square (t1, lambda); gf_add (t1, t1, lambda); /* now t1 = x3 */ /* evaluate y3 = x^2 + lambda*x3 + x3: */ gf_square (p->y, p->x); gf_multiply (t2, lambda, t1); gf_add (p->y, p->y, t2); gf_add (p->y, p->y, t1); /* deposit the value of x3: */ gf_copy (p->x, t1); } /* ec_double */
int ec_ybit (const ec_point *p) /* evaluates to 0 if p->x == 0, otherwise to gf_ybit (p->y / p->x) */ { gf_point t1, t2; if (p->x[0] == 0) { return 0; } else { gf_invert (t1, p->x); gf_multiply (t2, p->y, t1); return gf_ybit (t2); } } /* ec_ybit */
void make_T_Table(char *table, const PRUint8 Sx[256], FILE *file, unsigned char m0, unsigned char m1, unsigned char m2, unsigned char m3) { PRUint32 Ti; int i; fprintf(file, "#ifdef IS_LITTLE_ENDIAN\n"); fprintf(file, "static const PRUint32 _T%s[256] = \n{\n", table); for (i=0; i<256; i++) { Ti = WORD_LE( gf_multiply(Sx[i], m0), gf_multiply(Sx[i], m1), gf_multiply(Sx[i], m2), gf_multiply(Sx[i], m3) ); if (Ti == 0) fprintf(file, "0x00000000%c%c", (i==255)?' ':',', (i%6==5)?'\n':' '); else fprintf(file, "%#.8x%c%c", Ti, (i==255)?' ':',', (i%6==5)?'\n':' '); } fprintf(file, "\n};\n"); fprintf(file, "#else\n"); fprintf(file, "static const PRUint32 _T%s[256] = \n{\n", table); for (i=0; i<256; i++) { Ti = WORD_BE( gf_multiply(Sx[i], m0), gf_multiply(Sx[i], m1), gf_multiply(Sx[i], m2), gf_multiply(Sx[i], m3) ); if (Ti == 0) fprintf(file, "0x00000000%c%c", (i==255)?' ':',', (i%6==5)?'\n':' '); else fprintf(file, "%#.8x%c%c", Ti, (i==255)?' ':',', (i%6==5)?'\n':' '); } fprintf(file, "\n};\n"); fprintf(file, "#endif\n\n"); }
int main() { int i, j; PRUint8 cur, last; PRUint32 tmp; FILE *optfile; optfile = fopen("rijndael32.tab", "w"); /* output S, if there are no T tables */ fprintf(optfile, "#ifndef RIJNDAEL_INCLUDE_TABLES\n"); fprintf(optfile, "static const PRUint8 _S[256] = \n{\n"); for (i=0; i<256; i++) { fprintf(optfile, "%3d%c%c", __S[i],(i==255)?' ':',', (i%16==15)?'\n':' '); } fprintf(optfile, "};\n#endif /* not RIJNDAEL_INCLUDE_TABLES */\n\n"); /* output S**-1 */ fprintf(optfile, "static const PRUint8 _SInv[256] = \n{\n"); for (i=0; i<256; i++) { fprintf(optfile, "%3d%c%c", __SInv[i],(i==255)?' ':',', (i%16==15)?'\n':' '); } fprintf(optfile, "};\n\n"); fprintf(optfile, "#ifdef RIJNDAEL_INCLUDE_TABLES\n"); /* The 32-bit word tables for optimized implementation */ /* T0 = [ S[a] * 02, S[a], S[a], S[a] * 03 ] */ make_T_Table("0", __S, optfile, 0x02, 0x01, 0x01, 0x03); /* T1 = [ S[a] * 03, S[a] * 02, S[a], S[a] ] */ make_T_Table("1", __S, optfile, 0x03, 0x02, 0x01, 0x01); /* T2 = [ S[a], S[a] * 03, S[a] * 02, S[a] ] */ make_T_Table("2", __S, optfile, 0x01, 0x03, 0x02, 0x01); /* T3 = [ S[a], S[a], S[a] * 03, S[a] * 02 ] */ make_T_Table("3", __S, optfile, 0x01, 0x01, 0x03, 0x02); /* TInv0 = [ Si[a] * 0E, Si[a] * 09, Si[a] * 0D, Si[a] * 0B ] */ make_T_Table("Inv0", __SInv, optfile, 0x0e, 0x09, 0x0d, 0x0b); /* TInv1 = [ Si[a] * 0B, Si[a] * 0E, Si[a] * 09, Si[a] * 0D ] */ make_T_Table("Inv1", __SInv, optfile, 0x0b, 0x0e, 0x09, 0x0d); /* TInv2 = [ Si[a] * 0D, Si[a] * 0B, Si[a] * 0E, Si[a] * 09 ] */ make_T_Table("Inv2", __SInv, optfile, 0x0d, 0x0b, 0x0e, 0x09); /* TInv3 = [ Si[a] * 09, Si[a] * 0D, Si[a] * 0B, Si[a] * 0E ] */ make_T_Table("Inv3", __SInv, optfile, 0x09, 0x0d, 0x0b, 0x0e); /* byte multiply tables for inverse key expansion (mimics InvMixColumn) */ make_InvMixCol_Table(0, optfile, 0x0e, 0x09, 0x0d, 0x0b); make_InvMixCol_Table(1, optfile, 0x0b, 0x0E, 0x09, 0x0d); make_InvMixCol_Table(2, optfile, 0x0d, 0x0b, 0x0e, 0x09); make_InvMixCol_Table(3, optfile, 0x09, 0x0d, 0x0b, 0x0e); fprintf(optfile, "#endif /* RIJNDAEL_INCLUDE_TABLES */\n\n"); /* round constants for key expansion */ fprintf(optfile, "#ifdef IS_LITTLE_ENDIAN\n"); fprintf(optfile, "static const PRUint32 Rcon[30] = {\n"); cur = 0x01; for (i=0; i<30; i++) { fprintf(optfile, "%#.8x%c%c", WORD_LE(cur, 0, 0, 0), (i==29)?' ':',', (i%6==5)?'\n':' '); last = cur; cur = gf_multiply(last, 0x02); } fprintf(optfile, "};\n"); fprintf(optfile, "#else\n"); fprintf(optfile, "static const PRUint32 Rcon[30] = {\n"); cur = 0x01; for (i=0; i<30; i++) { fprintf(optfile, "%#.8x%c%c", WORD_BE(cur, 0, 0, 0), (i==29)?' ':',', (i%6==5)?'\n':' '); last = cur; cur = gf_multiply(last, 0x02); } fprintf(optfile, "};\n"); fprintf(optfile, "#endif\n\n"); fclose(optfile); return 0; }