crypto/bn: bignum supports negative number operations
1.Add sign to indicate negative and positive 2.Fix case where there are negative numbers in the operation 3.expand to 512 bytes to support rsa2048 Signed-off-by: makejian <makejian@xiaomi.com>
This commit is contained in:
parent
fbb2e5f781
commit
21514e266a
112
crypto/bn.c
112
crypto/bn.c
@ -159,6 +159,38 @@ static void rshift_one_bit(FAR struct bn *a)
|
|||||||
a->array[BN_ARRAY_SIZE - 1] >>= 1;
|
a->array[BN_ARRAY_SIZE - 1] >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void bignum_add_sub(struct bn *a, struct bn *b, struct bn *c, int flip)
|
||||||
|
{
|
||||||
|
int cmp;
|
||||||
|
int s;
|
||||||
|
|
||||||
|
require(a, "a is null");
|
||||||
|
require(b, "b is null");
|
||||||
|
require(c, "c is null");
|
||||||
|
|
||||||
|
s = a->s;
|
||||||
|
if (a->s * b->s * flip < 0)
|
||||||
|
{
|
||||||
|
cmp = bignum_cmp_abs(a, b);
|
||||||
|
if (cmp >= 0)
|
||||||
|
{
|
||||||
|
bignum_sub_abs(a, b, c);
|
||||||
|
c->s = cmp == 0 ? 1 : s;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bignum_sub_abs(b, a, c);
|
||||||
|
c->s = -s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bignum_add_abs(a, b, c);
|
||||||
|
c->s = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -175,6 +207,8 @@ void bignum_init(FAR struct bn *n)
|
|||||||
{
|
{
|
||||||
n->array[i] = 0;
|
n->array[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n->s = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bignum_from_int(FAR struct bn *n, DTYPE_TMP i)
|
void bignum_from_int(FAR struct bn *n, DTYPE_TMP i)
|
||||||
@ -345,6 +379,11 @@ void bignum_inc(FAR struct bn *n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void bignum_add(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c)
|
void bignum_add(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c)
|
||||||
|
{
|
||||||
|
bignum_add_sub(a, b, c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bignum_add_abs(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c)
|
||||||
{
|
{
|
||||||
DTYPE_TMP tmp;
|
DTYPE_TMP tmp;
|
||||||
int carry = 0;
|
int carry = 0;
|
||||||
@ -363,6 +402,11 @@ void bignum_add(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void bignum_sub(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c)
|
void bignum_sub(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c)
|
||||||
|
{
|
||||||
|
bignum_add_sub(a, b, c, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bignum_sub_abs(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c)
|
||||||
{
|
{
|
||||||
DTYPE_TMP res;
|
DTYPE_TMP res;
|
||||||
DTYPE_TMP tmp1;
|
DTYPE_TMP tmp1;
|
||||||
@ -415,11 +459,20 @@ void bignum_mul(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c)
|
|||||||
((DTYPE_TMP)a->array[i] * (DTYPE_TMP)b->array[j]);
|
((DTYPE_TMP)a->array[i] * (DTYPE_TMP)b->array[j]);
|
||||||
bignum_from_int(&tmp, intermediate);
|
bignum_from_int(&tmp, intermediate);
|
||||||
lshift_word(&tmp, i + j);
|
lshift_word(&tmp, i + j);
|
||||||
bignum_add(&tmp, &row, &row);
|
bignum_add_abs(&tmp, &row, &row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bignum_add(c, &row, c);
|
bignum_add_abs(c, &row, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bignum_is_zero(c) != 0)
|
||||||
|
{
|
||||||
|
c->s = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c->s = a->s * b->s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,7 +492,7 @@ void bignum_div(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c)
|
|||||||
bignum_assign(&denom, b); /* denom = b */
|
bignum_assign(&denom, b); /* denom = b */
|
||||||
bignum_assign(&tmp, a); /* tmp = a */
|
bignum_assign(&tmp, a); /* tmp = a */
|
||||||
|
|
||||||
while (bignum_cmp(&denom, a) != LARGER) /* while (denom <= a) { */
|
while (bignum_cmp_abs(&denom, &tmp) != LARGER) /* while (denom <= a) { */
|
||||||
{
|
{
|
||||||
if (denom.array[BN_ARRAY_SIZE - 1] >= half_max)
|
if (denom.array[BN_ARRAY_SIZE - 1] >= half_max)
|
||||||
{
|
{
|
||||||
@ -461,16 +514,18 @@ void bignum_div(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c)
|
|||||||
|
|
||||||
while (!bignum_is_zero(¤t)) /* while (current != 0) */
|
while (!bignum_is_zero(¤t)) /* while (current != 0) */
|
||||||
{
|
{
|
||||||
if (bignum_cmp(&tmp, &denom) != SMALLER) /* if (dividend >= denom) */
|
if (bignum_cmp_abs(&tmp, &denom) != SMALLER) /* if (dividend >= denom) */
|
||||||
{
|
{
|
||||||
bignum_sub(&tmp, &denom, &tmp); /* dividend -= denom; */
|
bignum_sub_abs(&tmp, &denom, &tmp); /* dividend -= denom; */
|
||||||
bignum_or(c, ¤t, c); /* answer |= current; */
|
bignum_or(c, ¤t, c); /* answer |= current; */
|
||||||
}
|
}
|
||||||
|
|
||||||
rshift_one_bit(¤t); /* current >>= 1; */
|
rshift_one_bit(¤t); /* current >>= 1; */
|
||||||
rshift_one_bit(&denom); /* denom >>= 1; */
|
rshift_one_bit(&denom); /* denom >>= 1; */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c->s = a->s * b->s;
|
||||||
|
|
||||||
/* return answer; */
|
/* return answer; */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,6 +635,11 @@ void bignum_divmod(FAR struct bn *a, FAR struct bn *b,
|
|||||||
/* c = a - tmp */
|
/* c = a - tmp */
|
||||||
|
|
||||||
bignum_sub(a, &tmp, d);
|
bignum_sub(a, &tmp, d);
|
||||||
|
|
||||||
|
while (d->s < 0)
|
||||||
|
{
|
||||||
|
bignum_add(d, b, d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bignum_and(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c)
|
void bignum_and(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c)
|
||||||
@ -631,6 +691,40 @@ int bignum_cmp(FAR struct bn *a, FAR struct bn *b)
|
|||||||
require(a, "a is null");
|
require(a, "a is null");
|
||||||
require(b, "b is null");
|
require(b, "b is null");
|
||||||
|
|
||||||
|
if (a->s > 0 && b->s < 0)
|
||||||
|
{
|
||||||
|
return LARGER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b->s > 0 && a->s < 0)
|
||||||
|
{
|
||||||
|
return SMALLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
i -= 1; /* Decrement first, to start with last array element */
|
||||||
|
if (a->array[i] > b->array[i])
|
||||||
|
{
|
||||||
|
return a->s;
|
||||||
|
}
|
||||||
|
else if (a->array[i] < b->array[i])
|
||||||
|
{
|
||||||
|
return -a->s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (i != 0);
|
||||||
|
|
||||||
|
return EQUAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bignum_cmp_abs(FAR struct bn *a, FAR struct bn *b)
|
||||||
|
{
|
||||||
|
int i = BN_ARRAY_SIZE;
|
||||||
|
|
||||||
|
require(a, "a is null");
|
||||||
|
require(b, "b is null");
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
i -= 1; /* Decrement first, to start with last array element */
|
i -= 1; /* Decrement first, to start with last array element */
|
||||||
@ -741,9 +835,9 @@ void bignum_isqrt(FAR struct bn *a, FAR struct bn *b)
|
|||||||
bignum_assign(&low, &mid);
|
bignum_assign(&low, &mid);
|
||||||
}
|
}
|
||||||
|
|
||||||
bignum_sub(&high, &low, &mid);
|
bignum_sub_abs(&high, &low, &mid);
|
||||||
rshift_one_bit(&mid);
|
rshift_one_bit(&mid);
|
||||||
bignum_add(&low, &mid, &mid);
|
bignum_add_abs(&low, &mid, &mid);
|
||||||
bignum_inc(&mid);
|
bignum_inc(&mid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -761,6 +855,8 @@ void bignum_assign(FAR struct bn *dst, FAR struct bn *src)
|
|||||||
{
|
{
|
||||||
dst->array[i] = src->array[i];
|
dst->array[i] = src->array[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dst->s = src->s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pow_mod_faster(FAR struct bn *a, FAR struct bn *b,
|
void pow_mod_faster(FAR struct bn *a, FAR struct bn *b,
|
||||||
|
@ -68,7 +68,7 @@
|
|||||||
|
|
||||||
/* Size of big-numbers in bytes */
|
/* Size of big-numbers in bytes */
|
||||||
|
|
||||||
#define BN_ARRAY_SIZE (256 / WORD_SIZE)
|
#define BN_ARRAY_SIZE (512 / WORD_SIZE)
|
||||||
|
|
||||||
/* Data type of array in structure */
|
/* Data type of array in structure */
|
||||||
|
|
||||||
@ -101,6 +101,9 @@
|
|||||||
|
|
||||||
struct bn
|
struct bn
|
||||||
{
|
{
|
||||||
|
/* Sign: -1 if the bignum is negative, 1 otherwise. */
|
||||||
|
|
||||||
|
int s;
|
||||||
DTYPE array[BN_ARRAY_SIZE];
|
DTYPE array[BN_ARRAY_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -131,10 +134,18 @@ void bignum_to_string(FAR struct bn *n, FAR char *str, int maxsize);
|
|||||||
|
|
||||||
void bignum_add(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c);
|
void bignum_add(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c);
|
||||||
|
|
||||||
|
/* c = |a| + |b| */
|
||||||
|
|
||||||
|
void bignum_add_abs(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c);
|
||||||
|
|
||||||
/* c = a - b */
|
/* c = a - b */
|
||||||
|
|
||||||
void bignum_sub(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c);
|
void bignum_sub(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c);
|
||||||
|
|
||||||
|
/* c = |a| - |b| */
|
||||||
|
|
||||||
|
void bignum_sub_abs(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c);
|
||||||
|
|
||||||
/* c = a * b */
|
/* c = a * b */
|
||||||
|
|
||||||
void bignum_mul(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c);
|
void bignum_mul(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c);
|
||||||
@ -180,6 +191,10 @@ void bignum_rshift(FAR struct bn *a, FAR struct bn *b, int nbits);
|
|||||||
|
|
||||||
int bignum_cmp(FAR struct bn *a, FAR struct bn *b);
|
int bignum_cmp(FAR struct bn *a, FAR struct bn *b);
|
||||||
|
|
||||||
|
/* Compare |A| and |B| */
|
||||||
|
|
||||||
|
int bignum_cmp_abs(FAR struct bn *a, FAR struct bn *b);
|
||||||
|
|
||||||
/* For comparison with zero */
|
/* For comparison with zero */
|
||||||
|
|
||||||
int bignum_is_zero(FAR struct bn *n);
|
int bignum_is_zero(FAR struct bn *n);
|
||||||
|
Loading…
Reference in New Issue
Block a user