@@ -206,19 +206,27 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
206206#elif DIGIT_BIT > 32
207207 unsigned int i;
208208 int j = 0;
209+ int o;
210+ int last = (int)a->used - 1;
209211 word32 s = 0;
210212 sp_uint32 d;
211213 sp_uint32 mask;
212214
215+ /* Last valid digit index; 0 when a->used == 0 (as in the == branch). */
216+ last &= 0 - (a->used > 0);
213217 r[0] = 0;
214218 /* Loop a fixed number of times (bounded by the output size, not by
215- * a->used) and mask input digits at or after a->used to zero, so
216- * converting a secret value runs in constant time. */
219+ * a->used). Clamp the read index to a valid digit and mask digits at or
220+ * after a->used to zero, so a secret value is converted in constant time
221+ * without reading past the mp_int digit array. */
217222 for (i = 0; j < size; i++) {
218223 /* mask = all ones while i < a->used, else zero (branchless). */
219224 mask = (sp_uint32)0 - (((sp_uint32)i - (sp_uint32)(unsigned int)a->used) >>
220225 (sizeof(sp_uint32) * 8 - 1));
221- d = (sp_uint32)a->dp[i] & mask;
226+ /* o = i while i < a->used, else the last valid index (in bounds). */
227+ o = (int)(((unsigned int)i & (unsigned int)mask) |
228+ ((unsigned int)last & ~(unsigned int)mask));
229+ d = (sp_uint32)a->dp[o] & mask;
222230 r[j] |= (d << s);
223231 r[j] &= 0xffffffff;
224232 s = 32U - s;
@@ -18974,19 +18982,27 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
1897418982#elif DIGIT_BIT > 32
1897518983 unsigned int i;
1897618984 int j = 0;
18985+ int o;
18986+ int last = (int)a->used - 1;
1897718987 word32 s = 0;
1897818988 sp_uint32 d;
1897918989 sp_uint32 mask;
1898018990
18991+ /* Last valid digit index; 0 when a->used == 0 (as in the == branch). */
18992+ last &= 0 - (a->used > 0);
1898118993 r[0] = 0;
1898218994 /* Loop a fixed number of times (bounded by the output size, not by
18983- * a->used) and mask input digits at or after a->used to zero, so
18984- * converting a secret value runs in constant time. */
18995+ * a->used). Clamp the read index to a valid digit and mask digits at or
18996+ * after a->used to zero, so a secret value is converted in constant time
18997+ * without reading past the mp_int digit array. */
1898518998 for (i = 0; j < size; i++) {
1898618999 /* mask = all ones while i < a->used, else zero (branchless). */
1898719000 mask = (sp_uint32)0 - (((sp_uint32)i - (sp_uint32)(unsigned int)a->used) >>
1898819001 (sizeof(sp_uint32) * 8 - 1));
18989- d = (sp_uint32)a->dp[i] & mask;
19002+ /* o = i while i < a->used, else the last valid index (in bounds). */
19003+ o = (int)(((unsigned int)i & (unsigned int)mask) |
19004+ ((unsigned int)last & ~(unsigned int)mask));
19005+ d = (sp_uint32)a->dp[o] & mask;
1899019006 r[j] |= (d << s);
1899119007 r[j] &= 0xffffffff;
1899219008 s = 32U - s;
@@ -47009,19 +47025,27 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
4700947025#elif DIGIT_BIT > 32
4701047026 unsigned int i;
4701147027 int j = 0;
47028+ int o;
47029+ int last = (int)a->used - 1;
4701247030 word32 s = 0;
4701347031 sp_uint32 d;
4701447032 sp_uint32 mask;
4701547033
47034+ /* Last valid digit index; 0 when a->used == 0 (as in the == branch). */
47035+ last &= 0 - (a->used > 0);
4701647036 r[0] = 0;
4701747037 /* Loop a fixed number of times (bounded by the output size, not by
47018- * a->used) and mask input digits at or after a->used to zero, so
47019- * converting a secret value runs in constant time. */
47038+ * a->used). Clamp the read index to a valid digit and mask digits at or
47039+ * after a->used to zero, so a secret value is converted in constant time
47040+ * without reading past the mp_int digit array. */
4702047041 for (i = 0; j < size; i++) {
4702147042 /* mask = all ones while i < a->used, else zero (branchless). */
4702247043 mask = (sp_uint32)0 - (((sp_uint32)i - (sp_uint32)(unsigned int)a->used) >>
4702347044 (sizeof(sp_uint32) * 8 - 1));
47024- d = (sp_uint32)a->dp[i] & mask;
47045+ /* o = i while i < a->used, else the last valid index (in bounds). */
47046+ o = (int)(((unsigned int)i & (unsigned int)mask) |
47047+ ((unsigned int)last & ~(unsigned int)mask));
47048+ d = (sp_uint32)a->dp[o] & mask;
4702547049 r[j] |= (d << s);
4702647050 r[j] &= 0xffffffff;
4702747051 s = 32U - s;
@@ -67773,19 +67797,27 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
6777367797#elif DIGIT_BIT > 32
6777467798 unsigned int i;
6777567799 int j = 0;
67800+ int o;
67801+ int last = (int)a->used - 1;
6777667802 word32 s = 0;
6777767803 sp_uint32 d;
6777867804 sp_uint32 mask;
6777967805
67806+ /* Last valid digit index; 0 when a->used == 0 (as in the == branch). */
67807+ last &= 0 - (a->used > 0);
6778067808 r[0] = 0;
6778167809 /* Loop a fixed number of times (bounded by the output size, not by
67782- * a->used) and mask input digits at or after a->used to zero, so
67783- * converting a secret value runs in constant time. */
67810+ * a->used). Clamp the read index to a valid digit and mask digits at or
67811+ * after a->used to zero, so a secret value is converted in constant time
67812+ * without reading past the mp_int digit array. */
6778467813 for (i = 0; j < size; i++) {
6778567814 /* mask = all ones while i < a->used, else zero (branchless). */
6778667815 mask = (sp_uint32)0 - (((sp_uint32)i - (sp_uint32)(unsigned int)a->used) >>
6778767816 (sizeof(sp_uint32) * 8 - 1));
67788- d = (sp_uint32)a->dp[i] & mask;
67817+ /* o = i while i < a->used, else the last valid index (in bounds). */
67818+ o = (int)(((unsigned int)i & (unsigned int)mask) |
67819+ ((unsigned int)last & ~(unsigned int)mask));
67820+ d = (sp_uint32)a->dp[o] & mask;
6778967821 r[j] |= (d << s);
6779067822 r[j] &= 0xffffffff;
6779167823 s = 32U - s;
@@ -90910,19 +90942,27 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a)
9091090942#elif DIGIT_BIT > 32
9091190943 unsigned int i;
9091290944 int j = 0;
90945+ int o;
90946+ int last = (int)a->used - 1;
9091390947 word32 s = 0;
9091490948 sp_uint32 d;
9091590949 sp_uint32 mask;
9091690950
90951+ /* Last valid digit index; 0 when a->used == 0 (as in the == branch). */
90952+ last &= 0 - (a->used > 0);
9091790953 r[0] = 0;
9091890954 /* Loop a fixed number of times (bounded by the output size, not by
90919- * a->used) and mask input digits at or after a->used to zero, so
90920- * converting a secret value runs in constant time. */
90955+ * a->used). Clamp the read index to a valid digit and mask digits at or
90956+ * after a->used to zero, so a secret value is converted in constant time
90957+ * without reading past the mp_int digit array. */
9092190958 for (i = 0; j < size; i++) {
9092290959 /* mask = all ones while i < a->used, else zero (branchless). */
9092390960 mask = (sp_uint32)0 - (((sp_uint32)i - (sp_uint32)(unsigned int)a->used) >>
9092490961 (sizeof(sp_uint32) * 8 - 1));
90925- d = (sp_uint32)a->dp[i] & mask;
90962+ /* o = i while i < a->used, else the last valid index (in bounds). */
90963+ o = (int)(((unsigned int)i & (unsigned int)mask) |
90964+ ((unsigned int)last & ~(unsigned int)mask));
90965+ d = (sp_uint32)a->dp[o] & mask;
9092690966 r[j] |= (d << s);
9092790967 r[j] &= 0xffffffff;
9092890968 s = 32U - s;
@@ -117770,19 +117810,27 @@ static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a)
117770117810#elif DIGIT_BIT > 32
117771117811 unsigned int i;
117772117812 int j = 0;
117813+ int o;
117814+ int last = (int)a->used - 1;
117773117815 word32 s = 0;
117774117816 sp_uint32 d;
117775117817 sp_uint32 mask;
117776117818
117819+ /* Last valid digit index; 0 when a->used == 0 (as in the == branch). */
117820+ last &= 0 - (a->used > 0);
117777117821 r[0] = 0;
117778117822 /* Loop a fixed number of times (bounded by the output size, not by
117779- * a->used) and mask input digits at or after a->used to zero, so
117780- * converting a secret value runs in constant time. */
117823+ * a->used). Clamp the read index to a valid digit and mask digits at or
117824+ * after a->used to zero, so a secret value is converted in constant time
117825+ * without reading past the mp_int digit array. */
117781117826 for (i = 0; j < size; i++) {
117782117827 /* mask = all ones while i < a->used, else zero (branchless). */
117783117828 mask = (sp_uint32)0 - (((sp_uint32)i - (sp_uint32)(unsigned int)a->used) >>
117784117829 (sizeof(sp_uint32) * 8 - 1));
117785- d = (sp_uint32)a->dp[i] & mask;
117830+ /* o = i while i < a->used, else the last valid index (in bounds). */
117831+ o = (int)(((unsigned int)i & (unsigned int)mask) |
117832+ ((unsigned int)last & ~(unsigned int)mask));
117833+ d = (sp_uint32)a->dp[o] & mask;
117786117834 r[j] |= (d << s);
117787117835 r[j] &= 0xffffffff;
117788117836 s = 32U - s;
@@ -147580,19 +147628,27 @@ static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a)
147580147628#elif DIGIT_BIT > 32
147581147629 unsigned int i;
147582147630 int j = 0;
147631+ int o;
147632+ int last = (int)a->used - 1;
147583147633 word32 s = 0;
147584147634 sp_uint32 d;
147585147635 sp_uint32 mask;
147586147636
147637+ /* Last valid digit index; 0 when a->used == 0 (as in the == branch). */
147638+ last &= 0 - (a->used > 0);
147587147639 r[0] = 0;
147588147640 /* Loop a fixed number of times (bounded by the output size, not by
147589- * a->used) and mask input digits at or after a->used to zero, so
147590- * converting a secret value runs in constant time. */
147641+ * a->used). Clamp the read index to a valid digit and mask digits at or
147642+ * after a->used to zero, so a secret value is converted in constant time
147643+ * without reading past the mp_int digit array. */
147591147644 for (i = 0; j < size; i++) {
147592147645 /* mask = all ones while i < a->used, else zero (branchless). */
147593147646 mask = (sp_uint32)0 - (((sp_uint32)i - (sp_uint32)(unsigned int)a->used) >>
147594147647 (sizeof(sp_uint32) * 8 - 1));
147595- d = (sp_uint32)a->dp[i] & mask;
147648+ /* o = i while i < a->used, else the last valid index (in bounds). */
147649+ o = (int)(((unsigned int)i & (unsigned int)mask) |
147650+ ((unsigned int)last & ~(unsigned int)mask));
147651+ d = (sp_uint32)a->dp[o] & mask;
147596147652 r[j] |= (d << s);
147597147653 r[j] &= 0xffffffff;
147598147654 s = 32U - s;
0 commit comments