@@ -206,27 +206,45 @@ 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;
210-
212+ /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so
213+ * the wide-digit split shifts below are not truncated when DIGIT_BIT is
214+ * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */
215+ mp_digit d;
216+ mp_digit mask;
217+
218+ /* Last valid digit index; 0 when a->used == 0 (as in the == branch). */
219+ last &= 0 - (a->used > 0);
211220 r[0] = 0;
212- for (i = 0; i < (unsigned int)a->used && j < size; i++) {
213- r[j] |= ((sp_uint32)a->dp[i] << s);
221+ /* Loop a fixed number of times (bounded by the output size, not by
222+ * a->used). Clamp the read index to a valid digit and mask digits at or
223+ * after a->used to zero, so a secret value is converted in constant time
224+ * without reading past the mp_int digit array. */
225+ for (i = 0; j < size; i++) {
226+ /* mask = all ones while i < a->used, else zero (branchless). */
227+ mask = (mp_digit)0 - (((mp_digit)i - (mp_digit)(unsigned int)a->used) >>
228+ (sizeof(mp_digit) * 8 - 1));
229+ /* o = i while i < a->used, else the last valid index (in bounds). */
230+ o = (int)(((unsigned int)i & (unsigned int)mask) |
231+ ((unsigned int)last & ~(unsigned int)mask));
232+ d = a->dp[o] & mask;
233+ r[j] |= (sp_digit)(d << s);
214234 r[j] &= 0xffffffff;
215235 s = 32U - s;
216236 if (j + 1 >= size) {
217237 break;
218238 }
219- /* lint allow cast of mismatch word32 and mp_digit */
220- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
239+ r[++j] = (sp_digit)(d >> s);
221240 while ((s + 32U) <= (word32)DIGIT_BIT) {
222241 s += 32U;
223242 r[j] &= 0xffffffff;
224243 if (j + 1 >= size) {
225244 break;
226245 }
227246 if (s < (word32)DIGIT_BIT) {
228- /* lint allow cast of mismatch word32 and mp_digit */
229- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
247+ r[++j] = (sp_digit)(d >> s);
230248 }
231249 else {
232250 r[++j] = (sp_digit)0;
@@ -18967,27 +18985,45 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
1896718985#elif DIGIT_BIT > 32
1896818986 unsigned int i;
1896918987 int j = 0;
18988+ int o;
18989+ int last = (int)a->used - 1;
1897018990 word32 s = 0;
18971-
18991+ /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so
18992+ * the wide-digit split shifts below are not truncated when DIGIT_BIT is
18993+ * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */
18994+ mp_digit d;
18995+ mp_digit mask;
18996+
18997+ /* Last valid digit index; 0 when a->used == 0 (as in the == branch). */
18998+ last &= 0 - (a->used > 0);
1897218999 r[0] = 0;
18973- for (i = 0; i < (unsigned int)a->used && j < size; i++) {
18974- r[j] |= ((sp_uint32)a->dp[i] << s);
19000+ /* Loop a fixed number of times (bounded by the output size, not by
19001+ * a->used). Clamp the read index to a valid digit and mask digits at or
19002+ * after a->used to zero, so a secret value is converted in constant time
19003+ * without reading past the mp_int digit array. */
19004+ for (i = 0; j < size; i++) {
19005+ /* mask = all ones while i < a->used, else zero (branchless). */
19006+ mask = (mp_digit)0 - (((mp_digit)i - (mp_digit)(unsigned int)a->used) >>
19007+ (sizeof(mp_digit) * 8 - 1));
19008+ /* o = i while i < a->used, else the last valid index (in bounds). */
19009+ o = (int)(((unsigned int)i & (unsigned int)mask) |
19010+ ((unsigned int)last & ~(unsigned int)mask));
19011+ d = a->dp[o] & mask;
19012+ r[j] |= (sp_digit)(d << s);
1897519013 r[j] &= 0xffffffff;
1897619014 s = 32U - s;
1897719015 if (j + 1 >= size) {
1897819016 break;
1897919017 }
18980- /* lint allow cast of mismatch word32 and mp_digit */
18981- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
19018+ r[++j] = (sp_digit)(d >> s);
1898219019 while ((s + 32U) <= (word32)DIGIT_BIT) {
1898319020 s += 32U;
1898419021 r[j] &= 0xffffffff;
1898519022 if (j + 1 >= size) {
1898619023 break;
1898719024 }
1898819025 if (s < (word32)DIGIT_BIT) {
18989- /* lint allow cast of mismatch word32 and mp_digit */
18990- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
19026+ r[++j] = (sp_digit)(d >> s);
1899119027 }
1899219028 else {
1899319029 r[++j] = (sp_digit)0;
@@ -46995,27 +47031,45 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
4699547031#elif DIGIT_BIT > 32
4699647032 unsigned int i;
4699747033 int j = 0;
47034+ int o;
47035+ int last = (int)a->used - 1;
4699847036 word32 s = 0;
46999-
47037+ /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so
47038+ * the wide-digit split shifts below are not truncated when DIGIT_BIT is
47039+ * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */
47040+ mp_digit d;
47041+ mp_digit mask;
47042+
47043+ /* Last valid digit index; 0 when a->used == 0 (as in the == branch). */
47044+ last &= 0 - (a->used > 0);
4700047045 r[0] = 0;
47001- for (i = 0; i < (unsigned int)a->used && j < size; i++) {
47002- r[j] |= ((sp_uint32)a->dp[i] << s);
47046+ /* Loop a fixed number of times (bounded by the output size, not by
47047+ * a->used). Clamp the read index to a valid digit and mask digits at or
47048+ * after a->used to zero, so a secret value is converted in constant time
47049+ * without reading past the mp_int digit array. */
47050+ for (i = 0; j < size; i++) {
47051+ /* mask = all ones while i < a->used, else zero (branchless). */
47052+ mask = (mp_digit)0 - (((mp_digit)i - (mp_digit)(unsigned int)a->used) >>
47053+ (sizeof(mp_digit) * 8 - 1));
47054+ /* o = i while i < a->used, else the last valid index (in bounds). */
47055+ o = (int)(((unsigned int)i & (unsigned int)mask) |
47056+ ((unsigned int)last & ~(unsigned int)mask));
47057+ d = a->dp[o] & mask;
47058+ r[j] |= (sp_digit)(d << s);
4700347059 r[j] &= 0xffffffff;
4700447060 s = 32U - s;
4700547061 if (j + 1 >= size) {
4700647062 break;
4700747063 }
47008- /* lint allow cast of mismatch word32 and mp_digit */
47009- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
47064+ r[++j] = (sp_digit)(d >> s);
4701047065 while ((s + 32U) <= (word32)DIGIT_BIT) {
4701147066 s += 32U;
4701247067 r[j] &= 0xffffffff;
4701347068 if (j + 1 >= size) {
4701447069 break;
4701547070 }
4701647071 if (s < (word32)DIGIT_BIT) {
47017- /* lint allow cast of mismatch word32 and mp_digit */
47018- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
47072+ r[++j] = (sp_digit)(d >> s);
4701947073 }
4702047074 else {
4702147075 r[++j] = (sp_digit)0;
@@ -67752,27 +67806,45 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
6775267806#elif DIGIT_BIT > 32
6775367807 unsigned int i;
6775467808 int j = 0;
67809+ int o;
67810+ int last = (int)a->used - 1;
6775567811 word32 s = 0;
67756-
67812+ /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so
67813+ * the wide-digit split shifts below are not truncated when DIGIT_BIT is
67814+ * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */
67815+ mp_digit d;
67816+ mp_digit mask;
67817+
67818+ /* Last valid digit index; 0 when a->used == 0 (as in the == branch). */
67819+ last &= 0 - (a->used > 0);
6775767820 r[0] = 0;
67758- for (i = 0; i < (unsigned int)a->used && j < size; i++) {
67759- r[j] |= ((sp_uint32)a->dp[i] << s);
67821+ /* Loop a fixed number of times (bounded by the output size, not by
67822+ * a->used). Clamp the read index to a valid digit and mask digits at or
67823+ * after a->used to zero, so a secret value is converted in constant time
67824+ * without reading past the mp_int digit array. */
67825+ for (i = 0; j < size; i++) {
67826+ /* mask = all ones while i < a->used, else zero (branchless). */
67827+ mask = (mp_digit)0 - (((mp_digit)i - (mp_digit)(unsigned int)a->used) >>
67828+ (sizeof(mp_digit) * 8 - 1));
67829+ /* o = i while i < a->used, else the last valid index (in bounds). */
67830+ o = (int)(((unsigned int)i & (unsigned int)mask) |
67831+ ((unsigned int)last & ~(unsigned int)mask));
67832+ d = a->dp[o] & mask;
67833+ r[j] |= (sp_digit)(d << s);
6776067834 r[j] &= 0xffffffff;
6776167835 s = 32U - s;
6776267836 if (j + 1 >= size) {
6776367837 break;
6776467838 }
67765- /* lint allow cast of mismatch word32 and mp_digit */
67766- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
67839+ r[++j] = (sp_digit)(d >> s);
6776767840 while ((s + 32U) <= (word32)DIGIT_BIT) {
6776867841 s += 32U;
6776967842 r[j] &= 0xffffffff;
6777067843 if (j + 1 >= size) {
6777167844 break;
6777267845 }
6777367846 if (s < (word32)DIGIT_BIT) {
67774- /* lint allow cast of mismatch word32 and mp_digit */
67775- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
67847+ r[++j] = (sp_digit)(d >> s);
6777667848 }
6777767849 else {
6777867850 r[++j] = (sp_digit)0;
@@ -90882,27 +90954,45 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a)
9088290954#elif DIGIT_BIT > 32
9088390955 unsigned int i;
9088490956 int j = 0;
90957+ int o;
90958+ int last = (int)a->used - 1;
9088590959 word32 s = 0;
90886-
90960+ /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so
90961+ * the wide-digit split shifts below are not truncated when DIGIT_BIT is
90962+ * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */
90963+ mp_digit d;
90964+ mp_digit mask;
90965+
90966+ /* Last valid digit index; 0 when a->used == 0 (as in the == branch). */
90967+ last &= 0 - (a->used > 0);
9088790968 r[0] = 0;
90888- for (i = 0; i < (unsigned int)a->used && j < size; i++) {
90889- r[j] |= ((sp_uint32)a->dp[i] << s);
90969+ /* Loop a fixed number of times (bounded by the output size, not by
90970+ * a->used). Clamp the read index to a valid digit and mask digits at or
90971+ * after a->used to zero, so a secret value is converted in constant time
90972+ * without reading past the mp_int digit array. */
90973+ for (i = 0; j < size; i++) {
90974+ /* mask = all ones while i < a->used, else zero (branchless). */
90975+ mask = (mp_digit)0 - (((mp_digit)i - (mp_digit)(unsigned int)a->used) >>
90976+ (sizeof(mp_digit) * 8 - 1));
90977+ /* o = i while i < a->used, else the last valid index (in bounds). */
90978+ o = (int)(((unsigned int)i & (unsigned int)mask) |
90979+ ((unsigned int)last & ~(unsigned int)mask));
90980+ d = a->dp[o] & mask;
90981+ r[j] |= (sp_digit)(d << s);
9089090982 r[j] &= 0xffffffff;
9089190983 s = 32U - s;
9089290984 if (j + 1 >= size) {
9089390985 break;
9089490986 }
90895- /* lint allow cast of mismatch word32 and mp_digit */
90896- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
90987+ r[++j] = (sp_digit)(d >> s);
9089790988 while ((s + 32U) <= (word32)DIGIT_BIT) {
9089890989 s += 32U;
9089990990 r[j] &= 0xffffffff;
9090090991 if (j + 1 >= size) {
9090190992 break;
9090290993 }
9090390994 if (s < (word32)DIGIT_BIT) {
90904- /* lint allow cast of mismatch word32 and mp_digit */
90905- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
90995+ r[++j] = (sp_digit)(d >> s);
9090690996 }
9090790997 else {
9090890998 r[++j] = (sp_digit)0;
@@ -117735,27 +117825,45 @@ static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a)
117735117825#elif DIGIT_BIT > 32
117736117826 unsigned int i;
117737117827 int j = 0;
117828+ int o;
117829+ int last = (int)a->used - 1;
117738117830 word32 s = 0;
117739-
117831+ /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so
117832+ * the wide-digit split shifts below are not truncated when DIGIT_BIT is
117833+ * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */
117834+ mp_digit d;
117835+ mp_digit mask;
117836+
117837+ /* Last valid digit index; 0 when a->used == 0 (as in the == branch). */
117838+ last &= 0 - (a->used > 0);
117740117839 r[0] = 0;
117741- for (i = 0; i < (unsigned int)a->used && j < size; i++) {
117742- r[j] |= ((sp_uint32)a->dp[i] << s);
117840+ /* Loop a fixed number of times (bounded by the output size, not by
117841+ * a->used). Clamp the read index to a valid digit and mask digits at or
117842+ * after a->used to zero, so a secret value is converted in constant time
117843+ * without reading past the mp_int digit array. */
117844+ for (i = 0; j < size; i++) {
117845+ /* mask = all ones while i < a->used, else zero (branchless). */
117846+ mask = (mp_digit)0 - (((mp_digit)i - (mp_digit)(unsigned int)a->used) >>
117847+ (sizeof(mp_digit) * 8 - 1));
117848+ /* o = i while i < a->used, else the last valid index (in bounds). */
117849+ o = (int)(((unsigned int)i & (unsigned int)mask) |
117850+ ((unsigned int)last & ~(unsigned int)mask));
117851+ d = a->dp[o] & mask;
117852+ r[j] |= (sp_digit)(d << s);
117743117853 r[j] &= 0xffffffff;
117744117854 s = 32U - s;
117745117855 if (j + 1 >= size) {
117746117856 break;
117747117857 }
117748- /* lint allow cast of mismatch word32 and mp_digit */
117749- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
117858+ r[++j] = (sp_digit)(d >> s);
117750117859 while ((s + 32U) <= (word32)DIGIT_BIT) {
117751117860 s += 32U;
117752117861 r[j] &= 0xffffffff;
117753117862 if (j + 1 >= size) {
117754117863 break;
117755117864 }
117756117865 if (s < (word32)DIGIT_BIT) {
117757- /* lint allow cast of mismatch word32 and mp_digit */
117758- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
117866+ r[++j] = (sp_digit)(d >> s);
117759117867 }
117760117868 else {
117761117869 r[++j] = (sp_digit)0;
@@ -147538,27 +147646,45 @@ static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a)
147538147646#elif DIGIT_BIT > 32
147539147647 unsigned int i;
147540147648 int j = 0;
147649+ int o;
147650+ int last = (int)a->used - 1;
147541147651 word32 s = 0;
147542-
147652+ /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so
147653+ * the wide-digit split shifts below are not truncated when DIGIT_BIT is
147654+ * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */
147655+ mp_digit d;
147656+ mp_digit mask;
147657+
147658+ /* Last valid digit index; 0 when a->used == 0 (as in the == branch). */
147659+ last &= 0 - (a->used > 0);
147543147660 r[0] = 0;
147544- for (i = 0; i < (unsigned int)a->used && j < size; i++) {
147545- r[j] |= ((sp_uint32)a->dp[i] << s);
147661+ /* Loop a fixed number of times (bounded by the output size, not by
147662+ * a->used). Clamp the read index to a valid digit and mask digits at or
147663+ * after a->used to zero, so a secret value is converted in constant time
147664+ * without reading past the mp_int digit array. */
147665+ for (i = 0; j < size; i++) {
147666+ /* mask = all ones while i < a->used, else zero (branchless). */
147667+ mask = (mp_digit)0 - (((mp_digit)i - (mp_digit)(unsigned int)a->used) >>
147668+ (sizeof(mp_digit) * 8 - 1));
147669+ /* o = i while i < a->used, else the last valid index (in bounds). */
147670+ o = (int)(((unsigned int)i & (unsigned int)mask) |
147671+ ((unsigned int)last & ~(unsigned int)mask));
147672+ d = a->dp[o] & mask;
147673+ r[j] |= (sp_digit)(d << s);
147546147674 r[j] &= 0xffffffff;
147547147675 s = 32U - s;
147548147676 if (j + 1 >= size) {
147549147677 break;
147550147678 }
147551- /* lint allow cast of mismatch word32 and mp_digit */
147552- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
147679+ r[++j] = (sp_digit)(d >> s);
147553147680 while ((s + 32U) <= (word32)DIGIT_BIT) {
147554147681 s += 32U;
147555147682 r[j] &= 0xffffffff;
147556147683 if (j + 1 >= size) {
147557147684 break;
147558147685 }
147559147686 if (s < (word32)DIGIT_BIT) {
147560- /* lint allow cast of mismatch word32 and mp_digit */
147561- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
147687+ r[++j] = (sp_digit)(d >> s);
147562147688 }
147563147689 else {
147564147690 r[++j] = (sp_digit)0;
0 commit comments