#include <stdlib.h>
#include <string.h>
-#if 0 // use PuTTY main debugging for diagbn()
-#include <windows.h>
-#include "putty.h"
-#define debugprint debug
-#else
-#define debugprint(x) printf x
-#endif
+#include "misc.h"
#define BIGNUM_INTERNAL
typedef unsigned short *Bignum;
static Bignum newbn(int length)
{
- Bignum b = smalloc((length + 1) * sizeof(unsigned short));
+ Bignum b = snewn(length + 1, unsigned short);
if (!b)
abort(); /* FIXME */
memset(b, 0, (length + 1) * sizeof(*b));
Bignum copybn(Bignum orig)
{
- Bignum b = smalloc((orig[0] + 1) * sizeof(unsigned short));
+ Bignum b = snewn(orig[0] + 1, unsigned short);
if (!b)
abort(); /* FIXME */
memcpy(b, orig, (orig[0] + 1) * sizeof(*b));
/* Allocate m of size mlen, copy mod to m */
/* We use big endian internally */
mlen = mod[0];
- m = smalloc(mlen * sizeof(unsigned short));
+ m = snewn(mlen, unsigned short);
for (j = 0; j < mlen; j++)
m[j] = mod[mod[0] - j];
}
/* Allocate n of size mlen, copy base to n */
- n = smalloc(mlen * sizeof(unsigned short));
+ n = snewn(mlen, unsigned short);
i = mlen - base[0];
for (j = 0; j < i; j++)
n[j] = 0;
n[i + j] = base[base[0] - j];
/* Allocate a and b of size 2*mlen. Set a = 1 */
- a = smalloc(2 * mlen * sizeof(unsigned short));
- b = smalloc(2 * mlen * sizeof(unsigned short));
+ a = snewn(2 * mlen, unsigned short);
+ b = snewn(2 * mlen, unsigned short);
for (i = 0; i < 2 * mlen; i++)
a[i] = 0;
a[2 * mlen - 1] = 1;
/* Allocate m of size mlen, copy mod to m */
/* We use big endian internally */
mlen = mod[0];
- m = smalloc(mlen * sizeof(unsigned short));
+ m = snewn(mlen, unsigned short);
for (j = 0; j < mlen; j++)
m[j] = mod[mod[0] - j];
pqlen = (p[0] > q[0] ? p[0] : q[0]);
/* Allocate n of size pqlen, copy p to n */
- n = smalloc(pqlen * sizeof(unsigned short));
+ n = snewn(pqlen, unsigned short);
i = pqlen - p[0];
for (j = 0; j < i; j++)
n[j] = 0;
n[i + j] = p[p[0] - j];
/* Allocate o of size pqlen, copy q to o */
- o = smalloc(pqlen * sizeof(unsigned short));
+ o = snewn(pqlen, unsigned short);
i = pqlen - q[0];
for (j = 0; j < i; j++)
o[j] = 0;
o[i + j] = q[q[0] - j];
/* Allocate a of size 2*pqlen for result */
- a = smalloc(2 * pqlen * sizeof(unsigned short));
+ a = snewn(2 * pqlen, unsigned short);
/* Main computation */
internal_mul(n, o, a, pqlen);
* Compute p % mod.
* The most significant word of mod MUST be non-zero.
* We assume that the result array is the same size as the mod array.
- * We optionally write out a quotient.
+ * We optionally write out a quotient if `quotient' is non-NULL.
+ * We can avoid writing out the result if `result' is NULL.
*/
-void bigmod(Bignum p, Bignum mod, Bignum result, Bignum quotient)
+static void bigdivmod(Bignum p, Bignum mod, Bignum result, Bignum quotient)
{
unsigned short *n, *m;
int mshift;
/* Allocate m of size mlen, copy mod to m */
/* We use big endian internally */
mlen = mod[0];
- m = smalloc(mlen * sizeof(unsigned short));
+ m = snewn(mlen, unsigned short);
for (j = 0; j < mlen; j++)
m[j] = mod[mod[0] - j];
plen = mlen + 1;
/* Allocate n of size plen, copy p to n */
- n = smalloc(plen * sizeof(unsigned short));
+ n = snewn(plen, unsigned short);
for (j = 0; j < plen; j++)
n[j] = 0;
for (j = 1; j <= p[0]; j++)
}
/* Copy result to buffer */
- for (i = 1; i <= result[0]; i++) {
- int j = plen - i;
- result[i] = j >= 0 ? n[j] : 0;
+ if (result) {
+ for (i = 1; i <= result[0]; i++) {
+ int j = plen - i;
+ result[i] = j >= 0 ? n[j] : 0;
+ }
}
/* Free temporary arrays */
bn[i]--;
}
-Bignum bignum_from_bytes(unsigned char *data, int nbytes)
+Bignum bignum_from_bytes(const unsigned char *data, int nbytes)
{
Bignum result;
int w, i;
* Read an ssh1-format bignum from a data buffer. Return the number
* of bytes consumed.
*/
-int ssh1_read_bignum(unsigned char *data, Bignum * result)
+int ssh1_read_bignum(const unsigned char *data, Bignum * result)
{
- unsigned char *p = data;
+ const unsigned char *p = data;
int i;
int w, b;
Bignum ret;
/* mlen space for a, mlen space for b, 2*mlen for result */
- workspace = smalloc(mlen * 4 * sizeof(unsigned short));
+ workspace = snewn(mlen * 4, 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);
}
/*
- * Convert a (max 16-bit) short into a bignum.
+ * Convert a (max 32-bit) long into a bignum.
*/
-Bignum bignum_from_short(unsigned short n)
+Bignum bignum_from_long(unsigned long n)
{
Bignum ret;
- ret = newbn(2);
- ret[1] = n & 0xFFFF;
- ret[2] = (n >> 16) & 0xFFFF;
- ret[0] = (ret[2] ? 2 : 1);
+ ret = newbn(3);
+ ret[1] = (unsigned short)(n & 0xFFFF);
+ ret[2] = (unsigned short)((n >> 16) & 0xFFFF);
+ ret[3] = 0;
+ ret[0] = (ret[2] ? 2 : 1);
return ret;
}
return (unsigned short) r;
}
+#if 0
void diagbn(char *prefix, Bignum md)
{
+#ifdef DEBUG
int i, nibbles, morenibbles;
static const char hex[] = "0123456789ABCDEF";
- debugprint(("%s0x", prefix ? prefix : ""));
+ debug(("%s0x", prefix ? prefix : ""));
nibbles = (3 + bignum_bitcount(md)) / 4;
if (nibbles < 1)
nibbles = 1;
morenibbles = 4 * md[0] - nibbles;
for (i = 0; i < morenibbles; i++)
- debugprint(("-"));
+ debug(("-"));
for (i = nibbles; i--;)
- debugprint(
- ("%c",
- hex[(bignum_byte(md, i / 2) >> (4 * (i % 2))) & 0xF]));
+ debug(("%c",
+ hex[(bignum_byte(md, i / 2) >> (4 * (i % 2))) & 0xF]));
if (prefix)
- debugprint(("\n"));
+ debug(("\n"));
+#endif
+}
+#endif
+
+/*
+ * Simple division.
+ */
+Bignum bigdiv(Bignum a, Bignum b)
+{
+ Bignum q = newbn(a[0]);
+ bigdivmod(a, b, NULL, q);
+ return q;
+}
+
+/*
+ * Simple remainder.
+ */
+Bignum bigmod(Bignum a, Bignum b)
+{
+ Bignum r = newbn(b[0]);
+ bigdivmod(a, b, r, NULL);
+ return r;
}
/*
Bignum a = copybn(av);
Bignum b = copybn(bv);
- diagbn("a = ", a);
- diagbn("b = ", b);
while (bignum_cmp(b, Zero) != 0) {
Bignum t = newbn(b[0]);
- bigmod(a, b, t, NULL);
- diagbn("t = ", t);
+ bigdivmod(a, b, t, NULL);
while (t[0] > 1 && t[t[0]] == 0)
t[0]--;
freebn(a);
while (bignum_cmp(b, One) != 0) {
Bignum t = newbn(b[0]);
Bignum q = newbn(a[0]);
- bigmod(a, b, t, q);
+ bigdivmod(a, b, t, q);
while (t[0] > 1 && t[t[0]] == 0)
t[0]--;
freebn(a);
i = bignum_bitcount(x);
ndigits = (28 * i + 92) / 93; /* multiply by 28/93 and round up */
ndigits++; /* allow for trailing \0 */
- ret = smalloc(ndigits);
+ ret = snewn(ndigits, char);
/*
* 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 = smalloc(sizeof(unsigned short) * x[0]);
+ workspace = snewn(x[0], unsigned short);
for (i = 0; i < x[0]; i++)
workspace[i] = x[x[0] - i];