📄 bn32.c
字号:
return 0;
}
int
bnMul_32(BigNum *dest, BigNum const *a, BigNum const *b)
{
unsigned s, t;
BNWORD32 *srcbuf;
PGPBoolean secure = dest->isSecure || a->isSecure || b->isSecure;
s = bniNorm_32((BNWORD32 *)a->ptr, a->size);
t = bniNorm_32((BNWORD32 *)b->ptr, b->size);
if (!s || !t) {
dest->size = 0;
return 0;
}
if (a == b)
return bnSquare_32(dest, a);
bnSizeCheck(dest, s+t);
if (dest == a) {
BNIALLOC( dest->mgr, secure, srcbuf, BNWORD32, s);
if (!srcbuf)
return -1;
bniCopy_32(srcbuf, (BNWORD32 *)a->ptr, s);
bniMul_32((BNWORD32 *)dest->ptr, srcbuf, s,
(BNWORD32 *)b->ptr, t);
BNIFREE(srcbuf, s);
} else if (dest == b) {
BNIALLOC( dest->mgr, secure, srcbuf, BNWORD32, t);
if (!srcbuf)
return -1;
bniCopy_32(srcbuf, (BNWORD32 *)b->ptr, t);
bniMul_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s,
srcbuf, t);
BNIFREE(srcbuf, t);
} else {
bniMul_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s,
(BNWORD32 *)b->ptr, t);
}
dest->size = bniNorm_32((BNWORD32 *)dest->ptr, s+t);
MALLOCDB;
return 0;
}
int
bnMulQ_32(BigNum *dest, BigNum const *a, unsigned b)
{
unsigned s;
s = bniNorm_32((BNWORD32 *)a->ptr, a->size);
if (!s || !b) {
dest->size = 0;
return 0;
}
if (b == 1)
return bnCopy_32(dest, a);
bnSizeCheck(dest, s+1);
bniMulN1_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s, b);
dest->size = bniNorm_32((BNWORD32 *)dest->ptr, s+1);
MALLOCDB;
return 0;
}
int
bnDivMod_32(BigNum *q, BigNum *r, BigNum const *n,
BigNum const *d)
{
unsigned dsize, nsize;
BNWORD32 qhigh;
dsize = bniNorm_32((BNWORD32 *)d->ptr, d->size);
nsize = bniNorm_32((BNWORD32 *)n->ptr, n->size);
if (nsize < dsize) {
q->size = 0; /* No quotient */
r->size = nsize;
return 0; /* Success */
}
bnSizeCheck(q, nsize-dsize);
if (r != n) { /* You are allowed to reduce in place */
bnSizeCheck(r, nsize);
bniCopy_32((BNWORD32 *)r->ptr, (BNWORD32 *)n->ptr, nsize);
}
qhigh = bniDiv_32((BNWORD32 *)q->ptr, (BNWORD32 *)r->ptr, nsize,
(BNWORD32 *)d->ptr, dsize);
nsize -= dsize;
if (qhigh) {
bnSizeCheck(q, nsize+1);
*((BNWORD32 *)q->ptr BIGLITTLE(-nsize-1,+nsize)) = qhigh;
q->size = nsize+1;
} else {
q->size = bniNorm_32((BNWORD32 *)q->ptr, nsize);
}
r->size = bniNorm_32((BNWORD32 *)r->ptr, dsize);
MALLOCDB;
return 0;
}
int
bnMod_32(BigNum *dest, BigNum const *src, BigNum const *d)
{
unsigned dsize, nsize;
nsize = bniNorm_32((BNWORD32 *)src->ptr, src->size);
dsize = bniNorm_32((BNWORD32 *)d->ptr, d->size);
if (dest != src) {
bnSizeCheck(dest, nsize);
bniCopy_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, nsize);
}
if (nsize < dsize) {
dest->size = nsize; /* No quotient */
return 0;
}
(void)bniDiv_32((BNWORD32 *)dest->ptr BIGLITTLE(-dsize,+dsize),
(BNWORD32 *)dest->ptr, nsize,
(BNWORD32 *)d->ptr, dsize);
dest->size = bniNorm_32((BNWORD32 *)dest->ptr, dsize);
MALLOCDB;
return 0;
}
unsigned
bnModQ_32(BigNum const *src, unsigned d)
{
unsigned s;
s = bniNorm_32((BNWORD32 *)src->ptr, src->size);
if (!s)
return 0;
if (d & (d-1)) /* Not a power of 2 */
d = bniModQ_32((BNWORD32 *)src->ptr, s, d);
else
d = (unsigned)((BNWORD32 *)src->ptr)[BIGLITTLE(-1,0)] & (d-1);
return d;
}
int
bnExpMod_32(BigNum *dest, BigNum const *n,
BigNum const *exp, BigNum const *mod)
{
unsigned nsize, esize, msize;
PGPBoolean secure;
secure = dest->isSecure || n->isSecure ||
exp->isSecure || mod->isSecure;
nsize = bniNorm_32((BNWORD32 *)n->ptr, n->size);
esize = bniNorm_32((BNWORD32 *)exp->ptr, exp->size);
msize = bniNorm_32((BNWORD32 *)mod->ptr, mod->size);
if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
return -1; /* Illegal modulus! */
bnSizeCheck(dest, msize);
/* Special-case base of 2 */
if (nsize == 1 && ((BNWORD32 *)n->ptr)[BIGLITTLE(-1,0)] == 2) {
if (bniTwoExpMod_32( dest->mgr, secure,
(BNWORD32 *)dest->ptr,
(BNWORD32 *)exp->ptr, esize,
(BNWORD32 *)mod->ptr, msize) < 0)
return -1;
} else {
if (bniExpMod_32( dest->mgr, secure,
(BNWORD32 *)dest->ptr,
(BNWORD32 *)n->ptr, nsize,
(BNWORD32 *)exp->ptr, esize,
(BNWORD32 *)mod->ptr, msize) < 0)
return -1;
}
dest->size = bniNorm_32((BNWORD32 *)dest->ptr, msize);
MALLOCDB;
return 0;
}
int
bnDoubleExpMod_32(BigNum *dest,
BigNum const *n1, BigNum const *e1,
BigNum const *n2, BigNum const *e2,
BigNum const *mod)
{
unsigned n1size, e1size, n2size, e2size, msize;
PGPBoolean secure;
secure = dest->isSecure || n1->isSecure || e1->isSecure ||
n2->isSecure || e2->isSecure || mod->isSecure;
n1size = bniNorm_32((BNWORD32 *)n1->ptr, n1->size);
e1size = bniNorm_32((BNWORD32 *)e1->ptr, e1->size);
n2size = bniNorm_32((BNWORD32 *)n2->ptr, n2->size);
e2size = bniNorm_32((BNWORD32 *)e2->ptr, e2->size);
msize = bniNorm_32((BNWORD32 *)mod->ptr, mod->size);
if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
return -1; /* Illegal modulus! */
bnSizeCheck(dest, msize);
if (bniDoubleExpMod_32(
dest->mgr, secure,
(BNWORD32 *)dest->ptr,
(BNWORD32 *)n1->ptr, n1size, (BNWORD32 *)e1->ptr, e1size,
(BNWORD32 *)n2->ptr, n2size, (BNWORD32 *)e2->ptr, e2size,
(BNWORD32 *)mod->ptr, msize) < 0)
return -1;
dest->size = bniNorm_32((BNWORD32 *)dest->ptr, msize);
MALLOCDB;
return 0;
}
int
bnTwoExpMod_32(BigNum *n, BigNum const *exp,
BigNum const *mod)
{
unsigned esize, msize;
PGPBoolean secure = n->isSecure || exp->isSecure || mod->isSecure;
esize = bniNorm_32((BNWORD32 *)exp->ptr, exp->size);
msize = bniNorm_32((BNWORD32 *)mod->ptr, mod->size);
if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
return -1; /* Illegal modulus! */
bnSizeCheck(n, msize);
if (bniTwoExpMod_32( n->mgr, secure,
(BNWORD32 *)n->ptr, (BNWORD32 *)exp->ptr, esize,
(BNWORD32 *)mod->ptr, msize) < 0)
return -1;
n->size = bniNorm_32((BNWORD32 *)n->ptr, msize);
MALLOCDB;
return 0;
}
int
bnGcd_32(BigNum *dest, BigNum const *a, BigNum const *b)
{
BNWORD32 *tmp;
unsigned asize, bsize;
int i;
PGPBoolean secure = dest->isSecure || a->isSecure || b->isSecure;
/* Kind of silly, but we might as well permit it... */
if (a == b)
return dest == a ? 0 : bnCopy(dest, a);
/* Ensure a is not the same as "dest" */
if (a == dest) {
a = b;
b = dest;
}
asize = bniNorm_32((BNWORD32 *)a->ptr, a->size);
bsize = bniNorm_32((BNWORD32 *)b->ptr, b->size);
bnSizeCheck(dest, bsize+1);
/* Copy a to tmp */
BNIALLOC( dest->mgr, secure, tmp, BNWORD32, asize+1);
if (!tmp)
return -1;
bniCopy_32(tmp, (BNWORD32 *)a->ptr, asize);
/* Copy b to dest, if necessary */
if (dest != b)
bniCopy_32((BNWORD32 *)dest->ptr,
(BNWORD32 *)b->ptr, bsize);
if (bsize > asize || (bsize == asize &&
bniCmp_32((BNWORD32 *)b->ptr, (BNWORD32 *)a->ptr, asize) > 0))
{
i = bniGcd_32((BNWORD32 *)dest->ptr, bsize, tmp, asize,
&dest->size);
if (i > 0) /* Result in tmp, not dest */
bniCopy_32((BNWORD32 *)dest->ptr, tmp, dest->size);
} else {
i = bniGcd_32(tmp, asize, (BNWORD32 *)dest->ptr, bsize,
&dest->size);
if (i == 0) /* Result in tmp, not dest */
bniCopy_32((BNWORD32 *)dest->ptr, tmp, dest->size);
}
BNIFREE(tmp, asize+1);
MALLOCDB;
return (i < 0) ? i : 0;
}
int
bnInv_32(BigNum *dest, BigNum const *src,
BigNum const *mod)
{
unsigned s, m;
int i;
PGPBoolean secure;
secure = dest->isSecure || src->isSecure || mod->isSecure;
s = bniNorm_32((BNWORD32 *)src->ptr, src->size);
m = bniNorm_32((BNWORD32 *)mod->ptr, mod->size);
/* bniInv_32 requires that the input be less than the modulus */
if (m < s ||
(m==s && bniCmp_32((BNWORD32 *)src->ptr, (BNWORD32 *)mod->ptr, s)))
{
bnSizeCheck(dest, s + (m==s));
if (dest != src)
bniCopy_32((BNWORD32 *)dest->ptr,
(BNWORD32 *)src->ptr, s);
/* Pre-reduce modulo the modulus */
(void)bniDiv_32((BNWORD32 *)dest->ptr BIGLITTLE(-m,+m),
(BNWORD32 *)dest->ptr, s,
(BNWORD32 *)mod->ptr, m);
s = bniNorm_32((BNWORD32 *)dest->ptr, m);
MALLOCDB;
} else {
bnSizeCheck(dest, m+1);
if (dest != src)
bniCopy_32((BNWORD32 *)dest->ptr,
(BNWORD32 *)src->ptr, s);
}
i = bniInv_32( dest->mgr, secure,
(BNWORD32 *)dest->ptr, s, (BNWORD32 *)mod->ptr, m);
if (i == 0)
dest->size = bniNorm_32((BNWORD32 *)dest->ptr, m);
MALLOCDB;
return i;
}
/*
* Shift a bignum left the appropriate number of bits,
* multiplying by 2^amt.
*/
int
bnLShift_32(BigNum *dest, unsigned amt)
{
unsigned s = dest->size;
BNWORD32 carry;
if (amt % 32) {
carry = bniLshift_32((BNWORD32 *)dest->ptr, s, amt % 32);
if (carry) {
s++;
bnSizeCheck(dest, s);
((BNWORD32 *)dest->ptr)[BIGLITTLE(-s,s-1)] = carry;
}
}
amt /= 32;
if (amt) {
bnSizeCheck(dest, s+amt);
memmove((BNWORD32 *)dest->ptr BIGLITTLE(-s-amt, +amt),
(BNWORD32 *)dest->ptr BIG(-s),
s * sizeof(BNWORD32));
bniZero_32((BNWORD32 *)dest->ptr, amt);
s += amt;
}
dest->size = s;
MALLOCDB;
return 0;
}
/*
* Shift a bignum right the appropriate number of bits,
* dividing by 2^amt.
*/
void bnRShift_32(BigNum *dest, unsigned amt)
{
unsigned s = dest->size;
if (amt >= 32) {
memmove(
(BNWORD32 *)dest->ptr BIG(-s+amt/32),
(BNWORD32 *)dest->ptr BIGLITTLE(-s, +amt/32),
(s-amt/32) * sizeof(BNWORD32));
s -= amt/32;
amt %= 32;
}
if (amt)
(void)bniRshift_32((BNWORD32 *)dest->ptr, s, amt);
dest->size = bniNorm_32((BNWORD32 *)dest->ptr, s);
MALLOCDB;
}
/*
* Shift a bignum right until it is odd, and return the number of
* bits shifted. n = d * 2^s. Replaces n with d and returns s.
* Returns 0 when given 0. (Another valid answer is infinity.)
*/
unsigned
bnMakeOdd_32(BigNum *n)
{
unsigned size;
unsigned s; /* shift amount */
BNWORD32 *p;
BNWORD32 t;
p = (BNWORD32 *)n->ptr;
size = bniNorm_32(p, n->size);
if (!size)
return 0;
t = BIGLITTLE(p[-1],p[0]);
s = 0;
/* See how many words we have to shift */
if (!t) {
/* Shift by words */
do {
s++;
BIGLITTLE(--p,p++);
} while ((t = BIGLITTLE(p[-1],p[0])) == 0);
size -= s;
s *= 32;
memmove((BNWORD32 *)n->ptr BIG(-size), p BIG(-size),
size * sizeof(BNWORD32));
p = (BNWORD32 *)n->ptr;
MALLOCDB;
}
pgpAssert(t);
/* Now count the bits */
while ((t & 1) == 0) {
t >>= 1;
s++;
}
/* Shift the bits */
if (s & (32-1)) {
bniRshift_32(p, size, s & (32-1));
/* Renormalize */
if (BIGLITTLE(*(p-size),*(p+(size-1))) == 0)
--size;
}
n->size = size;
MALLOCDB;
return s;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -