示例#1
0
/*-
 * a and b must be the same size, which is n2.
 * r needs to be n2 words and t needs to be n2*2
 * l is the low words of the output.
 * t needs to be n2*3
 */
void bn_mul_high(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, BN_ULONG *l, int n2,
                 BN_ULONG *t)
{
    int i, n;
    int c1, c2;
    int neg, oneg, zero;
    BN_ULONG ll, lc, *lp, *mp;

# ifdef BN_COUNT
    fprintf(stderr, " bn_mul_high %d * %d\n", n2, n2);
# endif
    n = n2 / 2;

    /* Calculate (al-ah)*(bh-bl) */
    neg = zero = 0;
    c1 = bn_cmp_words(&(a[0]), &(a[n]), n);
    c2 = bn_cmp_words(&(b[n]), &(b[0]), n);
    switch (c1 * 3 + c2) {
    case -4:
        bn_sub_words(&(r[0]), &(a[n]), &(a[0]), n);
        bn_sub_words(&(r[n]), &(b[0]), &(b[n]), n);
        break;
    case -3:
        zero = 1;
        break;
    case -2:
        bn_sub_words(&(r[0]), &(a[n]), &(a[0]), n);
        bn_sub_words(&(r[n]), &(b[n]), &(b[0]), n);
        neg = 1;
        break;
    case -1:
    case 0:
    case 1:
        zero = 1;
        break;
    case 2:
        bn_sub_words(&(r[0]), &(a[0]), &(a[n]), n);
        bn_sub_words(&(r[n]), &(b[0]), &(b[n]), n);
        neg = 1;
        break;
    case 3:
        zero = 1;
        break;
    case 4:
        bn_sub_words(&(r[0]), &(a[0]), &(a[n]), n);
        bn_sub_words(&(r[n]), &(b[n]), &(b[0]), n);
        break;
    }

    oneg = neg;
    /* t[10] = (a[0]-a[1])*(b[1]-b[0]) */
    /* r[10] = (a[1]*b[1]) */
# ifdef BN_MUL_COMBA
    if (n == 8) {
        bn_mul_comba8(&(t[0]), &(r[0]), &(r[n]));
        bn_mul_comba8(r, &(a[n]), &(b[n]));
    } else
# endif
    {
        bn_mul_recursive(&(t[0]), &(r[0]), &(r[n]), n, 0, 0, &(t[n2]));
        bn_mul_recursive(r, &(a[n]), &(b[n]), n, 0, 0, &(t[n2]));
    }

    /*-
     * s0 == low(al*bl)
     * s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl)
     * We know s0 and s1 so the only unknown is high(al*bl)
     * high(al*bl) == s1 - low(ah*bh+s0+(al-ah)*(bh-bl))
     * high(al*bl) == s1 - (r[0]+l[0]+t[0])
     */
    if (l != NULL) {
        lp = &(t[n2 + n]);
        c1 = (int)(bn_add_words(lp, &(r[0]), &(l[0]), n));
    } else {
        c1 = 0;
        lp = &(r[0]);
    }

    if (neg)
        neg = (int)(bn_sub_words(&(t[n2]), lp, &(t[0]), n));
    else {
        bn_add_words(&(t[n2]), lp, &(t[0]), n);
        neg = 0;
    }

    if (l != NULL) {
        bn_sub_words(&(t[n2 + n]), &(l[n]), &(t[n2]), n);
    } else {
        lp = &(t[n2 + n]);
        mp = &(t[n2]);
        for (i = 0; i < n; i++)
            lp[i] = ((~mp[i]) + 1) & BN_MASK2;
    }

    /*-
     * s[0] = low(al*bl)
     * t[3] = high(al*bl)
     * t[10] = (a[0]-a[1])*(b[1]-b[0]) neg is the sign
     * r[10] = (a[1]*b[1])
     */
    /*-
     * R[10] = al*bl
     * R[21] = al*bl + ah*bh + (a[0]-a[1])*(b[1]-b[0])
     * R[32] = ah*bh
     */
    /*-
     * R[1]=t[3]+l[0]+r[0](+-)t[0] (have carry/borrow)
     * R[2]=r[0]+t[3]+r[1](+-)t[1] (have carry/borrow)
     * R[3]=r[1]+(carry/borrow)
     */
    if (l != NULL) {
        lp = &(t[n2]);
        c1 = (int)(bn_add_words(lp, &(t[n2 + n]), &(l[0]), n));
    } else {
        lp = &(t[n2 + n]);
        c1 = 0;
    }
    c1 += (int)(bn_add_words(&(t[n2]), lp, &(r[0]), n));
    if (oneg)
        c1 -= (int)(bn_sub_words(&(t[n2]), &(t[n2]), &(t[0]), n));
    else
        c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), &(t[0]), n));

    c2 = (int)(bn_add_words(&(r[0]), &(r[0]), &(t[n2 + n]), n));
    c2 += (int)(bn_add_words(&(r[0]), &(r[0]), &(r[n]), n));
    if (oneg)
        c2 -= (int)(bn_sub_words(&(r[0]), &(r[0]), &(t[n]), n));
    else
        c2 += (int)(bn_add_words(&(r[0]), &(r[0]), &(t[n]), n));

    if (c1 != 0) {              /* Add starting at r[0], could be +ve or -ve */
        i = 0;
        if (c1 > 0) {
            lc = c1;
            do {
                ll = (r[i] + lc) & BN_MASK2;
                r[i++] = ll;
                lc = (lc > ll);
            } while (lc);
        } else {
            lc = -c1;
            do {
                ll = r[i];
                r[i++] = (ll - lc) & BN_MASK2;
                lc = (lc > ll);
            } while (lc);
        }
    }
    if (c2 != 0) {              /* Add starting at r[1] */
        i = n;
        if (c2 > 0) {
            lc = c2;
            do {
                ll = (r[i] + lc) & BN_MASK2;
                r[i++] = ll;
                lc = (lc > ll);
            } while (lc);
        } else {
            lc = -c2;
            do {
                ll = r[i];
                r[i++] = (ll - lc) & BN_MASK2;
                lc = (lc > ll);
            } while (lc);
        }
    }
}
示例#2
0
/* n+tn is the word length
 * t needs to be n*4 is size, as does r */
void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int tn,
	     int n, BN_ULONG *t)
	{
	int c1,c2,i,j,n2=n*2;
	unsigned int neg;
	BN_ULONG ln,lo,*p;

# ifdef BN_COUNT
	printf(" bn_mul_part_recursive %d * %d\n",tn+n,tn+n);
# endif
	if (n < 8)
		{
		i=tn+n;
		bn_mul_normal(r,a,i,b,i);
		return;
		}

	/* r=(a[0]-a[1])*(b[1]-b[0]) */
	c1=bn_cmp_words(a,&(a[n]),n);
	c2=bn_cmp_words(&(b[n]),b,n);
	neg=0;
	switch (c1*3+c2)
		{
	case -4:
		bn_sub_words(t,      &(a[n]),a,      n); /* - */
		bn_sub_words(&(t[n]),b,      &(b[n]),n); /* - */
		break;
	case -3:
	case -2:
		bn_sub_words(t,      &(a[n]),a,      n); /* - */
		bn_sub_words(&(t[n]),&(b[n]),b,      n); /* + */
		neg=1;
		break;
	case -1:
	case 0:
	case 1:
	case 2:
		bn_sub_words(t,      a,      &(a[n]),n); /* + */
		bn_sub_words(&(t[n]),b,      &(b[n]),n); /* - */
		neg=1;
		break;
	case 3:
	case 4:
		bn_sub_words(t,      a,      &(a[n]),n);
		bn_sub_words(&(t[n]),&(b[n]),b,      n);
		break;
		}
		/* The zero case isn't yet implemented here. The speedup
		   would probably be negligible. */
# if 0
	if (n == 4)
		{
		bn_mul_comba4(&(t[n2]),t,&(t[n]));
		bn_mul_comba4(r,a,b);
		bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
		memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2));
		}
	else
# endif
	if (n == 8)
		{
		bn_mul_comba8(&(t[n2]),t,&(t[n]));
		bn_mul_comba8(r,a,b);
		bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
		memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2));
		}
	else
		{
		p= &(t[n2*2]);
		bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p);
		bn_mul_recursive(r,a,b,n,p);
		i=n/2;
		/* If there is only a bottom half to the number,
		 * just do it */
		j=tn-i;
		if (j == 0)
			{
			bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),i,p);
			memset(&(r[n2+i*2]),0,sizeof(BN_ULONG)*(n2-i*2));
			}
		else if (j > 0) /* eg, n == 16, i == 8 and tn == 11 */
				{
				bn_mul_part_recursive(&(r[n2]),&(a[n]),&(b[n]),
					j,i,p);
				memset(&(r[n2+tn*2]),0,
					sizeof(BN_ULONG)*(n2-tn*2));
				}
		else /* (j < 0) eg, n == 16, i == 8 and tn == 5 */
			{
			memset(&(r[n2]),0,sizeof(BN_ULONG)*n2);
			if (tn < BN_MUL_RECURSIVE_SIZE_NORMAL)
				{
				bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
				}
			else
				{
				for (;;)
					{
					i/=2;
					if (i < tn)
						{
						bn_mul_part_recursive(&(r[n2]),
							&(a[n]),&(b[n]),
							tn-i,i,p);
						break;
						}
					else if (i == tn)
						{
						bn_mul_recursive(&(r[n2]),
							&(a[n]),&(b[n]),
							i,p);
						break;
						}
					}
				}
			}
		}

	/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
	 * r[10] holds (a[0]*b[0])
	 * r[32] holds (b[1]*b[1])
	 */

	c1=(int)(bn_add_words(t,r,&(r[n2]),n2));

	if (neg) /* if t[32] is negative */
		{
		c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2));
		}
	else
		{
		/* Might have a carry */
		c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),t,n2));
		}

	/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
	 * r[10] holds (a[0]*b[0])
	 * r[32] holds (b[1]*b[1])
	 * c1 holds the carry bits
	 */
	c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2));
	if (c1)
		{
		p= &(r[n+n2]);
		lo= *p;
		ln=(lo+c1)&BN_MASK2;
		*p=ln;

		/* The overflow will stop before we over write
		 * words we should not overwrite */
		if (ln < (BN_ULONG)c1)
			{
			do	{
				p++;
				lo= *p;
				ln=(lo+1)&BN_MASK2;
				*p=ln;
				} while (ln == 0);
			}
		}
	}
示例#3
0
文件: bn_sqr.c 项目: 1234-/openssl
/*-
 * r is 2*n words in size,
 * a and b are both n words in size.    (There's not actually a 'b' here ...)
 * n must be a power of 2.
 * We multiply and return the result.
 * t must be 2*n words in size
 * We calculate
 * a[0]*b[0]
 * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
 * a[1]*b[1]
 */
void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, BN_ULONG *t)
{
    int n = n2 / 2;
    int zero, c1;
    BN_ULONG ln, lo, *p;

    if (n2 == 4) {
# ifndef BN_SQR_COMBA
        bn_sqr_normal(r, a, 4, t);
# else
        bn_sqr_comba4(r, a);
# endif
        return;
    } else if (n2 == 8) {
# ifndef BN_SQR_COMBA
        bn_sqr_normal(r, a, 8, t);
# else
        bn_sqr_comba8(r, a);
# endif
        return;
    }
    if (n2 < BN_SQR_RECURSIVE_SIZE_NORMAL) {
        bn_sqr_normal(r, a, n2, t);
        return;
    }
    /* r=(a[0]-a[1])*(a[1]-a[0]) */
    c1 = bn_cmp_words(a, &(a[n]), n);
    zero = 0;
    if (c1 > 0)
        bn_sub_words(t, a, &(a[n]), n);
    else if (c1 < 0)
        bn_sub_words(t, &(a[n]), a, n);
    else
        zero = 1;

    /* The result will always be negative unless it is zero */
    p = &(t[n2 * 2]);

    if (!zero)
        bn_sqr_recursive(&(t[n2]), t, n, p);
    else
        memset(&t[n2], 0, sizeof(*t) * n2);
    bn_sqr_recursive(r, a, n, p);
    bn_sqr_recursive(&(r[n2]), &(a[n]), n, p);

    /*-
     * t[32] holds (a[0]-a[1])*(a[1]-a[0]), it is negative or zero
     * r[10] holds (a[0]*b[0])
     * r[32] holds (b[1]*b[1])
     */

    c1 = (int)(bn_add_words(t, r, &(r[n2]), n2));

    /* t[32] is negative */
    c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2));

    /*-
     * t[32] holds (a[0]-a[1])*(a[1]-a[0])+(a[0]*a[0])+(a[1]*a[1])
     * r[10] holds (a[0]*a[0])
     * r[32] holds (a[1]*a[1])
     * c1 holds the carry bits
     */
    c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2));
    if (c1) {
        p = &(r[n + n2]);
        lo = *p;
        ln = (lo + c1) & BN_MASK2;
        *p = ln;

        /*
         * The overflow will stop before we over write words we should not
         * overwrite
         */
        if (ln < (BN_ULONG)c1) {
            do {
                p++;
                lo = *p;
                ln = (lo + 1) & BN_MASK2;
                *p = ln;
            } while (ln == 0);
        }
    }
}