-{
- BIGNUM tmod;
- BN_ULONG buf[2];
- /* int z; */
-
- mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
- BN_lshift(R,BN_value_one(),BN_BITS2); /* R */
- /* I was bad, this modification of a passed variable was
- * breaking the multithreaded stuff :-(
- * z=mod->top;
- * mod->top=1; */
-
- buf[0]=mod->d[0];
- buf[1]=0;
- tmod.d=buf;
- tmod.top=1;
- tmod.max=mod->max;
- tmod.neg=mod->neg;
-
- if ((Ri=BN_mod_inverse(R,&tmod,ctx)) == NULL) goto err; /* Ri */
- BN_lshift(Ri,Ri,BN_BITS2); /* R*Ri */
- bn_qsub(Ri,Ri,BN_value_one()); /* R*Ri - 1 */
- BN_div(Ri,NULL,Ri,&tmod,ctx);
- mont->n0=Ri->d[0];
- BN_free(Ri);
- /* mod->top=z; */
-}
-#else
- mont->ri=BN_num_bits(mod);
- BN_lshift(R,BN_value_one(),mont->ri); /* R */
- if ((Ri=BN_mod_inverse(R,mod,ctx)) == NULL) goto err; /* Ri */
- BN_lshift(Ri,Ri,mont->ri); /* R*Ri */
- bn_qsub(Ri,Ri,BN_value_one()); /* R*Ri - 1 */
- BN_div(Ri,NULL,Ri,mod,ctx);
- if (mont->Ni != NULL) BN_free(mont->Ni);
- mont->Ni=Ri; /* Ni=(R*Ri-1)/N */
+ {
+ BIGNUM tmod;
+ BN_ULONG buf[2];
+
+ mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
+ BN_zero(R);
+ BN_set_bit(R,BN_BITS2); /* R */
+
+ buf[0]=mod->d[0]; /* tmod = N mod word size */
+ buf[1]=0;
+ tmod.d=buf;
+ tmod.top=1;
+ tmod.max=2;
+ tmod.neg=mod->neg;
+ /* Ri = R^-1 mod N*/
+ if ((BN_mod_inverse(&Ri,R,&tmod,ctx)) == NULL)
+ goto err;
+ BN_lshift(&Ri,&Ri,BN_BITS2); /* R*Ri */
+ if (!BN_is_zero(&Ri))
+ BN_sub_word(&Ri,1);
+ else /* if N mod word size == 1 */
+ BN_set_word(&Ri,BN_MASK2); /* Ri-- (mod word size) */
+ BN_div(&Ri,NULL,&Ri,&tmod,ctx); /* Ni = (R*Ri-1)/N,
+ * keep only least significant word: */
+ mont->n0=Ri.d[0];
+ BN_free(&Ri);
+ }
+#else /* !MONT_WORD */
+ { /* bignum version */
+ mont->ri=BN_num_bits(mod);
+ BN_zero(R);
+ BN_set_bit(R,mont->ri); /* R = 2^ri */
+ /* Ri = R^-1 mod N*/
+ if ((BN_mod_inverse(&Ri,R,mod,ctx)) == NULL)
+ goto err;
+ BN_lshift(&Ri,&Ri,mont->ri); /* R*Ri */
+ BN_sub_word(&Ri,1);
+ /* Ni = (R*Ri-1) / N */
+ BN_div(&(mont->Ni),NULL,&Ri,mod,ctx);
+ BN_free(&Ri);
+ }