* [including the GNU Public Licence.]
*/
-#include <stdio.h>
+
+
#include "cryptlib.h"
#include "bn_lcl.h"
int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
{
const BIGNUM *tmp;
+ int a_neg = a->neg, ret;
bn_check_top(a);
bn_check_top(b);
- /* a + b a+b
+ /*-
+ * a + b a+b
* a + -b a-b
* -a + b b-a
* -a + -b -(a+b)
*/
- if (a->neg ^ b->neg)
+ if (a_neg ^ b->neg)
{
/* only one is negative */
- if (a->neg)
+ if (a_neg)
{ tmp=a; a=b; b=tmp; }
/* we are now a - b */
return(1);
}
- if (a->neg) /* both are neg */
- r->neg=1;
- else
- r->neg=0;
-
- if (!BN_uadd(r,a,b)) return(0);
- return(1);
+ ret = BN_uadd(r,a,b);
+ r->neg = a_neg;
+ bn_check_top(r);
+ return ret;
}
-/* unsigned add of b to a, r must be large enough */
+/* unsigned add of b to a */
int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
{
- register int i;
- int max,min;
- BN_ULONG *ap,*bp,*rp,carry,t1;
+ int max,min,dif;
+ const BN_ULONG *ap,*bp;
+ BN_ULONG *rp,carry,t1,t2;
const BIGNUM *tmp;
bn_check_top(a);
if (a->top < b->top)
{ tmp=a; a=b; b=tmp; }
- max=a->top;
- min=b->top;
+ max = a->top;
+ min = b->top;
+ dif = max - min;
if (bn_wexpand(r,max+1) == NULL)
- return(0);
+ return 0;
r->top=max;
ap=a->d;
bp=b->d;
rp=r->d;
- carry=0;
carry=bn_add_words(rp,ap,bp,min);
rp+=min;
ap+=min;
bp+=min;
- i=min;
if (carry)
{
- while (i < max)
+ while (dif)
{
- i++;
- t1= *(ap++);
- if ((*(rp++)=(t1+1)&BN_MASK2) >= t1)
+ dif--;
+ t1 = *(ap++);
+ t2 = (t1+1) & BN_MASK2;
+ *(rp++) = t2;
+ if (t2)
{
carry=0;
break;
}
}
- if ((i >= max) && carry)
+ if (carry)
{
- *(rp++)=1;
+ /* carry != 0 => dif == 0 */
+ *rp = 1;
r->top++;
}
}
- if (rp != ap)
- {
- for (; i<max; i++)
- *(rp++)= *(ap++);
- }
- /* memcpy(rp,ap,sizeof(*ap)*(max-i));*/
- return(1);
+ if (dif && rp != ap)
+ while (dif--)
+ /* copy remaining words if ap != rp */
+ *(rp++) = *(ap++);
+ r->neg = 0;
+ bn_check_top(r);
+ return 1;
}
/* unsigned subtraction of b from a, a must be larger than b. */
int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
{
- int max,min;
- register BN_ULONG t1,t2,*ap,*bp,*rp;
+ int max,min,dif;
+ register BN_ULONG t1,t2,*rp;
+ register const BN_ULONG *ap,*bp;
int i,carry;
-#if defined(IRIX_CC_BUG) && !defined(LINT)
- int dummy;
-#endif
bn_check_top(a);
bn_check_top(b);
- if (a->top < b->top) /* hmm... should not be happening */
+ max = a->top;
+ min = b->top;
+ dif = max - min;
+
+ if (dif < 0) /* hmm... should not be happening */
{
BNerr(BN_F_BN_USUB,BN_R_ARG2_LT_ARG3);
return(0);
}
- max=a->top;
- min=b->top;
if (bn_wexpand(r,max) == NULL) return(0);
ap=a->d;
#if 1
carry=0;
- for (i=0; i<min; i++)
+ for (i = min; i != 0; i--)
{
t1= *(ap++);
t2= *(bp++);
carry=(t1 < t2);
t1=(t1-t2)&BN_MASK2;
}
-#if defined(IRIX_CC_BUG) && !defined(LINT)
- dummy=t1;
-#endif
*(rp++)=t1&BN_MASK2;
}
#else
ap+=min;
bp+=min;
rp+=min;
- i=min;
#endif
if (carry) /* subtracted */
{
- while (i < max)
+ if (!dif)
+ /* error: a < b */
+ return 0;
+ while (dif)
{
- i++;
- t1= *(ap++);
- t2=(t1-1)&BN_MASK2;
- *(rp++)=t2;
- if (t1 > t2) break;
+ dif--;
+ t1 = *(ap++);
+ t2 = (t1-1)&BN_MASK2;
+ *(rp++) = t2;
+ if (t1)
+ break;
}
}
#if 0
{
for (;;)
{
- if (i++ >= max) break;
+ if (!dif--) break;
rp[0]=ap[0];
- if (i++ >= max) break;
+ if (!dif--) break;
rp[1]=ap[1];
- if (i++ >= max) break;
+ if (!dif--) break;
rp[2]=ap[2];
- if (i++ >= max) break;
+ if (!dif--) break;
rp[3]=ap[3];
rp+=4;
ap+=4;
#endif
r->top=max;
- bn_fix_top(r);
+ r->neg=0;
+ bn_correct_top(r);
return(1);
}
bn_check_top(a);
bn_check_top(b);
- /* a - b a-b
+ /*-
+ * a - b a-b
* a - -b a+b
* -a - b -(a+b)
* -a - -b b-a
if (!BN_usub(r,a,b)) return(0);
r->neg=0;
}
+ bn_check_top(r);
return(1);
}