mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 06:18:40 +08:00
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
2 changed files with 120 additions and 9 deletions
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;
|
||||
}
|
||||
|
||||
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
|
||||
****************************************************************************/
|
||||
|
@ -175,6 +207,8 @@ void bignum_init(FAR struct bn *n)
|
|||
{
|
||||
n->array[i] = 0;
|
||||
}
|
||||
|
||||
n->s = 1;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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 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]);
|
||||
bignum_from_int(&tmp, intermediate);
|
||||
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(&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)
|
||||
{
|
||||
|
@ -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) */
|
||||
{
|
||||
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_or(c, ¤t, c); /* answer |= current; */
|
||||
bignum_sub_abs(&tmp, &denom, &tmp); /* dividend -= denom; */
|
||||
bignum_or(c, ¤t, c); /* answer |= current; */
|
||||
}
|
||||
|
||||
rshift_one_bit(¤t); /* current >>= 1; */
|
||||
rshift_one_bit(&denom); /* denom >>= 1; */
|
||||
}
|
||||
|
||||
c->s = a->s * b->s;
|
||||
|
||||
/* return answer; */
|
||||
}
|
||||
|
||||
|
@ -580,6 +635,11 @@ void bignum_divmod(FAR struct bn *a, FAR struct bn *b,
|
|||
/* c = a - tmp */
|
||||
|
||||
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)
|
||||
|
@ -631,6 +691,40 @@ int bignum_cmp(FAR struct bn *a, FAR struct bn *b)
|
|||
require(a, "a 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
|
||||
{
|
||||
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_sub(&high, &low, &mid);
|
||||
bignum_sub_abs(&high, &low, &mid);
|
||||
rshift_one_bit(&mid);
|
||||
bignum_add(&low, &mid, &mid);
|
||||
bignum_add_abs(&low, &mid, &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->s = src->s;
|
||||
}
|
||||
|
||||
void pow_mod_faster(FAR struct bn *a, FAR struct bn *b,
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
|
||||
/* 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 */
|
||||
|
||||
|
@ -101,6 +101,9 @@
|
|||
|
||||
struct bn
|
||||
{
|
||||
/* Sign: -1 if the bignum is negative, 1 otherwise. */
|
||||
|
||||
int s;
|
||||
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);
|
||||
|
||||
/* c = |a| + |b| */
|
||||
|
||||
void bignum_add_abs(FAR struct bn *a, FAR struct bn *b, FAR struct bn *c);
|
||||
|
||||
/* c = a - b */
|
||||
|
||||
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 */
|
||||
|
||||
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);
|
||||
|
||||
/* Compare |A| and |B| */
|
||||
|
||||
int bignum_cmp_abs(FAR struct bn *a, FAR struct bn *b);
|
||||
|
||||
/* For comparison with zero */
|
||||
|
||||
int bignum_is_zero(FAR struct bn *n);
|
||||
|
|
Loading…
Reference in a new issue