Skip to content

Commit 8c85618

Browse files
committed
Fix SP int truncation issue
1 parent 121387a commit 8c85618

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
@@ -6140,14 +6140,17 @@ int sp_leading_bit(const sp_int* a)
61406140
int sp_set_bit(sp_int* a, int i)
61416141
{
61426142
int err = MP_OKAY;
6143-
/* Get index of word to set. */
6144-
sp_size_t w = (sp_size_t)(i >> SP_WORD_SHIFT);
6143+
/* Compute word index in full int width so that bit indices large enough
6144+
* to make the word index overflow sp_size_t are caught by the bounds
6145+
* check below rather than wrapping. */
6146+
int wi = (i < 0) ? 0 : (i >> SP_WORD_SHIFT);
61456147

61466148
/* Check for valid number and space for bit. */
6147-
if ((a == NULL) || (i < 0) || (w >= a->size)) {
6149+
if ((a == NULL) || (i < 0) || (wi >= (int)a->size)) {
61486150
err = MP_VAL;
61496151
}
61506152
if (err == MP_OKAY) {
6153+
sp_size_t w = (sp_size_t)wi;
61516154
/* Amount to shift up to set bit in word. */
61526155
unsigned int s = (unsigned int)(i & (SP_WORD_SIZE - 1));
61536156
unsigned int j;
@@ -8621,15 +8624,16 @@ void sp_rshd(sp_int* a, int c)
86218624
{
86228625
/* Do shift if we have an SP int. */
86238626
if ((a != NULL) && (c > 0)) {
8624-
/* Make zero if shift removes all digits. */
8625-
if ((sp_size_t)c >= a->used) {
8627+
/* Compare c in int width to avoid narrowing to sp_size_t (which can
8628+
* be word16) before the bounds check. */
8629+
if (c >= (int)a->used) {
86268630
_sp_zero(a);
86278631
}
86288632
else {
86298633
sp_size_t i;
86308634

86318635
/* Update used digits count. */
8632-
a->used = (sp_size_t)(a->used - c);
8636+
a->used = (sp_size_t)((int)a->used - c);
86338637
/* Move digits down. */
86348638
for (i = 0; i < a->used; i++, c++) {
86358639
a->dp[i] = a->dp[c];
@@ -8651,21 +8655,23 @@ void sp_rshd(sp_int* a, int c)
86518655
int sp_rshb(const sp_int* a, int n, sp_int* r)
86528656
{
86538657
int err = MP_OKAY;
8654-
/* Number of digits to shift down. */
8655-
sp_size_t i;
8658+
/* Compute the digit-shift count in full int width to avoid wrapping
8659+
* when n is large enough that the count would exceed sp_size_t range. */
8660+
int ni = (n < 0) ? 0 : (n >> SP_WORD_SHIFT);
86568661

86578662
if ((a == NULL) || (n < 0)) {
86588663
err = MP_VAL;
86598664
}
86608665
/* Handle case where shifting out all digits. */
8661-
else if ((i = (sp_size_t)(n >> SP_WORD_SHIFT)) >= a->used) {
8666+
else if (ni >= (int)a->used) {
86628667
_sp_zero(r);
86638668
}
86648669
/* Change callers when more error cases returned. */
8665-
else if ((err == MP_OKAY) && (a->used - i > r->size)) {
8670+
else if ((err == MP_OKAY) && ((int)a->used - ni > (int)r->size)) {
86668671
err = MP_VAL;
86678672
}
86688673
else if (err == MP_OKAY) {
8674+
sp_size_t i = (sp_size_t)ni;
86698675
sp_size_t j;
86708676

86718677
/* Number of bits to shift in digits. */
@@ -14914,16 +14920,25 @@ int sp_div_2d(const sp_int* a, int e, sp_int* r, sp_int* rem)
1491414920
int sp_mod_2d(const sp_int* a, int e, sp_int* r)
1491514921
{
1491614922
int err = MP_OKAY;
14917-
sp_size_t digits = (sp_size_t)((e + SP_WORD_SIZE - 1) >> SP_WORD_SHIFT);
14923+
/* Compute digit count in full int width. Decompose to avoid signed
14924+
* overflow if e is near INT_MAX: (e + SP_WORD_SIZE - 1) >> SHIFT is
14925+
* equivalent to (e >> SHIFT) + (e has remainder ? 1 : 0). */
14926+
int digits_full = 0;
14927+
sp_size_t digits = 0;
1491814928

1491914929
if ((a == NULL) || (r == NULL) || (e < 0)) {
1492014930
err = MP_VAL;
1492114931
}
14922-
if ((err == MP_OKAY) && (digits > r->size)) {
14923-
err = MP_VAL;
14932+
if (err == MP_OKAY) {
14933+
digits_full = (e >> SP_WORD_SHIFT) +
14934+
(((e & (SP_WORD_SIZE - 1)) != 0) ? 1 : 0);
14935+
if (digits_full > (int)r->size) {
14936+
err = MP_VAL;
14937+
}
1492414938
}
1492514939

1492614940
if (err == MP_OKAY) {
14941+
digits = (sp_size_t)digits_full;
1492714942
/* Copy a into r if not same pointer. */
1492814943
if (a != r) {
1492914944
sp_size_t cnt = (a->used < digits) ? a->used : digits;

0 commit comments

Comments
 (0)