-/* $OpenBSD: bn_mul.c,v 1.36 2023/03/30 14:28:56 tb Exp $ */
+/* $OpenBSD: bn_mul.c,v 1.37 2023/04/19 10:51:22 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
}
}
-#ifdef BN_RECURSION
-/* Karatsuba recursive multiplication algorithm
- * (cf. Knuth, The Art of Computer Programming, Vol. 2) */
-
-/* r is 2*n2 words in size,
- * a and b are both n2 words in size.
- * n2 must be a power of 2.
- * We multiply and return the result.
- * t must be 2*n2 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]
- */
-/* dnX may not be positive, but n2/2+dnX has to be */
-void
-bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, int dna,
- int dnb, BN_ULONG *t)
-{
- int n = n2 / 2, c1, c2;
- int tna = n + dna, tnb = n + dnb;
- unsigned int neg, zero;
- BN_ULONG ln, lo, *p;
-
-# ifdef BN_MUL_COMBA
-# if 0
- if (n2 == 4) {
- bn_mul_comba4(r, a, b);
- return;
- }
-# endif
- /* Only call bn_mul_comba 8 if n2 == 8 and the
- * two arrays are complete [steve]
- */
- if (n2 == 8 && dna == 0 && dnb == 0) {
- bn_mul_comba8(r, a, b);
- return;
- }
-# endif /* BN_MUL_COMBA */
- /* Else do normal multiply */
- if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) {
- bn_mul_normal(r, a, n2 + dna, b, n2 + dnb);
- if ((dna + dnb) < 0)
- memset(&r[2*n2 + dna + dnb], 0,
- sizeof(BN_ULONG) * -(dna + dnb));
- return;
- }
- /* r=(a[0]-a[1])*(b[1]-b[0]) */
- c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna);
- c2 = bn_cmp_part_words(&(b[n]), b,tnb, tnb - n);
- zero = neg = 0;
- switch (c1 * 3 + c2) {
- case -4:
- bn_sub(t, n, &a[n], tna, a, n); /* - */
- bn_sub(&t[n], n, b, n, &b[n], tnb); /* - */
- break;
- case -3:
- zero = 1;
- break;
- case -2:
- bn_sub(t, n, &a[n], tna, a, n); /* - */
- bn_sub(&t[n], n, &b[n], tnb, b, n); /* + */
- neg = 1;
- break;
- case -1:
- case 0:
- case 1:
- zero = 1;
- break;
- case 2:
- bn_sub(t, n, a, n, &a[n], tna); /* + */
- bn_sub(&t[n], n, b, n, &b[n], tnb); /* - */
- neg = 1;
- break;
- case 3:
- zero = 1;
- break;
- case 4:
- bn_sub(t, n, a, n, &a[n], tna);
- bn_sub(&t[n], n, &b[n], tnb, b, n);
- break;
- }
-
-# ifdef BN_MUL_COMBA
- if (n == 4 && dna == 0 && dnb == 0) /* XXX: bn_mul_comba4 could take
- extra args to do this well */
- {
- if (!zero)
- bn_mul_comba4(&(t[n2]), t, &(t[n]));
- else
- memset(&(t[n2]), 0, 8 * sizeof(BN_ULONG));
-
- bn_mul_comba4(r, a, b);
- bn_mul_comba4(&(r[n2]), &(a[n]), &(b[n]));
- } else if (n == 8 && dna == 0 && dnb == 0) /* XXX: bn_mul_comba8 could
- take extra args to do this
- well */
- {
- if (!zero)
- bn_mul_comba8(&(t[n2]), t, &(t[n]));
- else
- memset(&(t[n2]), 0, 16 * sizeof(BN_ULONG));
-
- bn_mul_comba8(r, a, b);
- bn_mul_comba8(&(r[n2]), &(a[n]), &(b[n]));
- } else
-# endif /* BN_MUL_COMBA */
- {
- p = &(t[n2 * 2]);
- if (!zero)
- bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);
- else
- memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG));
- bn_mul_recursive(r, a, b, n, 0, 0, p);
- bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), n, dna, dnb, p);
- }
-
- /* 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);
- }
- }
-}
-
-/* n+tn is the word length
- * t needs to be n*4 is size, as does r */
-/* tnX may not be negative but less than n */
-void
-bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n, int tna,
- int tnb, BN_ULONG *t)
-{
- int i, j, n2 = n * 2;
- int c1, c2, neg;
- BN_ULONG ln, lo, *p;
-
- if (n < 8) {
- bn_mul_normal(r, a, n + tna, b, n + tnb);
- return;
- }
-
- /* r=(a[0]-a[1])*(b[1]-b[0]) */
- c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna);
- c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n);
- neg = 0;
- switch (c1 * 3 + c2) {
- case -4:
- bn_sub(t, n, &a[n], tna, a, n); /* - */
- bn_sub(&t[n], n, b, n, &b[n], tnb); /* - */
- break;
- case -3:
- /* break; */
- case -2:
- bn_sub(t, n, &a[n], tna, a, n); /* - */
- bn_sub(&t[n], n, &b[n], tnb, b, n); /* + */
- neg = 1;
- break;
- case -1:
- case 0:
- case 1:
- /* break; */
- case 2:
- bn_sub(t, n, a, n, &a[n], tna); /* + */
- bn_sub(&t[n], n, b, n, &b[n], tnb); /* - */
- neg = 1;
- break;
- case 3:
- /* break; */
- case 4:
- bn_sub(t, n, a, n, &a[n], tna);
- bn_sub(&t[n], n, &b[n], tnb, 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]), tna, &(b[n]), tnb);
- memset(&(r[n2 + tna + tnb]), 0,
- sizeof(BN_ULONG) * (n2 - tna - tnb));
- } else {
- p = &(t[n2*2]);
- bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);
- bn_mul_recursive(r, a, b, n, 0, 0, p);
- i = n / 2;
- /* If there is only a bottom half to the number,
- * just do it */
- if (tna > tnb)
- j = tna - i;
- else
- j = tnb - i;
- if (j == 0) {
- bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]),
- i, tna - i, tnb - 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]),
- i, tna - i, tnb - i, p);
- memset(&(r[n2 + tna + tnb]), 0,
- sizeof(BN_ULONG) * (n2 - tna - tnb));
- }
- else /* (j < 0) eg, n == 16, i == 8 and tn == 5 */
- {
- memset(&(r[n2]), 0, sizeof(BN_ULONG) * n2);
- if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL &&
- tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) {
- bn_mul_normal(&(r[n2]), &(a[n]), tna,
- &(b[n]), tnb);
- } else {
- for (;;) {
- i /= 2;
- /* these simplified conditions work
- * exclusively because difference
- * between tna and tnb is 1 or 0 */
- if (i < tna || i < tnb) {
- bn_mul_part_recursive(&(r[n2]),
- &(a[n]), &(b[n]), i,
- tna - i, tnb - i, p);
- break;
- } else if (i == tna || i == tnb) {
- bn_mul_recursive(&(r[n2]),
- &(a[n]), &(b[n]), i,
- tna - i, tnb - 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);
- }
- }
-}
-#endif /* BN_RECURSION */
#ifndef HAVE_BN_MUL
-#ifndef BN_RECURSION
int
bn_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, int rn, BN_CTX *ctx)
{
return 1;
}
-#else /* BN_RECURSION */
-int
-bn_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, int rn, BN_CTX *ctx)
-{
- BIGNUM *t = NULL;
- int al, bl, i, k;
- int j = 0;
- int ret = 0;
-
- BN_CTX_start(ctx);
-
- al = a->top;
- bl = b->top;
-
- i = al - bl;
-
- if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) {
- if (i >= -1 && i <= 1) {
- /* Find out the power of two lower or equal
- to the longest of the two numbers */
- if (i >= 0) {
- j = BN_num_bits_word((BN_ULONG)al);
- }
- if (i == -1) {
- j = BN_num_bits_word((BN_ULONG)bl);
- }
- j = 1 << (j - 1);
- assert(j <= al || j <= bl);
- k = j + j;
- if ((t = BN_CTX_get(ctx)) == NULL)
- goto err;
- if (al > j || bl > j) {
- if (!bn_wexpand(t, k * 4))
- goto err;
- if (!bn_wexpand(r, k * 4))
- goto err;
- bn_mul_part_recursive(r->d, a->d, b->d,
- j, al - j, bl - j, t->d);
- }
- else /* al <= j || bl <= j */
- {
- if (!bn_wexpand(t, k * 2))
- goto err;
- if (!bn_wexpand(r, k * 2))
- goto err;
- bn_mul_recursive(r->d, a->d, b->d,
- j, al - j, bl - j, t->d);
- }
- r->top = rn;
- goto end;
- }
-#if 0
- if (i == 1 && !BN_get_flags(b, BN_FLG_STATIC_DATA)) {
- BIGNUM *tmp_bn = (BIGNUM *)b;
- if (!bn_wexpand(tmp_bn, al))
- goto err;
- tmp_bn->d[bl] = 0;
- bl++;
- i--;
- } else if (i == -1 && !BN_get_flags(a, BN_FLG_STATIC_DATA)) {
- BIGNUM *tmp_bn = (BIGNUM *)a;
- if (!bn_wexpand(tmp_bn, bl))
- goto err;
- tmp_bn->d[al] = 0;
- al++;
- i++;
- }
- if (i == 0) {
- /* symmetric and > 4 */
- /* 16 or larger */
- j = BN_num_bits_word((BN_ULONG)al);
- j = 1 << (j - 1);
- k = j + j;
- if ((t = BN_CTX_get(ctx)) == NULL)
- goto err;
- if (al == j) /* exact multiple */
- {
- if (!bn_wexpand(t, k * 2))
- goto err;
- if (!bn_wexpand(r, k * 2))
- goto err;
- bn_mul_recursive(r->d, a->d, b->d, al, t->d);
- } else {
- if (!bn_wexpand(t, k * 4))
- goto err;
- if (!bn_wexpand(r, k * 4))
- goto err;
- bn_mul_part_recursive(r->d, a->d, b->d,
- al - j, j, t->d);
- }
- r->top = top;
- goto end;
- }
-#endif
- }
-
- bn_mul_normal(r->d, a->d, al, b->d, bl);
-
- end:
- ret = 1;
- err:
- BN_CTX_end(ctx);
-
- return ret;
-}
-#endif /* BN_RECURSION */
#endif /* HAVE_BN_MUL */
int
-/* $OpenBSD: bn_sqr.c,v 1.29 2023/03/30 14:28:56 tb Exp $ */
+/* $OpenBSD: bn_sqr.c,v 1.30 2023/04/19 10:51:22 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
bn_add_words(r, r, tmp, max);
}
-#ifdef BN_RECURSION
-/* 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) {
- bn_sqr_comba4(r, a);
- return;
- } else if (n2 == 8) {
- bn_sqr_comba8(r, a);
- 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, n2 * sizeof(BN_ULONG));
- 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);
- }
- }
-}
-#endif
/*
* bn_sqr() computes a * a, storing the result in r. The caller must ensure that
if ((tmp = BN_CTX_get(ctx)) == NULL)
goto err;
-#if defined(BN_RECURSION)
- if (a->top < BN_SQR_RECURSIVE_SIZE_NORMAL) {
- BN_ULONG t[BN_SQR_RECURSIVE_SIZE_NORMAL*2];
- bn_sqr_normal(r->d, a->d, a->top, t);
- } else {
- int j, k;
-
- j = BN_num_bits_word((BN_ULONG)a->top);
- j = 1 << (j - 1);
- k = j + j;
- if (a->top == j) {
- if (!bn_wexpand(tmp, k * 2))
- goto err;
- bn_sqr_recursive(r->d, a->d, a->top, tmp->d);
- } else {
- if (!bn_wexpand(tmp, rn))
- goto err;
- bn_sqr_normal(r->d, a->d, a->top, tmp->d);
- }
- }
-#else
if (!bn_wexpand(tmp, rn))
goto err;
bn_sqr_normal(r->d, a->d, a->top, tmp->d);
-#endif
ret = 1;