1022 lines
24 KiB
C
1022 lines
24 KiB
C
/* Author: Michael Scott */
|
|
/* Date: Dec 2007 */
|
|
/* Even Faster Duursma-Lee char 2 Tate pairing based on eta_T pairing */
|
|
/* See MIRACL dl2.cpp for more readable C++ version */
|
|
/* cl /O2 etat271.c miracl.lib */
|
|
/* 8-bit version */
|
|
/* Half sized loop so nearly twice as fast! */
|
|
|
|
/* MIRACL mirdef.h
|
|
* For Atmel AVR (e.g. ATmega128L) set up mirdef.h as follows
|
|
|
|
#define MR_LITTLE_ENDIAN
|
|
#define MIRACL 8
|
|
#define mr_utype char
|
|
#define MR_IBITS 16
|
|
#define MR_LBITS 32
|
|
#define mr_unsign32 unsigned long
|
|
#define mr_dltype int
|
|
#define MR_STATIC 34
|
|
#define MR_ALWAYS_BINARY
|
|
#define MR_NOASM
|
|
#define MR_STRIPPED_DOWN
|
|
#define MR_GENERIC_MT
|
|
#define MAXBASE ((mr_small)1<<(MIRACL-1))
|
|
#define MR_BITSINCHAR 8
|
|
#define MR_NOKOBLITZ
|
|
#define MR_NO_STANDARD_IO
|
|
#define MR_NO_FILE_IO
|
|
#define MR_SIMPLE_BASE
|
|
#define MR_SIMPLE_IO
|
|
#define MR_AVR
|
|
#define SP271
|
|
|
|
*/
|
|
|
|
/* use this mirdef.h to mimic 8-bit implementation on a PC
|
|
#define MR_LITTLE_ENDIAN
|
|
#define MIRACL 8
|
|
#define mr_utype char
|
|
#define MR_IBITS 32
|
|
#define MR_LBITS 32
|
|
#define mr_unsign32 unsigned int
|
|
#define mr_dltype short
|
|
#define MR_STATIC 34
|
|
#define MR_ALWAYS_BINARY
|
|
#define MR_NOASM
|
|
#define MR_STRIPPED_DOWN
|
|
#define MR_GENERIC_MT
|
|
#define MAXBASE ((mr_small)1<<(MIRACL-1))
|
|
#define MR_BITSINCHAR 8
|
|
#define MR_NOKOBLITZ
|
|
|
|
*/
|
|
|
|
/* rem build using this batch file for PC
|
|
rem Compile MIRACL modules
|
|
cl /c /O2 /W3 mrcore.c
|
|
cl /c /O2 /W3 mrarth0.c
|
|
cl /c /O2 /W3 mrarth1.c
|
|
cl /c /O2 /W3 mrio1.c
|
|
cl /c /O2 /W3 mrbits.c
|
|
cl /c /O2 /W3 mrgf2m.c
|
|
cl /c /O2 /W3 mrec2m.c
|
|
|
|
rem
|
|
rem Create library 'miracl.lib'
|
|
del miracl.lib
|
|
|
|
lib /OUT:miracl.lib mrio1.obj
|
|
lib /OUT:miracl.lib miracl.lib mrbits.obj
|
|
lib /OUT:miracl.lib miracl.lib mrarth0.obj mrarth1.obj mrcore.obj
|
|
lib /OUT:miracl.lib miracl.lib mrec2m.obj mrgf2m.obj
|
|
del mr*.obj
|
|
|
|
cl /O2 etat271.c miracl.lib
|
|
|
|
On the ARM use a header like
|
|
|
|
#define MR_LITTLE_ENDIAN
|
|
#define MIRACL 32
|
|
#define mr_utype int
|
|
#define MR_IBITS 32
|
|
#define MR_LBITS 32
|
|
#define mr_unsign32 unsigned int
|
|
#define mr_dltype long long
|
|
#define MR_STATIC 9
|
|
#define MR_ALWAYS_BINARY
|
|
#define MR_NOASM
|
|
#define MR_STRIPPED_DOWN
|
|
#define MR_GENERIC_MT
|
|
#define MAXBASE ((mr_small)1<<(MIRACL-1))
|
|
#define MR_BITSINCHAR 8
|
|
#define MR_NOKOBLITZ
|
|
|
|
|
|
/* define one curve or the other.. */
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "miracl.h"
|
|
|
|
#define M 271
|
|
#define T 207
|
|
#define U 175
|
|
#define V 111
|
|
|
|
#define B 0
|
|
#define TYPE 1
|
|
|
|
/* points P and Q from ROM */
|
|
|
|
/* WORDS = number of words needs to store GF(2^m) = size of bigs */
|
|
|
|
/* elements of GF(2^m) are stored in bigs */
|
|
/* elements of the quartic extension field GF(2^{4m}) are stored as an array of 4 bigs */
|
|
/* = {a,b,c,d} = d.X^3+c.X^2+b.X+a */
|
|
|
|
/* fast inlined addition code */
|
|
|
|
#if MIRACL==64
|
|
|
|
#define WORDS 5
|
|
#define NPW 16 /* nibbles per word */
|
|
#define ROMSZ 20
|
|
|
|
static const mr_small rom[]={
|
|
0x591B401498D66271,0xA16F0C4E5357F2F6,0xD76AEF912696E510,0x75C041258C778D1D,0x10B1,
|
|
0x80DC7F385B9C26BF,0x2B65C2A7BAF3B9FD,0x6A84C19620F8D8B9,0x6D0DB856E16E7097,0x7C02,
|
|
0x4EDF428FD0EE2151,0x8A4509E6D6013138,0xBB5FBE66F7C468E7,0xA2740AF91652325E,0x2C67,
|
|
0x329B869A3E833026,0xB3716EC7D5F80608,0x3EE35C892B03AE59,0x5AF93E7449ABB134,0x48FB
|
|
};
|
|
|
|
void fincr2(big a,big c)
|
|
{
|
|
mr_small *aa,*cc;
|
|
aa=a->w; cc=c->w;
|
|
|
|
cc[0]^=aa[0];
|
|
cc[1]^=aa[1];
|
|
cc[2]^=aa[2];
|
|
cc[3]^=aa[3];
|
|
cc[4]^=aa[4];
|
|
|
|
c->len=WORDS;
|
|
if (cc[4]==0) mr_lzero(c);
|
|
}
|
|
|
|
void fadd2(big a,big b,big c)
|
|
{
|
|
mr_small *aa,*bb,*cc;
|
|
aa=a->w; bb=b->w; cc=c->w;
|
|
|
|
cc[0]=aa[0]^bb[0];
|
|
cc[1]=aa[1]^bb[1];
|
|
cc[2]=aa[2]^bb[2];
|
|
cc[3]=aa[3]^bb[3];
|
|
cc[4]=aa[4]^bb[4];
|
|
|
|
c->len=WORDS;
|
|
if (cc[4]==0) mr_lzero(c);
|
|
}
|
|
|
|
/* fast inlined copy code - replaces copy(.) */
|
|
|
|
void fcopy2(big a,big b)
|
|
{
|
|
mr_small *aa,*bb;
|
|
aa=a->w; bb=b->w;
|
|
|
|
bb[0]=aa[0];
|
|
bb[1]=aa[1];
|
|
bb[2]=aa[2];
|
|
bb[3]=aa[3];
|
|
bb[4]=aa[4];
|
|
|
|
b->len=a->len;
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
#if MIRACL==32
|
|
|
|
#define WORDS 9
|
|
#define NPW 8 /* nibbles per word */
|
|
#define ROMSZ 36
|
|
|
|
static const mr_small rom[]={
|
|
0x98D66271,0x591B4014,0x5357F2F6,0xA16F0C4E,0x2696E510,0xD76AEF91,0x8C778D1D,0x75C04125,0x10B1,
|
|
0x5B9C26BF,0x80DC7F38,0xBAF3B9FD,0x2B65C2A7,0x20F8D8B9,0x6A84C196,0xE16E7097,0x6D0DB856,0x7C02,
|
|
0xD0EE2151,0x4EDF428F,0xD6013138,0x8A4509E6,0xF7C468E7,0xBB5FBE66,0x1652325E,0xA2740AF9,0x2C67,
|
|
0x3E833026,0x329B869A,0xD5F80608,0xB3716EC7,0x2B03AE59,0x3EE35C89,0x49ABB134,0x5AF93E74,0x48FB
|
|
};
|
|
|
|
void fincr2(big a,big c)
|
|
{
|
|
mr_small *aa,*cc;
|
|
aa=a->w; cc=c->w;
|
|
|
|
cc[0]^=aa[0];
|
|
cc[1]^=aa[1];
|
|
cc[2]^=aa[2];
|
|
cc[3]^=aa[3];
|
|
cc[4]^=aa[4];
|
|
cc[5]^=aa[5];
|
|
cc[6]^=aa[6];
|
|
cc[7]^=aa[7];
|
|
cc[8]^=aa[8];
|
|
|
|
|
|
c->len=WORDS;
|
|
if (cc[8]==0) mr_lzero(c);
|
|
}
|
|
|
|
void fadd2(big a,big b,big c)
|
|
{
|
|
mr_small *aa,*bb,*cc;
|
|
aa=a->w; bb=b->w; cc=c->w;
|
|
|
|
cc[0]=aa[0]^bb[0];
|
|
cc[1]=aa[1]^bb[1];
|
|
cc[2]=aa[2]^bb[2];
|
|
cc[3]=aa[3]^bb[3];
|
|
cc[4]=aa[4]^bb[4];
|
|
cc[5]=aa[5]^bb[5];
|
|
cc[6]=aa[6]^bb[6];
|
|
cc[7]=aa[7]^bb[7];
|
|
cc[8]=aa[8]^bb[8];
|
|
|
|
c->len=WORDS;
|
|
if (cc[8]==0) mr_lzero(c);
|
|
}
|
|
|
|
/* fast inlined copy code - replaces copy(.) */
|
|
|
|
void fcopy2(big a,big b)
|
|
{
|
|
mr_small *aa,*bb;
|
|
aa=a->w; bb=b->w;
|
|
|
|
bb[0]=aa[0];
|
|
bb[1]=aa[1];
|
|
bb[2]=aa[2];
|
|
bb[3]=aa[3];
|
|
bb[4]=aa[4];
|
|
bb[5]=aa[5];
|
|
bb[6]=aa[6];
|
|
bb[7]=aa[7];
|
|
bb[8]=aa[8];
|
|
|
|
b->len=a->len;
|
|
}
|
|
|
|
#endif
|
|
|
|
#if MIRACL==8
|
|
|
|
#define WORDS 34
|
|
#define NPW 2
|
|
#define ROMSZ 136
|
|
|
|
/* For Pentanomial x^271+x^207+x^175+x^111+1 */
|
|
|
|
#ifdef MR_AVR
|
|
__attribute__((__progmem__))
|
|
#endif
|
|
static const mr_small rom[]={
|
|
0x71,0x62,0xD6,0x98,0x14,0x40,0x1B,0x59,0xF6,0xF2,0x57,0x53,0x4E,0xC,0x6F,0xA1,0x10,0xE5,0x96,0x26,0x91,0xEF,0x6A,0xD7,0x1D,0x8D,0x77,0x8C,0x25,0x41,0xC0,0x75,0xB1,0x10,
|
|
0xBF,0x26,0x9C,0x5B,0x38,0x7F,0xDC,0x80,0xFD,0xB9,0xF3,0xBA,0xA7,0xC2,0x65,0x2B,0xB9,0xD8,0xF8,0x20,0x96,0xC1,0x84,0x6A,0x97,0x70,0x6E,0xE1,0x56,0xB8,0xD,0x6D,0x2,0x7C,
|
|
0x51,0x21,0xEE,0xD0,0x8F,0x42,0xDF,0x4E,0x38,0x31,0x1,0xD6,0xE6,0x9,0x45,0x8A,0xE7,0x68,0xC4,0xF7,0x66,0xBE,0x5F,0xBB,0x5E,0x32,0x52,0x16,0xF9,0xA,0x74,0xA2,0x67,0x2C,
|
|
0x26,0x30,0x83,0x3E,0x9A,0x86,0x9B,0x32,0x8,0x6,0xF8,0xD5,0xC7,0x6E,0x71,0xB3,0x59,0xAE,0x3,0x2B,0x89,0x5C,0xE3,0x3E,0x34,0xB1,0xAB,0x49,0x74,0x3E,0xF9,0x5A,0xFB,0x48
|
|
};
|
|
|
|
void fincr2(big a,big c)
|
|
{
|
|
mr_small *aa,*cc;
|
|
aa=a->w; cc=c->w;
|
|
|
|
cc[0]^=aa[0];
|
|
cc[1]^=aa[1];
|
|
cc[2]^=aa[2];
|
|
cc[3]^=aa[3];
|
|
cc[4]^=aa[4];
|
|
cc[5]^=aa[5];
|
|
cc[6]^=aa[6];
|
|
cc[7]^=aa[7];
|
|
cc[8]^=aa[8];
|
|
cc[9]^=aa[9];
|
|
cc[10]^=aa[10];
|
|
cc[11]^=aa[11];
|
|
cc[12]^=aa[12];
|
|
cc[13]^=aa[13];
|
|
cc[14]^=aa[14];
|
|
cc[15]^=aa[15];
|
|
cc[16]^=aa[16];
|
|
cc[17]^=aa[17];
|
|
cc[18]^=aa[18];
|
|
cc[19]^=aa[19];
|
|
cc[20]^=aa[20];
|
|
cc[21]^=aa[21];
|
|
cc[22]^=aa[22];
|
|
cc[23]^=aa[23];
|
|
cc[24]^=aa[24];
|
|
cc[25]^=aa[25];
|
|
cc[26]^=aa[26];
|
|
cc[27]^=aa[27];
|
|
cc[28]^=aa[28];
|
|
cc[29]^=aa[29];
|
|
cc[30]^=aa[30];
|
|
cc[31]^=aa[31];
|
|
cc[32]^=aa[32];
|
|
cc[33]^=aa[33];
|
|
|
|
c->len=WORDS;
|
|
if (cc[33]==0) mr_lzero(c);
|
|
}
|
|
|
|
void fadd2(big a,big b,big c)
|
|
{
|
|
mr_small *aa,*bb,*cc;
|
|
aa=a->w; bb=b->w; cc=c->w;
|
|
|
|
cc[0]=aa[0]^bb[0];
|
|
cc[1]=aa[1]^bb[1];
|
|
cc[2]=aa[2]^bb[2];
|
|
cc[3]=aa[3]^bb[3];
|
|
cc[4]=aa[4]^bb[4];
|
|
cc[5]=aa[5]^bb[5];
|
|
cc[6]=aa[6]^bb[6];
|
|
cc[7]=aa[7]^bb[7];
|
|
cc[8]=aa[8]^bb[8];
|
|
cc[9]=aa[9]^bb[9];
|
|
cc[10]=aa[10]^bb[10];
|
|
cc[11]=aa[11]^bb[11];
|
|
cc[12]=aa[12]^bb[12];
|
|
cc[13]=aa[13]^bb[13];
|
|
cc[14]=aa[14]^bb[14];
|
|
cc[15]=aa[15]^bb[15];
|
|
cc[16]=aa[16]^bb[16];
|
|
cc[17]=aa[17]^bb[17];
|
|
cc[18]=aa[18]^bb[18];
|
|
cc[19]=aa[19]^bb[19];
|
|
cc[20]=aa[20]^bb[20];
|
|
cc[21]=aa[21]^bb[21];
|
|
cc[22]=aa[22]^bb[22];
|
|
cc[23]=aa[23]^bb[23];
|
|
cc[24]=aa[24]^bb[24];
|
|
cc[25]=aa[25]^bb[25];
|
|
cc[26]=aa[26]^bb[26];
|
|
cc[27]=aa[27]^bb[27];
|
|
cc[28]=aa[28]^bb[28];
|
|
cc[29]=aa[29]^bb[29];
|
|
cc[30]=aa[30]^bb[30];
|
|
cc[31]=aa[31]^bb[31];
|
|
cc[32]=aa[32]^bb[32];
|
|
cc[33]=aa[33]^bb[33];
|
|
|
|
c->len=WORDS;
|
|
if (cc[33]==0) mr_lzero(c);
|
|
}
|
|
|
|
/* fast inlined copy code - replaces copy(.) */
|
|
|
|
void fcopy2(big a,big b)
|
|
{
|
|
mr_small *aa,*bb;
|
|
aa=a->w; bb=b->w;
|
|
|
|
bb[0]=aa[0];
|
|
bb[1]=aa[1];
|
|
bb[2]=aa[2];
|
|
bb[3]=aa[3];
|
|
bb[4]=aa[4];
|
|
bb[5]=aa[5];
|
|
bb[6]=aa[6];
|
|
bb[7]=aa[7];
|
|
bb[8]=aa[8];
|
|
bb[9]=aa[9];
|
|
bb[10]=aa[10];
|
|
bb[11]=aa[11];
|
|
bb[12]=aa[12];
|
|
bb[13]=aa[13];
|
|
bb[14]=aa[14];
|
|
bb[15]=aa[15];
|
|
bb[16]=aa[16];
|
|
bb[17]=aa[17];
|
|
bb[18]=aa[18];
|
|
bb[19]=aa[19];
|
|
bb[20]=aa[20];
|
|
bb[21]=aa[21];
|
|
bb[22]=aa[22];
|
|
bb[23]=aa[23];
|
|
bb[24]=aa[24];
|
|
bb[25]=aa[25];
|
|
bb[26]=aa[26];
|
|
bb[27]=aa[27];
|
|
bb[28]=aa[28];
|
|
bb[29]=aa[29];
|
|
bb[30]=aa[30];
|
|
bb[31]=aa[31];
|
|
bb[32]=aa[32];
|
|
bb[33]=aa[33];
|
|
|
|
b->len=a->len;
|
|
}
|
|
|
|
#endif
|
|
|
|
/* Use internal workspace variables w1-w13 - must be careful doing this! - see comment below */
|
|
|
|
void mul(_MIPD_ big *a,big *b,big *r)
|
|
{
|
|
/* Special multiplier for GF(2^{4m}) values of the form (x,y,y+1,0) */
|
|
|
|
fcopy2(a[1],mr_mip->w2);
|
|
fcopy2(b[1],mr_mip->w3);
|
|
fadd2(a[1],a[0],mr_mip->w8); /* e=w+p */
|
|
fadd2(b[1],b[0],mr_mip->w9); /* s=t+q */
|
|
|
|
/* only 3 modmults.. */
|
|
|
|
modmult2(_MIPP_ mr_mip->w9,mr_mip->w8,mr_mip->w9); /* z=(w+p)*(t+q) */
|
|
modmult2(_MIPP_ mr_mip->w3,mr_mip->w2,mr_mip->w4); /* tw=t*w */
|
|
modmult2(_MIPP_ a[0],b[0],mr_mip->w8); /* pq=p*q */
|
|
fincr2(mr_mip->w4,mr_mip->w9); /* z+=tw */
|
|
fincr2(mr_mip->w8,mr_mip->w9); /* z+=pq */
|
|
fincr2(mr_mip->w3,mr_mip->w2); /* w+=t */
|
|
fadd2(mr_mip->w2,mr_mip->w4,mr_mip->w3); /* t=w+tw */
|
|
incr2(mr_mip->w3,1,mr_mip->w3); /* t=w+tw+1 */
|
|
|
|
fadd2(mr_mip->w9,a[0],mr_mip->w12); /* x=z+p */
|
|
fincr2(b[0],mr_mip->w12); /* x=z+p+q */
|
|
|
|
fadd2(mr_mip->w8,mr_mip->w3,r[0]); /* r[0]=pq+t */
|
|
fadd2(mr_mip->w9,mr_mip->w3,r[1]); /* r[1]=z+t */
|
|
fadd2(mr_mip->w12,mr_mip->w4,r[2]); /* r[2]=z+p+q+tw */
|
|
fcopy2(mr_mip->w2,r[3]); /* r[3]=w */
|
|
}
|
|
|
|
/* squaring GF(2^{4m}) values */
|
|
|
|
void square4(_MIPD_ big *a,big *c)
|
|
{
|
|
if (a!=c)
|
|
{
|
|
fcopy2(a[0],c[0]);
|
|
fcopy2(a[1],c[1]);
|
|
fcopy2(a[2],c[2]);
|
|
fcopy2(a[3],c[3]);
|
|
}
|
|
|
|
modsquare2(_MIPP_ c[3],c[3]);
|
|
fcopy2(c[2],mr_mip->w1);
|
|
modsquare2(_MIPP_ mr_mip->w1,mr_mip->w1);
|
|
fcopy2(c[1],c[2]);
|
|
modsquare2(_MIPP_ c[2],c[2]);
|
|
modsquare2(_MIPP_ c[0],c[0]);
|
|
fincr2(c[3],c[2]);
|
|
fincr2(mr_mip->w1,c[0]);
|
|
fcopy2(mr_mip->w1,c[1]);
|
|
|
|
return;
|
|
}
|
|
|
|
/* multiplying general GF(2^{4m}) values */
|
|
/* Uses karatsuba - 9 modmults - very time critical */
|
|
/* Use internal workspace variables w1-w13 - must be careful doing this! */
|
|
/* The thing is to ensure that none of the invoked miracl internal routines are using the same variables */
|
|
/* So first check the miracl source code.... I did... Its OK ... */
|
|
|
|
void mult4(_MIPD_ big *a,big *b,big *c)
|
|
{
|
|
fadd2(a[1],a[3],mr_mip->w3);
|
|
fadd2(a[0],a[2],mr_mip->w4);
|
|
fadd2(b[1],b[3],mr_mip->w8);
|
|
fadd2(b[0],b[2],mr_mip->w9);
|
|
|
|
modmult2(_MIPP_ mr_mip->w8,mr_mip->w3,mr_mip->w10);
|
|
modmult2(_MIPP_ mr_mip->w9,mr_mip->w4,mr_mip->w11);
|
|
modmult2(_MIPP_ a[1],b[1],mr_mip->w2);
|
|
modmult2(_MIPP_ a[2],b[2],mr_mip->w1);
|
|
|
|
fadd2(mr_mip->w2,mr_mip->w1,mr_mip->w13);
|
|
|
|
fadd2(a[1],a[0],c[1]);
|
|
fadd2(b[0],b[1],mr_mip->w12);
|
|
modmult2(_MIPP_ c[1],mr_mip->w12,c[1]);
|
|
modmult2(_MIPP_ a[0],b[0],c[0]);
|
|
fincr2(c[0],c[1]);
|
|
fincr2(mr_mip->w2,c[1]);
|
|
|
|
fcopy2(a[2],c[2]);
|
|
fadd2(a[2],a[3],mr_mip->w12);
|
|
fadd2(b[2],b[3],mr_mip->w2);
|
|
modmult2(_MIPP_ mr_mip->w12,mr_mip->w2,mr_mip->w12);
|
|
|
|
fincr2(mr_mip->w12,mr_mip->w1);
|
|
modmult2(_MIPP_ a[3],b[3],mr_mip->w2);
|
|
fincr2(mr_mip->w2,mr_mip->w1);
|
|
|
|
fadd2(mr_mip->w9,mr_mip->w8,mr_mip->w12);
|
|
fcopy2(mr_mip->w12,c[3]);
|
|
fadd2(mr_mip->w4,mr_mip->w3,mr_mip->w12);
|
|
modmult2(_MIPP_ c[3],mr_mip->w12,c[3]);
|
|
|
|
fincr2(mr_mip->w2,mr_mip->w1);
|
|
|
|
fincr2(mr_mip->w10,c[3]);
|
|
fincr2(mr_mip->w11,c[3]);
|
|
fincr2(mr_mip->w1,c[3]);
|
|
fincr2(c[1],c[3]);
|
|
|
|
fadd2(mr_mip->w13,c[0],c[2]);
|
|
fincr2(mr_mip->w11,c[2]);
|
|
fincr2(mr_mip->w1,c[2]);
|
|
|
|
fincr2(mr_mip->w1,c[1]);
|
|
fincr2(mr_mip->w10,mr_mip->w13);
|
|
fincr2(mr_mip->w13,c[1]);
|
|
|
|
fincr2(mr_mip->w2,mr_mip->w13);
|
|
fincr2(mr_mip->w13,c[0]);
|
|
|
|
return;
|
|
}
|
|
|
|
/* Frobenius action - GF(2^{4m}) ^ 2^m */
|
|
|
|
void powq(_MIPD_ big *x)
|
|
{
|
|
fcopy2(x[1],mr_mip->w1);
|
|
fincr2(x[1],x[0]);
|
|
fcopy2(x[2],x[1]);
|
|
fincr2(x[3],x[1]);
|
|
fcopy2(mr_mip->w1,x[2]);
|
|
}
|
|
|
|
/* return degree of GF(2^{4m}) polynomial */
|
|
|
|
int degree(big *c)
|
|
{
|
|
if (size(c[3])!=0) return 3;
|
|
if (size(c[2])!=0) return 2;
|
|
if (size(c[1])!=0) return 1;
|
|
return 0;
|
|
}
|
|
|
|
/* Raise a GF(2^{4m}) to a power */
|
|
|
|
void power4(_MIPD_ big *a,big k,big *u)
|
|
{
|
|
int i,j,m,nb,n,nbw,nzs;
|
|
big u2[4],t[4][4];
|
|
#ifndef MR_STATIC
|
|
char *mem=(char *)memalloc(_MIPP_ 20);
|
|
#else
|
|
char mem[MR_BIG_RESERVE(20)];
|
|
memset(mem,0,MR_BIG_RESERVE(20));
|
|
#endif
|
|
m=0;
|
|
for (i=0;i<4;i++)
|
|
for (j=0;j<4;j++) t[i][j]=mirvar_mem(_MIPP_ mem,m++);
|
|
|
|
u2[0]=mirvar_mem(_MIPP_ mem,16);
|
|
u2[1]=mirvar_mem(_MIPP_ mem,17);
|
|
u2[2]=mirvar_mem(_MIPP_ mem,18);
|
|
u2[3]=mirvar_mem(_MIPP_ mem,19);
|
|
|
|
if(size(k)==0)
|
|
{
|
|
convert(_MIPP_ 1,u[0]);
|
|
zero(u[1]);
|
|
zero(u[2]);
|
|
zero(u[3]);
|
|
#ifndef MR_STATIC
|
|
memkill(_MIPP_ mem,20);
|
|
#else
|
|
memset(mem,0,MR_BIG_RESERVE(20));
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
for (i=0;i<4;i++)
|
|
fcopy2(a[i],u[i]);
|
|
|
|
if (size(k)==1)
|
|
{
|
|
#ifndef MR_STATIC
|
|
memkill(_MIPP_ mem,20);
|
|
#else
|
|
memset(mem,0,MR_BIG_RESERVE(20));
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
square4(_MIPP_ u,u2);
|
|
for (i=0;i<4;i++)
|
|
fcopy2(u[i],t[0][i]);
|
|
|
|
for(i=1;i<4;i++)
|
|
mult4(_MIPP_ u2,t[i-1],t[i]);
|
|
|
|
nb=logb2(_MIPP_ k);
|
|
if(nb>1) for(i=nb-2;i>=0;)
|
|
{
|
|
n=mr_window(_MIPP_ k,i,&nbw,&nzs,3); /* small 3 bit window to save RAM */
|
|
for(j=0;j<nbw;j++)
|
|
square4(_MIPP_ u,u);
|
|
if(n>0) mult4(_MIPP_ u,t[n/2],u);
|
|
i-=nbw;
|
|
if(nzs!=0)
|
|
{
|
|
for (j=0;j<nzs;j++) square4(_MIPP_ u,u);
|
|
i-=nzs;
|
|
}
|
|
}
|
|
|
|
#ifndef MR_STATIC
|
|
memkill(_MIPP_ mem,20);
|
|
#else
|
|
memset(mem,0,MR_BIG_RESERVE(20));
|
|
#endif
|
|
}
|
|
|
|
/* Inversion of GF(2^{4m}) - fast but not time critical */
|
|
|
|
void invert(_MIPD_ big *x)
|
|
{
|
|
int degF,degG,degB,degC,d,i,j;
|
|
big alpha,beta,gamma,BB[4],FF[5],CC[4],GG[5],t;
|
|
big *BP=BB,*CP=CC,*FP=FF,*GP=GG,*TP;
|
|
#ifndef MR_STATIC
|
|
char *mem=(char *)memalloc(_MIPP_ 22);
|
|
#else
|
|
char mem[MR_BIG_RESERVE(22)]; /* 972 bytes from the stack */
|
|
memset(mem,0,MR_BIG_RESERVE(22));
|
|
#endif
|
|
|
|
alpha=mirvar_mem(_MIPP_ mem,0);
|
|
beta=mirvar_mem(_MIPP_ mem,1);
|
|
gamma=mirvar_mem(_MIPP_ mem,2);
|
|
t=mirvar_mem(_MIPP_ mem,3);
|
|
|
|
for (i=0;i<4;i++)
|
|
BB[i]=mirvar_mem(_MIPP_ mem,4+i);
|
|
for (i=0;i<5;i++)
|
|
FF[i]=mirvar_mem(_MIPP_ mem,8+i);
|
|
for (i=0;i<4;i++)
|
|
CC[i]=mirvar_mem(_MIPP_ mem,13+i);
|
|
for (i=0;i<5;i++)
|
|
GG[i]=mirvar_mem(_MIPP_ mem,17+i);
|
|
|
|
convert(_MIPP_ 1,CP[0]);
|
|
convert(_MIPP_ 1,FP[0]);
|
|
convert(_MIPP_ 1,FP[1]);
|
|
convert(_MIPP_ 1,FP[4]); /* F = x^4+x+1 - irreducible polynomial for GF(2^{4m}) */
|
|
|
|
degF=4; degG=degree(x); degC=0; degB=-1;
|
|
|
|
if (degG==0)
|
|
{
|
|
inverse2(_MIPP_ x[0],x[0]);
|
|
return;
|
|
}
|
|
|
|
for (i=0;i<4;i++)
|
|
{
|
|
fcopy2(x[i],GP[i]);
|
|
zero(x[i]);
|
|
}
|
|
|
|
while (degF!=0)
|
|
{
|
|
if (degF<degG)
|
|
{ /* swap */
|
|
TP=FP; FP=GP; GP=TP; d=degF; degF=degG; degG=d;
|
|
TP=BP; BP=CP; CP=TP; d=degB; degB=degC; degC=d;
|
|
}
|
|
j=degF-degG;
|
|
modsquare2(_MIPP_ GP[degG],alpha);
|
|
modmult2(_MIPP_ FP[degF],GP[degG],beta);
|
|
modmult2(_MIPP_ GP[degG],FP[degF-1],t);
|
|
modmult2(_MIPP_ FP[degF],GP[degG-1],gamma);
|
|
fincr2(t,gamma);
|
|
zero(t);
|
|
|
|
for (i=0;i<=degF;i++ )
|
|
{
|
|
modmult2(_MIPP_ FP[i],alpha,FP[i]);
|
|
if (i>=j-1)
|
|
{
|
|
modmult2(_MIPP_ gamma,GP[i-j+1],t);
|
|
fincr2(t,FP[i]);
|
|
}
|
|
if (i>=j)
|
|
{
|
|
modmult2(_MIPP_ beta,GP[i-j],t);
|
|
fincr2(t,FP[i]);
|
|
}
|
|
}
|
|
for (i=0;i<=degB || i<=(degC+j);i++)
|
|
{
|
|
modmult2(_MIPP_ BP[i],alpha,BP[i]);
|
|
if (i>=j-1)
|
|
{
|
|
modmult2(_MIPP_ gamma,CP[i-j+1],t);
|
|
fincr2(t,BP[i]);
|
|
}
|
|
if (i>=j)
|
|
{
|
|
modmult2(_MIPP_ beta,CP[i-j],t);
|
|
fincr2(t,BP[i]);
|
|
}
|
|
}
|
|
|
|
while (degF>=0 && size(FP[degF])==0) degF--;
|
|
if (degF==degG)
|
|
{
|
|
fcopy2(FP[degF],alpha);
|
|
for (i=0;i<=degF;i++)
|
|
{
|
|
modmult2(_MIPP_ FP[i],GP[degF],FP[i]);
|
|
modmult2(_MIPP_ alpha,GP[i],t);
|
|
fincr2(t,FP[i]);
|
|
}
|
|
for (i=0;i<=4-degF;i++)
|
|
{
|
|
modmult2(_MIPP_ BP[i],GP[degF],BP[i]);
|
|
modmult2(_MIPP_ CP[i],alpha,t);
|
|
fincr2(t,BP[i]);
|
|
|
|
}
|
|
while (degF>=0 && size(FP[degF])==0) degF--;
|
|
}
|
|
degB=3;
|
|
while (degB>=0 && size(BP[degB])==0) degB--;
|
|
}
|
|
|
|
inverse2(_MIPP_ FP[0],alpha);
|
|
|
|
for (i=0;i<=degB;i++)
|
|
modmult2(_MIPP_ alpha,BP[i],x[i]);
|
|
#ifndef MR_STATIC
|
|
memkill(_MIPP_ mem,22);
|
|
#else
|
|
memset(mem,0,MR_BIG_RESERVE(22));
|
|
#endif
|
|
}
|
|
|
|
/* Tate Pairing - calculated from eta_T pairing */
|
|
|
|
void eta_T(_MIPD_ epoint *P,epoint *Q,big *f,big *res)
|
|
{
|
|
big xp,yp,xq,yq,t,d;
|
|
big miller[4],v[4],u[4];
|
|
int i,m=M;
|
|
int promptr;
|
|
#ifndef MR_STATIC
|
|
char *mem=(char *)memalloc(_MIPP_ 18);
|
|
#else
|
|
char mem[MR_BIG_RESERVE(18)]; /* 972 bytes from stack */
|
|
memset(mem,0,MR_BIG_RESERVE(18));
|
|
#endif
|
|
|
|
xp=mirvar_mem(_MIPP_ mem,0);
|
|
yp=mirvar_mem(_MIPP_ mem,1);
|
|
xq=mirvar_mem(_MIPP_ mem,2);
|
|
yq=mirvar_mem(_MIPP_ mem,3);
|
|
t=mirvar_mem(_MIPP_ mem,4);
|
|
d=mirvar_mem(_MIPP_ mem,5);
|
|
for (i=0;i<4;i++) miller[i]=mirvar_mem(_MIPP_ mem,6+i);
|
|
for (i=0;i<4;i++) v[i]=mirvar_mem(_MIPP_ mem,10+i);
|
|
for (i=0;i<4;i++) u[i]=mirvar_mem(_MIPP_ mem,14+i);
|
|
|
|
fcopy2(P->X,xp);
|
|
fcopy2(P->Y,yp);
|
|
fcopy2(Q->X,xq);
|
|
fcopy2(Q->Y,yq);
|
|
|
|
incr2(xp,1,t); /* t=xp+1 */
|
|
|
|
fadd2(xp,xq,d);
|
|
incr2(d,1,d); /* xp+xq+1 */
|
|
modmult2(_MIPP_ d,t,d); /* t*(xp+xq+1) */
|
|
fincr2(yp,d);
|
|
fincr2(yq,d);
|
|
incr2(d,B,d);
|
|
incr2(d,1,f[0]); /* f[0]=t*(xp+xq+1)+yp+yq+B+1 */
|
|
|
|
convert(_MIPP_ 1,miller[0]);
|
|
|
|
fadd2(t,xq,f[2]); /* f[2]=t+xq */
|
|
incr2(f[2],1,f[1]); /* f[1]=t+xq+1 */
|
|
zero(f[3]);
|
|
promptr=0;
|
|
|
|
for (i=0;i<(m-1)/2;i+=2)
|
|
{
|
|
fcopy2(xp,t);
|
|
sqroot2(_MIPP_ xp,xp);
|
|
sqroot2(_MIPP_ yp,yp);
|
|
fadd2(xp,xq,d);
|
|
modmult2(_MIPP_ d,t,d);
|
|
fincr2(yp,d);
|
|
fincr2(yq,d);
|
|
fadd2(d,xp,v[0]); /* v[0]=t*(xp+xq)+yp+yq+xp */
|
|
fadd2(t,xq,v[2]); /* v[2]=t+xq */
|
|
incr2(v[2],1,v[1]); /* v[1]=t+xq+1 */
|
|
modsquare2(_MIPP_ xq,xq); /* xq*=xq */
|
|
modsquare2(_MIPP_ yq,yq); /* yp*=yp */
|
|
|
|
fcopy2(xp,t); /* same again - unlooped times 2 */
|
|
|
|
sqroot2(_MIPP_ xp,xp);
|
|
sqroot2(_MIPP_ yp,yp);
|
|
|
|
fadd2(xp,xq,d);
|
|
modmult2(_MIPP_ d,t,d);
|
|
fincr2(yp,d);
|
|
fincr2(yq,d);
|
|
fadd2(d,xp,u[0]);
|
|
fadd2(t,xq,u[2]);
|
|
incr2(u[2],1,u[1]);
|
|
modsquare2(_MIPP_ xq,xq);
|
|
modsquare2(_MIPP_ yq,yq);
|
|
|
|
mul(_MIPP_ u,v,u); /* fast mul */
|
|
mult4(_MIPP_ miller,u,miller);
|
|
}
|
|
|
|
mult4(_MIPP_ miller,f,miller);
|
|
|
|
for (i=0;i<4;i++)
|
|
{
|
|
fcopy2(miller[i],u[i]);
|
|
fcopy2(miller[i],v[i]);
|
|
fcopy2(miller[i],f[i]);
|
|
}
|
|
|
|
/* final exponentiation */
|
|
|
|
for (i=0;i<(m+1)/2;i++) square4(_MIPP_ u,u); /* u*=u */
|
|
powq(_MIPP_ u);
|
|
powq(_MIPP_ f);
|
|
for(i=0;i<4;i++) fcopy2(f[i],v[i]);
|
|
powq(_MIPP_ f);
|
|
for(i=0;i<4;i++) fcopy2(f[i],res[i]);
|
|
powq(_MIPP_ f);
|
|
mult4(_MIPP_ f,u,f);
|
|
mult4(_MIPP_ f,miller,f);
|
|
mult4(_MIPP_ res,v,res);
|
|
powq(_MIPP_ u);
|
|
powq(_MIPP_ u);
|
|
mult4(_MIPP_ res,u,res);
|
|
|
|
/* doing inversion here could kill the stack... */
|
|
|
|
#ifndef MR_STATIC
|
|
memkill(_MIPP_ mem,18);
|
|
#else
|
|
memset(mem,0,MR_BIG_RESERVE(18));
|
|
#endif
|
|
}
|
|
|
|
/* ... so do inversion here to avoid stack overflow */
|
|
|
|
void tate(_MIPD_ epoint *P,epoint *Q,big *res)
|
|
{
|
|
int i;
|
|
big f[4];
|
|
#ifndef MR_STATIC
|
|
char *mem=(char *)memalloc(_MIPP_ 4);
|
|
#else
|
|
char mem[MR_BIG_RESERVE(4)]; /* 160 bytes from stack */
|
|
memset(mem,0,MR_BIG_RESERVE(4));
|
|
#endif
|
|
for (i=0;i<4;i++) f[i]=mirvar_mem(_MIPP_ mem,i);
|
|
|
|
eta_T(_MIPP_ P,Q,f,res);
|
|
|
|
invert(_MIPP_ f);
|
|
mult4(_MIPP_ res,f,res);
|
|
|
|
#ifndef MR_STATIC
|
|
memkill(_MIPP_ mem,4);
|
|
#else
|
|
memset(mem,0,MR_BIG_RESERVE(4));
|
|
#endif
|
|
}
|
|
|
|
/* Max stack requirement < 4K */
|
|
|
|
int main()
|
|
{
|
|
big a2,a6,bx,r;
|
|
big res[4];
|
|
epoint *P,*Q;
|
|
|
|
int i,romptr;
|
|
miracl instance; /* sizeof(miracl)= 2000 bytes from the stack */
|
|
#ifndef MR_STATIC
|
|
#ifdef MR_GENERIC_MT
|
|
miracl *mr_mip=mirsys(WORDS*NPW,16);
|
|
#else
|
|
miracl *mr_mip=mirsys(WORDS*NPW,16);
|
|
#endif
|
|
char *mem=(char *)memalloc(_MIPP_ 8);
|
|
char *mem1=(char *)ecp_memalloc(_MIPP_ 2);
|
|
#else
|
|
#ifdef MR_GENERIC_MT
|
|
miracl *mr_mip=mirsys(&instance,MR_STATIC*NPW,16); /* size of bigs is fixed */
|
|
#else
|
|
miracl *mr_mip=mirsys(&instance,MR_STATIC*NPW,16);
|
|
#endif
|
|
char mem[MR_BIG_RESERVE(8)]; /* reserve space on the stack for 8 bigs */
|
|
char mem1[MR_ECP_RESERVE(2)]; /* reserve space on stack for 2 curve points */
|
|
memset(mem,0,MR_BIG_RESERVE(8)); /* clear this memory */
|
|
memset(mem1,0,MR_ECP_RESERVE(2)); /* ~668 bytes in all */
|
|
#endif
|
|
|
|
/* Initialise bigs */
|
|
|
|
a2=mirvar_mem(_MIPP_ mem,0);
|
|
a6=mirvar_mem(_MIPP_ mem,1);
|
|
bx=mirvar_mem(_MIPP_ mem,2);
|
|
for (i=0;i<4;i++)
|
|
res[i]=mirvar_mem(_MIPP_ mem,3+i);
|
|
r=mirvar_mem(_MIPP_ mem,7);
|
|
|
|
/* printf("ROM size= %d\n",sizeof(rom)+sizeof(prom)); */
|
|
#ifndef MR_NO_STANDARD_IO
|
|
#ifdef MR_STATIC
|
|
printf("n Bigs require n*%d+%d bytes\n",MR_SIZE,MR_SL);
|
|
printf("n Points require n*%d+%d bytes\n",MR_ESIZE,MR_SL);
|
|
printf("sizeof(miracl)= %d\n",sizeof(miracl));
|
|
#endif
|
|
#endif
|
|
/* Initialise Elliptic curve points */
|
|
|
|
P=epoint_init_mem(_MIPP_ mem1,0);
|
|
Q=epoint_init_mem(_MIPP_ mem1,1);
|
|
|
|
/* Initialise supersingular curve */
|
|
|
|
convert(_MIPP_ 1,a2);
|
|
convert(_MIPP_ B,a6);
|
|
|
|
/* The -M tells MIRACL that this is a supersingular curve */
|
|
|
|
if (!ecurve2_init(_MIPP_ -M,T,U,V,a2,a6,FALSE,MR_PROJECTIVE))
|
|
{
|
|
#ifndef MR_NO_STANDARD_IO
|
|
printf("Problem with the curve\n");
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
/* Get P and Q from ROM */
|
|
/* These should have been multiplied by the cofactor 487805 = 5*97561 */
|
|
/* 487805 is a cofactor of the group order 2^271+2^136+1 */
|
|
|
|
romptr=0;
|
|
init_point_from_rom(P,WORDS,rom,ROMSZ,&romptr);
|
|
init_point_from_rom(Q,WORDS,rom,ROMSZ,&romptr);
|
|
|
|
#ifndef MR_NO_STANDARD_IO
|
|
printf( "P= \n");
|
|
otnum(_MIPP_ P->X,stdout);
|
|
otnum(_MIPP_ P->Y,stdout);
|
|
printf( "Q= \n");
|
|
otnum(_MIPP_ Q->X,stdout);
|
|
otnum(_MIPP_ Q->Y,stdout);
|
|
#endif
|
|
|
|
bigbits(_MIPP_ 160,r);
|
|
|
|
/* Simple bilinearity test */
|
|
|
|
tate(_MIPP_ P,Q,res);
|
|
|
|
/* this could break the 4k stack, 2060+668+2996 >4K */
|
|
/* so we cannot afford much precomputation in power4 */
|
|
|
|
power4(_MIPP_ res,r,res); /* res=res^{sr} */
|
|
|
|
#ifndef MR_NO_STANDARD_IO
|
|
printf( "\ne(P,Q)^r= \n");
|
|
for (i=0;i<4;i++)
|
|
{
|
|
otnum(_MIPP_ res[i],stdout);
|
|
zero(res[i]);
|
|
}
|
|
#endif
|
|
|
|
ecurve2_mult(_MIPP_ r,Q,Q); /* Q=rQ */
|
|
|
|
epoint2_norm(_MIPP_ Q);
|
|
|
|
tate(_MIPP_ P,Q,res); /* Now invert is taken out of Tate, and the stack should be OK */
|
|
|
|
#ifndef MR_NO_STANDARD_IO
|
|
printf( "\ne(P,rQ)= \n");
|
|
for (i=0;i<4;i++)
|
|
otnum(_MIPP_ res[i],stdout);
|
|
#endif
|
|
|
|
/* all done */
|
|
|
|
#ifndef MR_STATIC
|
|
memkill(_MIPP_ mem,8);
|
|
ecp_memkill(_MIPP_ mem1,2);
|
|
#else
|
|
memset(mem,0,MR_BIG_RESERVE(8)); /* clear this stack memory */
|
|
memset(mem1,0,MR_ECP_RESERVE(2));
|
|
#endif
|
|
|
|
mirexit(_MIPPO_ ); /* clears workspace memory */
|
|
return 0;
|
|
}
|
|
|
|
|