-{
- 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);
+ if (!(BN_set_bit(R,BN_BITS2))) goto err; /* R */
+
+ buf[0]=mod->d[0]; /* tmod = N mod word size */
+ buf[1]=0;
+ tmod.d=buf;
+ tmod.top = buf[0] != 0 ? 1 : 0;
+ tmod.dmax=2;
+ tmod.neg=0;
+ /* Ri = R^-1 mod N*/
+ if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL)
+ goto err;
+ if (!BN_lshift(Ri,Ri,BN_BITS2)) goto err; /* R*Ri */
+ if (!BN_is_zero(Ri))
+ {
+ if (!BN_sub_word(Ri,1)) goto err;
+ }
+ else /* if N mod word size == 1 */
+ {
+ if (!BN_set_word(Ri,BN_MASK2)) goto err; /* Ri-- (mod word size) */
+ }
+ if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err;
+ /* Ni = (R*Ri-1)/N,
+ * keep only least significant word: */
+ mont->n0 = (Ri->top > 0) ? Ri->d[0] : 0;
+ }
+#else /* !MONT_WORD */
+ { /* bignum version */
+ mont->ri=BN_num_bits(&mont->N);
+ BN_zero(R);
+ if (!BN_set_bit(R,mont->ri)) goto err; /* R = 2^ri */
+ /* Ri = R^-1 mod N*/
+ if ((BN_mod_inverse(Ri,R,&mont->N,ctx)) == NULL)
+ goto err;
+ if (!BN_lshift(Ri,Ri,mont->ri)) goto err; /* R*Ri */
+ if (!BN_sub_word(Ri,1)) goto err;
+ /* Ni = (R*Ri-1) / N */
+ if (!BN_div(&(mont->Ni),NULL,Ri,&mont->N,ctx)) goto err;
+ }