case 0x29:
{
BN_add(B,B,C);
- if(l<=0) l=wordsize; // conditional seems pretty useless
- bool b=BN_is_bit_set(B,l<<6);
- data[0]=b;
- if(b) BN_mask_bits(B,l<<6);
- cycles=504+(8*l)-((8*l-2)%5)-6;
+ bool b=BN_is_bit_set(B,wordsize<<6);
+ if(data) data[0]=b;
+ if(b) BN_mask_bits(B,wordsize<<6);
+ cycles=501+(8*wordsize+3)/5*5-6;
}
break;
case 0x32:
+ l=min(34,l);
A.GetLE(data,l<<3);
BN_div(C,B,A,D,ctx);
- BN_zero(A);
+ BN_rshift(A,C,17*64);
+ BN_mask_bits(C,17*64);
+ BN_zero(J);
break;
case 0x3b:
MonInit(wordsize*60+4*l);
#endif
{
cBN a, b, x, y, scalar;
- D.GetLE(data+0x00,16);
- x.GetLE(data+0x10,16);
- y.GetLE(data+0x20,16);
- b.GetLE(data+0x30,16);
- a.GetLE(data+0x40,16);
- scalar.GetLE(data+0x50,16);
+ if(l<2 || l>4) l=4;
+ TMPWS_START(l);
+ l<<=3;
+ D.GetLE(data+0*l,l);
+ x.GetLE(data+1*l,l);
+ y.GetLE(data+2*l,l);
+ b.GetLE(data+3*l,l);
+ a.GetLE(data+4*l,l);
+ scalar.GetLE(data+5*l,l);
+ bool doz=false;
int scalarbits=BN_num_bits(scalar);
- if(scalarbits>=2 && !BN_is_zero(x) && !BN_is_zero(y) && !BN_is_zero(b)) {
- CurveInit(a);
- ToProjective(0,x,y);
- BN_copy(Qx,Px);
- BN_copy(Qy,Py);
- for(int i=scalarbits-2; i>=0; i--) {
- DoubleP(0);
- if(BN_is_bit_set(scalar,i)) {
- BN_copy(A,Pz);
- if(BN_is_zero(Pz)) {
- BN_copy(Px,Qx);
- BN_copy(Py,Qy);
- BN_copy(Pz,Qz);
- AddP(1);
- }
- else {
- BN_mask_bits(Px,32);
- BN_lshift(b,Qz,32);
- BN_add(Px,Px,b);
- BN_mask_bits(Px,128);
- AddP(0);
+ if(scalarbits>=2) {
+ if(BN_is_zero(x) && (BN_is_zero(y) || (BN_is_zero(b) && BN_num_bits(y)==1))) {
+ BN_zero(Px);
+ BN_copy(Py,y);
+ BN_zero(Qz);
+ }
+ else {
+ CurveInit(a);
+ ToProjective(0,x,y);
+ BN_copy(Qx,Px);
+ BN_copy(Qy,Py);
+ for(int i=scalarbits-2; i>=0; i--) {
+ DoubleP(0);
+ if(BN_is_bit_set(scalar,i)) {
+ BN_copy(A,Pz);
+ if(BN_is_zero(Pz) || BN_is_zero(D)) {
+ BN_copy(Px,Qx);
+ BN_copy(Py,Qy);
+ BN_copy(Pz,Qz);
+ AddP(1);
+ }
+ else {
+ doz=true;
+ if(wordsize==4) {
+ BN_rshift(Py,Py,32);
+ BN_lshift(Py,Py,32);
+ BN_rshift(b,Qz,224);
+ BN_add(Py,Py,b);
+ }
+ BN_mask_bits(Px,32);
+ BN_lshift(b,Qz,32);
+ BN_add(Px,Px,b);
+ BN_mask_bits(Px,128);
+ AddP(0);
+ }
}
}
+ ToAffine();
}
- ToAffine();
}
- memset(data,0,0x60);
- Px.PutLE(&data[0x00],16);
- unsigned char tmp[16];
- Qz.PutLE(tmp,16);
- memcpy(&data[0x10],&tmp[0x0C],4);
- Py.PutLE(&data[0x20],16);
+ else {
+ BN_copy(Px,x);
+ BN_copy(Py,y);
+ BN_zero(Qz);
+ }
+ memset(data,0,0x40);
+ Px.PutLE(&data[0x00],l);
+ if(l<0x20 && doz) {
+ unsigned char tmp[0x20];
+ Qz.PutLE(tmp,l);
+ memcpy(&data[l],&tmp[l-4],4);
+ }
+ Py.PutLE(&data[0x20],l);
+ TMPWS_END();
+ BN_zero(A);
+ BN_zero(B);
+ BN_zero(C);
break;
}
default:
bool cN2Prov0101::ProcessMap(int f)
{
unsigned short addr;
- unsigned char tmp[256];
+ unsigned char tmp[512];
int l=GetOpSize(Get(0x48));
int dl=l<<3;
AddCycles(MapCycles());
break;
case 0x29:
- DoMap(f,tmp,-Get(0x48));
+ GetMem(HILO(0x44),tmp,dl,0);
+ DoMap(f,tmp);
Set(0x4b,tmp[0]);
AddCycles(MapCycles());
break;
+ case 0x3e:
+ if(l>wordsize) { l=wordsize; dl=l<<3; }
+ // fall through
case 0x32:
case 0x3b:
- case 0x3e:
+ if(l>34) { l=34; dl=34<<3; }
GetMem(HILO(0x44),tmp,dl,0);
DoMap(f,tmp,l);
AddCycles(MapCycles());
break;
case 0x57:
addr=HILO(0x46);
- GetMem(HILO(addr ),tmp,16,0);
- GetMem(HILO(addr+2 ),tmp+0x10,16,0);
- GetMem(HILO(addr+4 ),tmp+0x20,16,0);
- GetMem(HILO(addr+6 ),tmp+0x30,16,0);
- GetMem(HILO(addr+8 ),tmp+0x40,16,0);
- GetMem(HILO(addr+10),tmp+0x50,16,0);
+ l=wordsize; if(l<2 || l>4) l=4;
+ dl=l<<3;
+ for(int i=0; i<6; i++) GetMem(HILO(addr+i*2),tmp+i*dl,dl,0);
DoMap(f,tmp);
SetMem(0x400,tmp,0x40,0);
+ memset(tmp,0,11*32);
+ SetMem(0x440,tmp,11*32,0);
AddCycles(MapCycles());
break;
default:
BN_mask_bits(r,wordsize<<6);
}
-void cMapMath::MakeJ0(BIGNUM *j, BIGNUM *d)
+void cMapMath::MakeJ0(BIGNUM *j, BIGNUM *d, int bits)
{
#if OPENSSL_VERSION_NUMBER < 0x0090700fL
#error BN_mod_inverse is probably buggy in your openssl version
BN_zero(x);
BN_sub(j,x,d);
BN_set_bit(j,0);
- BN_set_bit(x,64);
+ BN_set_bit(x,bits);
BN_mod_inverse(j,j,x,ctx);
}
MonMul(B,B,B);
if(BN_is_bit_set(e,i)) MonMul(B,A,B);
}
+ if(BN_is_bit_set(D,0)) {
+ int i;
+ for(i=BN_num_bits(D)-2; i>0; i--) if(BN_is_bit_set(D,i)) break;
+ if(i<=0) {
+ MonMul(B,B,B);
+ MonMul(B,A,B);
+ }
+ }
BN_set_word(A,1);
MonMul(B,A,B);
}
BN_copy(A,B);
BN_copy(I,D);
BN_add_word(I,1);
+ BN_mask_bits(I,wordsize<<6);
BN_rshift(I,I,1);
MonMul(s140,I,B);
MonMul(s160,B,a);
cycles=0;
switch(f) {
case SETSIZE:
- wordsize=l; cycles=475-6; break;
+ cycles=(l>17 ? 459 : (l ? 475 : 454))-6;
+ if(l>=1 && l<=17) wordsize=l;
+ break;
case IMPORT_J:
cycles=890-6;
- // fall through
+ last=0;
+ regs[0]->GetLE(data,8);
+ break;
case IMPORT_A:
case IMPORT_B:
case IMPORT_C:
case IMPORT_D:
- if(!cycles) cycles=771+160*l1-6+(l==0?4:0);
+ if(l>17) { l=17; cycles+=5; }
+ else if(l<=0) { l=wordsize; cycles+=4; }
+ cycles+=771+160*l-6;
last=f-IMPORT_J;
- // fall through
+ regs[last]->GetLE(data,l<<3);
+ break;
case IMPORT_LAST:
- if(!cycles) cycles=656+160*l-6;
- regs[last]->GetLE(data,last>0?dl:8);
+ if(l>16) { l=1; cycles+=5; }
+ else if(l<=0) l=1;
+ cycles=656+160*l-6;
+ regs[last]->GetLE(data,(last==0?1:l)<<3);
break;
case EXPORT_J:
cycles=897-6;
- // fall through
+ last=0;
+ regs[0]->PutLE(data,8);
+ break;
case EXPORT_A:
case EXPORT_B:
case EXPORT_C:
case EXPORT_D:
- if(!cycles) cycles=778+160*l1-6+(l==0?4:0);
+ if(l>17) { l=17; cycles+=5; }
+ else if(l<=0) { l=wordsize; cycles+=4; }
+ cycles=778+160*l-6;
last=f-EXPORT_J;
- // fall through
+ regs[last]->PutLE(data,l<<3);
+ break;
case EXPORT_LAST:
- if(!cycles) cycles=668+160*l-6; // Even for 'J' cycles is dependent on 'l'
- regs[last]->PutLE(data,last>0?dl:8);
+ if(l>16) { l=1; cycles+=5; }
+ else if(l<=0) l=1;
+ cycles=668+160*l-6;
+ regs[last]->PutLE(data,(last==0?1:l)<<3);
break;
case SWAP_A:
case CLEAR_B:
case CLEAR_C:
case CLEAR_D:
- cycles=465+(8*l1)-((8*l1-2)%5)-6;
+ cycles=462+(8*l1+3)/5*5-6;
last=f-CLEAR_A+1; BN_zero(*regs[last]);
break;
case COPY_A_B:
- last=2; BN_copy(B,A); cycles=465+(8*l1)-((8*l1-2)%5)-6; break;
+ last=2; BN_copy(B,A); cycles=462+(8*l1+3)/5*5-6; break;
case COPY_B_A:
- last=1; BN_copy(A,B); cycles=465+(8*l1)-((8*l1-2)%5)-6; break;
+ last=1; BN_copy(A,B); cycles=462+(8*l1+3)/5*5-6; break;
case COPY_A_C:
- last=3; BN_copy(C,A); cycles=465+(8*l1)-((8*l1-2)%5)-6; break;
+ last=3; BN_copy(C,A); cycles=462+(8*l1+3)/5*5-6; break;
case COPY_C_A:
- last=1; BN_copy(A,C); cycles=465+(8*l1)-((8*l1-2)%5)-6; break;
+ last=1; BN_copy(A,C); cycles=462+(8*l1+3)/5*5-6; break;
case COPY_C_D:
- last=4; BN_copy(D,C); cycles=465+(8*l1)-((8*l1-2)%5)-6; break;
+ last=4; BN_copy(D,C); cycles=462+(8*l1+3)/5*5-6; break;
case COPY_D_C:
- last=3; BN_copy(C,D); cycles=465+(8*l1)-((8*l1-2)%5)-6; break;
+ last=3; BN_copy(C,D); cycles=462+(8*l1+3)/5*5-6; break;
case 0x43: // init SHA1
SHA1_Init(&sctx);
#define DEF_WORDSIZE 4
+#define TMPWS_START(x) { int __oldws=wordsize; wordsize=(x);
+#define TMPWS_END() wordsize=__oldws; }
+
class cMapMath {
private:
cBN x, y, s;
cBNctx ctx;
SHA_CTX sctx;
// stateless
- void MakeJ0(BIGNUM *j, BIGNUM *d);
+ void MakeJ0(BIGNUM *j, BIGNUM *d, int bits=64);
void ModAdd(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *d);
void ModSub(BIGNUM *r, BIGNUM *d, BIGNUM *b);
void MonMul(BIGNUM *o, BIGNUM *a, BIGNUM *b, BIGNUM *c, BIGNUM *d, BIGNUM *j, int w);