unsigned short bnZero[1] = { 0 };
unsigned short bnOne[2] = { 1, 1 };
+/*
+ * The Bignum format is an array of `unsigned short'. The first
+ * element of the array counts the remaining elements. The
+ * remaining elements express the actual number, base 2^16, _least_
+ * significant digit first. (So it's trivial to extract the bit
+ * with value 2^n for any n.)
+ *
+ * All Bignums in this module are positive. Negative numbers must
+ * be dealt with outside it.
+ *
+ * INVARIANT: the most significant word of any Bignum must be
+ * nonzero.
+ */
+
Bignum Zero = bnZero, One = bnOne;
Bignum newbn(int length) {
- Bignum b = malloc((length+1)*sizeof(unsigned short));
+ Bignum b = smalloc((length+1)*sizeof(unsigned short));
if (!b)
abort(); /* FIXME */
memset(b, 0, (length+1)*sizeof(*b));
}
Bignum copybn(Bignum orig) {
- Bignum b = malloc((orig[0]+1)*sizeof(unsigned short));
+ Bignum b = smalloc((orig[0]+1)*sizeof(unsigned short));
if (!b)
abort(); /* FIXME */
memcpy(b, orig, (orig[0]+1)*sizeof(*b));
* Burn the evidence, just in case.
*/
memset(b, 0, sizeof(b[0]) * (b[0] + 1));
- free(b);
+ sfree(b);
}
/*
* The most significant word of mod MUST be non-zero.
* We assume that the result array is the same size as the mod array.
*/
-void modpow(Bignum base, Bignum exp, Bignum mod, Bignum result)
+Bignum modpow(Bignum base, Bignum exp, Bignum mod)
{
unsigned short *a, *b, *n, *m;
int mshift;
int mlen, i, j;
+ Bignum result;
/* Allocate m of size mlen, copy mod to m */
/* We use big endian internally */
mlen = mod[0];
- m = malloc(mlen * sizeof(unsigned short));
+ m = smalloc(mlen * sizeof(unsigned short));
for (j = 0; j < mlen; j++) m[j] = mod[mod[0] - j];
/* Shift m left to make msb bit set */
}
/* Allocate n of size mlen, copy base to n */
- n = malloc(mlen * sizeof(unsigned short));
+ n = smalloc(mlen * sizeof(unsigned short));
i = mlen - base[0];
for (j = 0; j < i; j++) n[j] = 0;
for (j = 0; j < base[0]; j++) n[i+j] = base[base[0] - j];
/* Allocate a and b of size 2*mlen. Set a = 1 */
- a = malloc(2 * mlen * sizeof(unsigned short));
- b = malloc(2 * mlen * sizeof(unsigned short));
+ a = smalloc(2 * mlen * sizeof(unsigned short));
+ b = smalloc(2 * mlen * sizeof(unsigned short));
for (i = 0; i < 2*mlen; i++) a[i] = 0;
a[2*mlen-1] = 1;
}
/* Copy result to buffer */
+ result = newbn(mod[0]);
for (i = 0; i < mlen; i++)
result[result[0] - i] = a[i+mlen];
+ while (result[0] > 1 && result[result[0]] == 0) result[0]--;
/* Free temporary arrays */
- for (i = 0; i < 2*mlen; i++) a[i] = 0; free(a);
- for (i = 0; i < 2*mlen; i++) b[i] = 0; free(b);
- for (i = 0; i < mlen; i++) m[i] = 0; free(m);
- for (i = 0; i < mlen; i++) n[i] = 0; free(n);
+ for (i = 0; i < 2*mlen; i++) a[i] = 0; sfree(a);
+ for (i = 0; i < 2*mlen; i++) b[i] = 0; sfree(b);
+ for (i = 0; i < mlen; i++) m[i] = 0; sfree(m);
+ for (i = 0; i < mlen; i++) n[i] = 0; sfree(n);
+
+ return result;
}
/*
* The most significant word of mod MUST be non-zero.
* We assume that the result array is the same size as the mod array.
*/
-void modmul(Bignum p, Bignum q, Bignum mod, Bignum result)
+Bignum modmul(Bignum p, Bignum q, Bignum mod)
{
unsigned short *a, *n, *m, *o;
int mshift;
int pqlen, mlen, i, j;
+ Bignum result;
/* Allocate m of size mlen, copy mod to m */
/* We use big endian internally */
mlen = mod[0];
- m = malloc(mlen * sizeof(unsigned short));
+ m = smalloc(mlen * sizeof(unsigned short));
for (j = 0; j < mlen; j++) m[j] = mod[mod[0] - j];
/* Shift m left to make msb bit set */
pqlen = (p[0] > q[0] ? p[0] : q[0]);
/* Allocate n of size pqlen, copy p to n */
- n = malloc(pqlen * sizeof(unsigned short));
+ n = smalloc(pqlen * sizeof(unsigned short));
i = pqlen - p[0];
for (j = 0; j < i; j++) n[j] = 0;
for (j = 0; j < p[0]; j++) n[i+j] = p[p[0] - j];
/* Allocate o of size pqlen, copy q to o */
- o = malloc(pqlen * sizeof(unsigned short));
+ o = smalloc(pqlen * sizeof(unsigned short));
i = pqlen - q[0];
for (j = 0; j < i; j++) o[j] = 0;
for (j = 0; j < q[0]; j++) o[i+j] = q[q[0] - j];
/* Allocate a of size 2*pqlen for result */
- a = malloc(2 * pqlen * sizeof(unsigned short));
+ a = smalloc(2 * pqlen * sizeof(unsigned short));
/* Main computation */
internal_mul(n, o, a, pqlen);
}
/* Copy result to buffer */
+ result = newbn(mod[0]);
for (i = 0; i < mlen; i++)
result[result[0] - i] = a[i+2*pqlen-mlen];
+ while (result[0] > 1 && result[result[0]] == 0) result[0]--;
/* Free temporary arrays */
- for (i = 0; i < 2*pqlen; i++) a[i] = 0; free(a);
- for (i = 0; i < mlen; i++) m[i] = 0; free(m);
- for (i = 0; i < pqlen; i++) n[i] = 0; free(n);
- for (i = 0; i < pqlen; i++) o[i] = 0; free(o);
+ for (i = 0; i < 2*pqlen; i++) a[i] = 0; sfree(a);
+ for (i = 0; i < mlen; i++) m[i] = 0; sfree(m);
+ for (i = 0; i < pqlen; i++) n[i] = 0; sfree(n);
+ for (i = 0; i < pqlen; i++) o[i] = 0; sfree(o);
+
+ return result;
}
/*
/* Allocate m of size mlen, copy mod to m */
/* We use big endian internally */
mlen = mod[0];
- m = malloc(mlen * sizeof(unsigned short));
+ m = smalloc(mlen * sizeof(unsigned short));
for (j = 0; j < mlen; j++) m[j] = mod[mod[0] - j];
/* Shift m left to make msb bit set */
if (plen <= mlen) plen = mlen+1;
/* Allocate n of size plen, copy p to n */
- n = malloc(plen * sizeof(unsigned short));
+ n = smalloc(plen * sizeof(unsigned short));
for (j = 0; j < plen; j++) n[j] = 0;
for (j = 1; j <= p[0]; j++) n[plen-j] = p[j];
}
/* Free temporary arrays */
- for (i = 0; i < mlen; i++) m[i] = 0; free(m);
- for (i = 0; i < plen; i++) n[i] = 0; free(n);
+ for (i = 0; i < mlen; i++) m[i] = 0; sfree(m);
+ for (i = 0; i < plen; i++) n[i] = 0; sfree(n);
}
/*
Bignum ret;
/* mlen space for a, mlen space for b, 2*mlen for result */
- workspace = malloc(mlen * 4 * sizeof(unsigned short));
+ workspace = smalloc(mlen * 4 * sizeof(unsigned short));
for (i = 0; i < mlen; i++) {
workspace[0*mlen + i] = (mlen-i <= a[0] ? a[mlen-i] : 0);
workspace[1*mlen + i] = (mlen-i <= b[0] ? b[mlen-i] : 0);
i = ssh1_bignum_bitcount(x);
ndigits = (28*i + 92)/93; /* multiply by 28/93 and round up */
ndigits++; /* allow for trailing \0 */
- ret = malloc(ndigits);
+ ret = smalloc(ndigits);
/*
* Now allocate some workspace to hold the binary form as we
* repeatedly divide it by ten. Initialise this to the
* big-endian form of the number.
*/
- workspace = malloc(sizeof(unsigned short) * x[0]);
+ workspace = smalloc(sizeof(unsigned short) * x[0]);
for (i = 0; i < x[0]; i++)
workspace[i] = x[x[0] - i];