\Encryption\polynominal
poly_func.c
/****************************************************************
* *
* periferal functions useful for setting up polynomial *
* math but not called routinely. *
* *
****************************************************************/
#include "field2n.h"
#include "poly.h"
/* for given irreducible polynomial solve g^3 = g + 1.
Useful for GF(8^n) Koblitz curves.
Trick is to lineraize equation into form g^4 + g^2 + g = 0.
This is linear because (a + b)^(2^n) = a^(2^n) + b^(2^n).
There are four solutions: one is zero, two are found as
independent vectors and the third is their sum.
Input: pointers to irreducble polynomial and g[3]
Output: g[0], g[1], and g[3] = g[0] + g[1] filled in
*/
void poly_gf8( prime, g)
FIELD2N *prime, g[3];
{
FIELD2N gamma_matrix[NUMBITS], solve[NUMBITS];
FIELD2N power_table[4*NUMBITS], temp;
INDEX row, column, i, j, found, vector;
ELEMENT tobit, frombit, bit, null_check;
/* step 1: compute all powers of x modulo prime polynomial
with simple function */
null( &power_table[0]);
power_table[0].e[NUMWORD] = 1L;
for (row = 1; row < 4*NUMBITS; row++)
mul_x_mod( &power_table[row-1], prime, &power_table[row]);
/* step 2: sum powers of rows to create g^4 + g^2 + g
coefficients matrix.
*/
for( row=0; row < NUMBITS; row++)
{
copy( &power_table[row], &gamma_matrix[row]);
SUMLOOP (i) gamma_matrix[row].e[i] ^=
power_table[row<<1].e[i] ^ power_table[row<<2].e[i];
}
/* step 3: transpose matrix and work with single powers of x */
for ( row=0; row < NUMBITS; row++) null( &solve[row]);
for ( row=0; row < NUMBITS; row++)
{
bit = 1L << (row % WORDSIZE);
i = NUMWORD - (row/WORDSIZE);
frombit = 1;
j = NUMWORD;
for ( column = 0; column < NUMBITS; column++)
{
if (gamma_matrix[row].e[j] & frombit)
solve[column].e[i] |= bit;
frombit <<= 1;
if ( !frombit)
{
frombit = 1;
j--;
}
}
}
/* step 4: lower diagonalize solve matrix.
2 columns will go null, search for null rows instead
of diagnalizing. */
vector = 0; /* set up solution space */
null( &g[0]);
null( &g[1]);
for (column = NUMBITS - 1; column > 0; column--)
{
bit = 1L << (column % WORDSIZE);
i = NUMWORD - column/WORDSIZE;
if ( !(bit & solve[column].e[i]) )
{
/* go look for a bit set in this column */
found = 0;
for (row = column - 1; row >= 0; row--)
{
if ( bit & solve[row].e[i])
{
copy ( &solve[row], &temp);
copy ( &solve[column], &solve[row]);
copy ( &temp, &solve[column]);
found = 1;
break;
}
}
}
else found = 1;
/* and eliminate any set bits below it */
if (found)
{
for ( row = column-1; row >=0; row--)
{
if (solve[row].e[i] & bit)
SUMLOOP (j) solve[row].e[j] ^= solve[column].e[j];
}
}
else
{
/* if null column, see if we have null row to match it. */
null_check = 0;
SUMLOOP (j) null_check |= solve[column].e[j];
if ( null_check)
{
/* search for a null row to put here */
for ( row = column-1; row >=0; row--)
{
null_check = 0;
SUMLOOP (j) null_check |= solve[row].e[j];
if ( !null_check)
{
copy ( &solve[row], &temp);
copy ( &solve[column], &solve[row]);
copy ( &temp, &solve[column]);
break;
}
}
}
/* mark this vector with column bit, and use next vector */
g[vector].e[i] |= bit;
vector++;
}
}
/* last row may be null and not marked. if INDEX vector < 2,
set g[1] = 1
*/
if (vector < 2) g[1].e[NUMWORD] = 1;
/* find two solution vectors by back solving matrix. use bits
previoiusly solved to find bits not yet solved. Initial vectors
come from assuming g0 and g1 are variables.
*/
for ( row=1; row= 0; column--)
{
frombit = 1L << (column % WORDSIZE);
i = NUMWORD - column/WORDSIZE;
if ( solve[row].e[i] & frombit)
{
if (g[0].e[i] & frombit) g[0].e[j] ^= tobit;
if (g[1].e[i] & frombit) g[1].e[j] ^= tobit;
}
}
}
}
/* last step: g[2] = g[1] + g[0] */
SUMLOOP (i) g[2].e[i] = g[0].e[i] ^ g[1].e[i];
}