forked from wolfSSL/wolfssl
Rework sp_div to work around static analysis error
Fix _sp_exptmod_mont_ext() to handle when number of bits in exponent is a multiple of the window size.
This commit is contained in:
@ -7008,6 +7008,158 @@ void sp_rshb(sp_int* a, int n, sp_int* r)
|
||||
#if defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_DH) || defined(HAVE_ECC) || \
|
||||
(!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \
|
||||
!defined(WOLFSSL_RSA_PUBLIC_ONLY))
|
||||
/* Divide a by d and return the quotient in r and the remainder in a.
|
||||
* r = a / d; a = a % d
|
||||
*
|
||||
* @param [in, out] a SP integer to be divided and remainder on out.
|
||||
* @param [in] d SP integer to divide by.
|
||||
* @param [out] r SP integer that is the quotient.
|
||||
* @param [out] trial SP integer that is product in trial division.
|
||||
*
|
||||
* @return MP_OKAY on success.
|
||||
* @return MP_VAL when operation fails - only when compiling small code.
|
||||
*/
|
||||
static int _sp_div(sp_int* a, sp_int* d, sp_int* r, sp_int* trial)
|
||||
{
|
||||
#ifdef WOLFSSL_SP_SMALL
|
||||
int c;
|
||||
#else
|
||||
int j;
|
||||
int o;
|
||||
#ifndef SQR_MUL_ASM
|
||||
sp_int_sword sw;
|
||||
#else
|
||||
sp_int_digit sl;
|
||||
sp_int_digit sh;
|
||||
sp_int_digit st;
|
||||
#endif
|
||||
#endif /* WOLFSSL_SP_SMALL */
|
||||
int err = MP_OKAY;
|
||||
int i;
|
||||
sp_int_digit t;
|
||||
sp_int_digit dt;
|
||||
|
||||
#ifdef WOLFSSL_SP_INT_NEGATIVE
|
||||
a->sign = MP_ZPOS;
|
||||
d->sign = MP_ZPOS;
|
||||
#endif /* WOLFSSL_SP_INT_NEGATIVE */
|
||||
|
||||
r->used = a->used - d->used + 1;
|
||||
sp_clear(r);
|
||||
r->used = a->used - d->used + 1;
|
||||
dt = d->dp[d->used-1];
|
||||
|
||||
for (i = d->used - 1; i > 0; i--) {
|
||||
if (a->dp[a->used - d->used + i] != d->dp[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (a->dp[a->used - d->used + i] >= d->dp[i]) {
|
||||
i = a->used;
|
||||
_sp_sub_off(a, d, a, a->used - d->used);
|
||||
/* Keep the same 'used' so that zeros will be put in. */
|
||||
a->used = i;
|
||||
r->dp[a->used - d->used] = 1;
|
||||
}
|
||||
|
||||
for (i = a->used - 1; i >= d->used; i--) {
|
||||
if (a->dp[i] == dt) {
|
||||
t = SP_DIGIT_MAX;
|
||||
}
|
||||
else {
|
||||
t = sp_div_word(a->dp[i], a->dp[i-1], dt);
|
||||
}
|
||||
#ifdef WOLFSSL_SP_SMALL
|
||||
do {
|
||||
err = _sp_mul_d(d, t, trial, i - d->used);
|
||||
if (err != MP_OKAY) {
|
||||
break;
|
||||
}
|
||||
c = _sp_cmp_abs(trial, a);
|
||||
if (c == MP_GT) {
|
||||
t--;
|
||||
}
|
||||
}
|
||||
while (c == MP_GT);
|
||||
|
||||
if (err != MP_OKAY) {
|
||||
break;
|
||||
}
|
||||
|
||||
_sp_sub_off(a, trial, a, 0);
|
||||
r->dp[i - d->used] += t;
|
||||
if (r->dp[i - d->used] < t) {
|
||||
r->dp[i + 1 - d->used]++;
|
||||
}
|
||||
#else
|
||||
o = i - d->used;
|
||||
do {
|
||||
#ifndef SQR_MUL_ASM
|
||||
sp_int_word tw = 0;
|
||||
#else
|
||||
sp_int_digit tl = 0;
|
||||
sp_int_digit th = 0;
|
||||
#endif
|
||||
for (j = 0; j < d->used; j++) {
|
||||
#ifndef SQR_MUL_ASM
|
||||
tw += (sp_int_word)d->dp[j] * t;
|
||||
trial->dp[j] = (sp_int_digit)tw;
|
||||
tw >>= SP_WORD_SIZE;
|
||||
#else
|
||||
SP_ASM_MUL_ADD_NO(tl, th, d->dp[j], t);
|
||||
trial->dp[j] = tl;
|
||||
tl = th;
|
||||
th = 0;
|
||||
#endif
|
||||
}
|
||||
#ifndef SQR_MUL_ASM
|
||||
trial->dp[j] = (sp_int_digit)tw;
|
||||
#else
|
||||
trial->dp[j] = tl;
|
||||
#endif
|
||||
|
||||
for (j = d->used; j > 0; j--) {
|
||||
if (trial->dp[j] != a->dp[j + o]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (trial->dp[j] > a->dp[j + o]) {
|
||||
t--;
|
||||
}
|
||||
}
|
||||
while (trial->dp[j] > a->dp[j + o]);
|
||||
|
||||
#ifndef SQR_MUL_ASM
|
||||
sw = 0;
|
||||
#else
|
||||
sl = 0;
|
||||
sh = 0;
|
||||
#endif
|
||||
for (j = 0; j <= d->used; j++) {
|
||||
#ifndef SQR_MUL_ASM
|
||||
sw += a->dp[j + o];
|
||||
sw -= trial->dp[j];
|
||||
a->dp[j + o] = (sp_int_digit)sw;
|
||||
sw >>= SP_WORD_SIZE;
|
||||
#else
|
||||
st = a->dp[j + o];
|
||||
SP_ASM_ADDC(sl, sh, st);
|
||||
st = trial->dp[j];
|
||||
SP_ASM_SUBC(sl, sh, st);
|
||||
a->dp[j + o] = sl;
|
||||
sl = sh;
|
||||
sh = (sp_int_digit)0 - (sl >> (SP_WORD_SIZE - 1));
|
||||
#endif
|
||||
}
|
||||
|
||||
r->dp[o] = t;
|
||||
#endif /* WOLFSSL_SP_SMALL */
|
||||
}
|
||||
a->used = i + 1;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Divide a by d and return the quotient in r and the remainder in rem.
|
||||
* r = a / d; rem = a % d
|
||||
*
|
||||
@ -7028,10 +7180,7 @@ int sp_div(sp_int* a, sp_int* d, sp_int* r, sp_int* rem)
|
||||
int err = MP_OKAY;
|
||||
int ret;
|
||||
int done = 0;
|
||||
int i;
|
||||
int s = 0;
|
||||
sp_int_digit dt;
|
||||
sp_int_digit t;
|
||||
sp_int* sa = NULL;
|
||||
sp_int* sd = NULL;
|
||||
sp_int* tr = NULL;
|
||||
@ -7121,52 +7270,61 @@ int sp_div(sp_int* a, sp_int* d, sp_int* r, sp_int* rem)
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate temprorary 'sp_int's and assign. */
|
||||
if ((!done) && (err == MP_OKAY)) {
|
||||
#if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \
|
||||
!defined(WOLFSSL_SP_NO_MALLOC)
|
||||
#if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \
|
||||
!defined(WOLFSSL_SP_NO_MALLOC)
|
||||
int cnt = 4;
|
||||
/* Resuse where possible. */
|
||||
if ((rem != NULL) && (rem != d) && (rem->size > a->used)) {
|
||||
sa = rem;
|
||||
cnt--;
|
||||
}
|
||||
if ((r != NULL) && (r != d)) {
|
||||
tr = r;
|
||||
cnt--;
|
||||
}
|
||||
/* Macro always has code associated with it and checks err first. */
|
||||
ALLOC_SP_INT_ARRAY(td, a->used + 1, cnt, err, NULL);
|
||||
#else
|
||||
#else
|
||||
ALLOC_SP_INT_ARRAY(td, a->used + 1, 4, err, NULL);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((!done) && (err == MP_OKAY)) {
|
||||
sd = td[0];
|
||||
trial = td[1];
|
||||
#if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \
|
||||
!defined(WOLFSSL_SP_NO_MALLOC)
|
||||
i = 2;
|
||||
sa = ((rem != NULL) && (rem != d) && (rem->size > a->used)) ? rem :
|
||||
td[i++];
|
||||
tr = ((r != NULL) && (r != d)) ? r : td[i];
|
||||
#else
|
||||
#if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \
|
||||
!defined(WOLFSSL_SP_NO_MALLOC)
|
||||
int i = 2;
|
||||
|
||||
/* Set to temporary when not reusing. */
|
||||
if (sa == NULL) {
|
||||
sa = td[i++];
|
||||
}
|
||||
if (tr == NULL) {
|
||||
tr = td[i];
|
||||
}
|
||||
#else
|
||||
sa = td[2];
|
||||
tr = td[3];
|
||||
#endif
|
||||
#endif
|
||||
sd = td[0];
|
||||
trial = td[1];
|
||||
|
||||
sp_init_size(sd, d->used + 1);
|
||||
sp_init_size(trial, a->used + 1);
|
||||
#if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \
|
||||
!defined(WOLFSSL_SP_NO_MALLOC)
|
||||
#if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \
|
||||
!defined(WOLFSSL_SP_NO_MALLOC)
|
||||
if (sa != rem) {
|
||||
sp_init_size(sa, a->used + 1);
|
||||
}
|
||||
if (tr != r) {
|
||||
sp_init_size(tr, a->used - d->used + 2);
|
||||
}
|
||||
#else
|
||||
#else
|
||||
sp_init_size(sa, a->used + 1);
|
||||
sp_init_size(tr, a->used - d->used + 2);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Move divisor to top of word. Adjust dividend as well. */
|
||||
s = sp_count_bits(d);
|
||||
s = SP_WORD_SIZE - (s & SP_WORD_MASK);
|
||||
sp_copy(a, sa);
|
||||
@ -7180,165 +7338,37 @@ int sp_div(sp_int* a, sp_int* d, sp_int* r, sp_int* rem)
|
||||
}
|
||||
}
|
||||
if ((!done) && (err == MP_OKAY) && (d->used > 0)) {
|
||||
#ifdef WOLFSSL_SP_SMALL
|
||||
int c;
|
||||
#else
|
||||
int j;
|
||||
int o;
|
||||
#ifndef SQR_MUL_ASM
|
||||
sp_int_sword sw;
|
||||
#else
|
||||
sp_int_digit sl;
|
||||
sp_int_digit sh;
|
||||
sp_int_digit st;
|
||||
#endif
|
||||
#endif /* WOLFSSL_SP_SMALL */
|
||||
#ifdef WOLFSSL_SP_INT_NEGATIVE
|
||||
sa->sign = MP_ZPOS;
|
||||
sd->sign = MP_ZPOS;
|
||||
#endif /* WOLFSSL_SP_INT_NEGATIVE */
|
||||
|
||||
tr->used = sa->used - d->used + 1;
|
||||
sp_clear(tr);
|
||||
tr->used = sa->used - d->used + 1;
|
||||
dt = d->dp[d->used-1];
|
||||
|
||||
for (i = d->used - 1; i > 0; i--) {
|
||||
if (sa->dp[sa->used - d->used + i] != d->dp[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sa->dp[sa->used - d->used + i] >= d->dp[i]) {
|
||||
i = sa->used;
|
||||
_sp_sub_off(sa, d, sa, sa->used - d->used);
|
||||
/* Keep the same used so that 0 zeros will be put in. */
|
||||
sa->used = i;
|
||||
if (r != NULL) {
|
||||
tr->dp[sa->used - d->used] = 1;
|
||||
}
|
||||
}
|
||||
for (i = sa->used - 1; i >= d->used; i--) {
|
||||
if (sa->dp[i] == dt) {
|
||||
t = SP_DIGIT_MAX;
|
||||
}
|
||||
else {
|
||||
t = sp_div_word(sa->dp[i], sa->dp[i-1], dt);
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_SP_SMALL
|
||||
do {
|
||||
err = _sp_mul_d(d, t, trial, i - d->used);
|
||||
if (err != MP_OKAY) {
|
||||
break;
|
||||
}
|
||||
c = _sp_cmp_abs(trial, sa);
|
||||
if (c == MP_GT) {
|
||||
t--;
|
||||
}
|
||||
}
|
||||
while (c == MP_GT);
|
||||
|
||||
if (err != MP_OKAY) {
|
||||
break;
|
||||
}
|
||||
|
||||
_sp_sub_off(sa, trial, sa, 0);
|
||||
tr->dp[i - d->used] += t;
|
||||
if (tr->dp[i - d->used] < t) {
|
||||
tr->dp[i + 1 - d->used]++;
|
||||
}
|
||||
#else
|
||||
o = i - d->used;
|
||||
do {
|
||||
#ifndef SQR_MUL_ASM
|
||||
sp_int_word tw = 0;
|
||||
#else
|
||||
sp_int_digit tl = 0;
|
||||
sp_int_digit th = 0;
|
||||
#endif
|
||||
for (j = 0; j < d->used; j++) {
|
||||
#ifndef SQR_MUL_ASM
|
||||
tw += (sp_int_word)d->dp[j] * t;
|
||||
trial->dp[j] = (sp_int_digit)tw;
|
||||
tw >>= SP_WORD_SIZE;
|
||||
#else
|
||||
SP_ASM_MUL_ADD_NO(tl, th, d->dp[j], t);
|
||||
trial->dp[j] = tl;
|
||||
tl = th;
|
||||
th = 0;
|
||||
#endif
|
||||
}
|
||||
#ifndef SQR_MUL_ASM
|
||||
trial->dp[j] = (sp_int_digit)tw;
|
||||
#else
|
||||
trial->dp[j] = tl;
|
||||
#endif
|
||||
|
||||
for (j = d->used; j > 0; j--) {
|
||||
if (trial->dp[j] != sa->dp[j + o]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (trial->dp[j] > sa->dp[j + o]) {
|
||||
t--;
|
||||
}
|
||||
}
|
||||
while (trial->dp[j] > sa->dp[j + o]);
|
||||
|
||||
#ifndef SQR_MUL_ASM
|
||||
sw = 0;
|
||||
#else
|
||||
sl = 0;
|
||||
sh = 0;
|
||||
#endif
|
||||
for (j = 0; j <= d->used; j++) {
|
||||
#ifndef SQR_MUL_ASM
|
||||
sw += sa->dp[j + o];
|
||||
sw -= trial->dp[j];
|
||||
sa->dp[j + o] = (sp_int_digit)sw;
|
||||
sw >>= SP_WORD_SIZE;
|
||||
#else
|
||||
st = sa->dp[j + o];
|
||||
SP_ASM_ADDC(sl, sh, st);
|
||||
st = trial->dp[j];
|
||||
SP_ASM_SUBC(sl, sh, st);
|
||||
sa->dp[j + o] = sl;
|
||||
sl = sh;
|
||||
sh = (sp_int_digit)0 - (sl >> (SP_WORD_SIZE - 1));
|
||||
#endif
|
||||
}
|
||||
|
||||
tr->dp[o] = t;
|
||||
#endif /* WOLFSSL_SP_SMALL */
|
||||
}
|
||||
sa->used = i + 1;
|
||||
|
||||
/* Do division: tr = sa / d, sa = sa % d. */
|
||||
err = _sp_div(sa, d, tr, trial);
|
||||
/* Return the remainder if required. */
|
||||
if ((err == MP_OKAY) && (rem != NULL)) {
|
||||
#ifdef WOLFSSL_SP_INT_NEGATIVE
|
||||
#ifdef WOLFSSL_SP_INT_NEGATIVE
|
||||
sa->sign = (sa->used == 0) ? MP_ZPOS : aSign;
|
||||
#endif /* WOLFSSL_SP_INT_NEGATIVE */
|
||||
#endif /* WOLFSSL_SP_INT_NEGATIVE */
|
||||
/* Move result back down if moved up for divisor value. */
|
||||
if (s != SP_WORD_SIZE) {
|
||||
sp_rshb(sa, s, sa);
|
||||
}
|
||||
sp_copy(sa, rem);
|
||||
sp_clamp(rem);
|
||||
#ifdef WOLFSSL_SP_INT_NEGATIVE
|
||||
#ifdef WOLFSSL_SP_INT_NEGATIVE
|
||||
if (sp_iszero(rem)) {
|
||||
rem->sign = MP_ZPOS;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
/* Return the quotient if required. */
|
||||
if ((err == MP_OKAY) && (r != NULL)) {
|
||||
sp_copy(tr, r);
|
||||
sp_clamp(r);
|
||||
#ifdef WOLFSSL_SP_INT_NEGATIVE
|
||||
#ifdef WOLFSSL_SP_INT_NEGATIVE
|
||||
if (sp_iszero(r)) {
|
||||
r->sign = MP_ZPOS;
|
||||
}
|
||||
else {
|
||||
r->sign = (aSign == dSign) ? MP_ZPOS : MP_NEG;
|
||||
}
|
||||
#endif /* WOLFSSL_SP_INT_NEGATIVE */
|
||||
#endif /* WOLFSSL_SP_INT_NEGATIVE */
|
||||
}
|
||||
}
|
||||
|
||||
@ -11044,7 +11074,12 @@ static int _sp_exptmod_mont_ex(sp_int* b, sp_int* e, int bits, sp_int* m,
|
||||
if (c == 0) {
|
||||
c = SP_WORD_SIZE;
|
||||
}
|
||||
c -= bits % winBits;
|
||||
if ((bits % winBits) != 0) {
|
||||
c -= bits % winBits;
|
||||
}
|
||||
else {
|
||||
c -= winBits;
|
||||
}
|
||||
y = (int)(n >> c);
|
||||
n <<= SP_WORD_SIZE - c;
|
||||
/* Copy window number for top bits. */
|
||||
|
Reference in New Issue
Block a user