1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-15 10:07:39 -05:00

Remove the last lingering knowledge, outside sshbn.c, of the

internal structure of the Bignum type. Bignum is now a fully opaque
type unless you're inside sshbn.c.

[originally from svn r960]
This commit is contained in:
Simon Tatham
2001-03-01 17:41:26 +00:00
parent 7717c386a1
commit f72b5aa95f
7 changed files with 160 additions and 165 deletions

82
sshbn.c
View File

@ -6,6 +6,9 @@
#include <stdlib.h>
#include <string.h>
#define BIGNUM_INTERNAL
typedef unsigned short *Bignum;
#include "ssh.h"
unsigned short bnZero[1] = { 0 };
@ -27,7 +30,7 @@ unsigned short bnOne[2] = { 1, 1 };
Bignum Zero = bnZero, One = bnOne;
Bignum newbn(int length) {
static Bignum newbn(int length) {
Bignum b = smalloc((length+1)*sizeof(unsigned short));
if (!b)
abort(); /* FIXME */
@ -36,6 +39,10 @@ Bignum newbn(int length) {
return b;
}
void bn_restore_invariant(Bignum b) {
while (b[0] > 1 && b[b[0]] == 0) b[0]--;
}
Bignum copybn(Bignum orig) {
Bignum b = smalloc((orig[0]+1)*sizeof(unsigned short));
if (!b)
@ -52,6 +59,12 @@ void freebn(Bignum b) {
sfree(b);
}
Bignum bn_power_2(int n) {
Bignum ret = newbn((n+15)/16);
bignum_set_bit(ret, n, 1);
return ret;
}
/*
* Compute c = a * b.
* Input is in the first len words of a and b.
@ -410,41 +423,47 @@ void decbn(Bignum bn) {
bn[i]--;
}
Bignum bignum_from_bytes(unsigned char *data, int nbytes) {
Bignum result;
int w, i;
w = (nbytes+1)/2; /* bytes -> words */
result = newbn(w);
for (i=1; i<=w; i++)
result[i] = 0;
for (i=nbytes; i-- ;) {
unsigned char byte = *data++;
if (i & 1)
result[1+i/2] |= byte<<8;
else
result[1+i/2] |= byte;
}
while (result[0] > 1 && result[result[0]] == 0) result[0]--;
return result;
}
/*
* Read an ssh1-format bignum from a data buffer. Return the number
* of bytes consumed.
*/
int ssh1_read_bignum(unsigned char *data, Bignum *result) {
unsigned char *p = data;
Bignum bn;
int i;
int w, b;
w = 0;
for (i=0; i<2; i++)
w = (w << 8) + *p++;
b = (w+7)/8; /* bits -> bytes */
w = (w+15)/16; /* bits -> words */
if (!result) /* just return length */
return b + 2;
bn = newbn(w);
*result = bignum_from_bytes(p, b);
for (i=1; i<=w; i++)
bn[i] = 0;
for (i=b; i-- ;) {
unsigned char byte = *p++;
if (i & 1)
bn[1+i/2] |= byte<<8;
else
bn[1+i/2] |= byte;
}
*result = bn;
return p - data;
return p + b - data;
}
/*
@ -452,7 +471,6 @@ int ssh1_read_bignum(unsigned char *data, Bignum *result) {
*/
int ssh1_bignum_bitcount(Bignum bn) {
int bitcount = bn[0] * 16 - 1;
while (bitcount >= 0 && (bn[bitcount/16+1] >> (bitcount % 16)) == 0)
bitcount--;
return bitcount + 1;
@ -619,6 +637,30 @@ Bignum bigmul(Bignum a, Bignum b) {
return bigmuladd(a, b, NULL);
}
/*
* Create a bignum which is the bitmask covering another one. That
* is, the smallest integer which is >= N and is also one less than
* a power of two.
*/
Bignum bignum_bitmask(Bignum n) {
Bignum ret = copybn(n);
int i;
unsigned short j;
i = ret[0];
while (n[i] == 0 && i > 0)
i--;
if (i <= 0)
return ret; /* input was zero */
j = 1;
while (j < n[i])
j = 2*j+1;
ret[i] = j;
while (--i > 0)
ret[i] = 0xFFFF;
return ret;
}
/*
* Convert a (max 16-bit) short into a bignum.
*/
@ -667,7 +709,7 @@ unsigned short bignum_mod_short(Bignum number, unsigned short modulus) {
return (unsigned short) r;
}
static void diagbn(char *prefix, Bignum md) {
void diagbn(char *prefix, Bignum md) {
int i, nibbles, morenibbles;
static const char hex[] = "0123456789ABCDEF";