Skip to content

Commit 7867e60

Browse files
committed
Fix SP int truncation issue
1 parent d7bdfd3 commit 7867e60

1 file changed

Lines changed: 28 additions & 13 deletions

File tree

wolfcrypt/src/sp_int.c

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6124,14 +6124,17 @@ int sp_leading_bit(const sp_int* a)
61246124
int sp_set_bit(sp_int* a, int i)
61256125
{
61266126
int err = MP_OKAY;
6127-
/* Get index of word to set. */
6128-
sp_size_t w = (sp_size_t)(i >> SP_WORD_SHIFT);
6127+
/* Compute word index in full int width so that bit indices large enough
6128+
* to make the word index overflow sp_size_t are caught by the bounds
6129+
* check below rather than wrapping. */
6130+
int wi = (i < 0) ? 0 : (i >> SP_WORD_SHIFT);
61296131

61306132
/* Check for valid number and space for bit. */
6131-
if ((a == NULL) || (i < 0) || (w >= a->size)) {
6133+
if ((a == NULL) || (i < 0) || (wi >= (int)a->size)) {
61326134
err = MP_VAL;
61336135
}
61346136
if (err == MP_OKAY) {
6137+
sp_size_t w = (sp_size_t)wi;
61356138
/* Amount to shift up to set bit in word. */
61366139
unsigned int s = (unsigned int)(i & (SP_WORD_SIZE - 1));
61376140
unsigned int j;
@@ -8605,15 +8608,16 @@ void sp_rshd(sp_int* a, int c)
86058608
{
86068609
/* Do shift if we have an SP int. */
86078610
if ((a != NULL) && (c > 0)) {
8608-
/* Make zero if shift removes all digits. */
8609-
if ((sp_size_t)c >= a->used) {
8611+
/* Compare c in int width to avoid narrowing to sp_size_t (which can
8612+
* be word16) before the bounds check. */
8613+
if (c >= (int)a->used) {
86108614
_sp_zero(a);
86118615
}
86128616
else {
86138617
sp_size_t i;
86148618

86158619
/* Update used digits count. */
8616-
a->used = (sp_size_t)(a->used - c);
8620+
a->used = (sp_size_t)((int)a->used - c);
86178621
/* Move digits down. */
86188622
for (i = 0; i < a->used; i++, c++) {
86198623
a->dp[i] = a->dp[c];
@@ -8635,21 +8639,23 @@ void sp_rshd(sp_int* a, int c)
86358639
int sp_rshb(const sp_int* a, int n, sp_int* r)
86368640
{
86378641
int err = MP_OKAY;
8638-
/* Number of digits to shift down. */
8639-
sp_size_t i;
8642+
/* Compute the digit-shift count in full int width to avoid wrapping
8643+
* when n is large enough that the count would exceed sp_size_t range. */
8644+
int ni = (n < 0) ? 0 : (n >> SP_WORD_SHIFT);
86408645

86418646
if ((a == NULL) || (n < 0)) {
86428647
err = MP_VAL;
86438648
}
86448649
/* Handle case where shifting out all digits. */
8645-
else if ((i = (sp_size_t)(n >> SP_WORD_SHIFT)) >= a->used) {
8650+
else if (ni >= (int)a->used) {
86468651
_sp_zero(r);
86478652
}
86488653
/* Change callers when more error cases returned. */
8649-
else if ((err == MP_OKAY) && (a->used - i > r->size)) {
8654+
else if ((err == MP_OKAY) && ((int)a->used - ni > (int)r->size)) {
86508655
err = MP_VAL;
86518656
}
86528657
else if (err == MP_OKAY) {
8658+
sp_size_t i = (sp_size_t)ni;
86538659
sp_size_t j;
86548660

86558661
/* Number of bits to shift in digits. */
@@ -14848,16 +14854,25 @@ int sp_div_2d(const sp_int* a, int e, sp_int* r, sp_int* rem)
1484814854
int sp_mod_2d(const sp_int* a, int e, sp_int* r)
1484914855
{
1485014856
int err = MP_OKAY;
14851-
sp_size_t digits = (sp_size_t)((e + SP_WORD_SIZE - 1) >> SP_WORD_SHIFT);
14857+
/* Compute digit count in full int width. Decompose to avoid signed
14858+
* overflow if e is near INT_MAX: (e + SP_WORD_SIZE - 1) >> SHIFT is
14859+
* equivalent to (e >> SHIFT) + (e has remainder ? 1 : 0). */
14860+
int digits_full = 0;
14861+
sp_size_t digits = 0;
1485214862

1485314863
if ((a == NULL) || (r == NULL) || (e < 0)) {
1485414864
err = MP_VAL;
1485514865
}
14856-
if ((err == MP_OKAY) && (digits > r->size)) {
14857-
err = MP_VAL;
14866+
if (err == MP_OKAY) {
14867+
digits_full = (e >> SP_WORD_SHIFT) +
14868+
(((e & (SP_WORD_SIZE - 1)) != 0) ? 1 : 0);
14869+
if (digits_full > (int)r->size) {
14870+
err = MP_VAL;
14871+
}
1485814872
}
1485914873

1486014874
if (err == MP_OKAY) {
14875+
digits = (sp_size_t)digits_full;
1486114876
/* Copy a into r if not same pointer. */
1486214877
if (a != r) {
1486314878
sp_size_t cnt = (a->used < digits) ? a->used : digits;

0 commit comments

Comments
 (0)