Skip to content

Commit fe810aa

Browse files
committed
Regenerate SP sources: clamp from_mp read index (review fix)
Regenerated with the updated generator so sp_<N>_from_mp() clamps the read index to a valid digit (0 when a->used == 0), avoiding an out-of-bounds or NULL digit read in the fixed-count constant-time loop while keeping the conversion constant time. Addresses the Copilot review comments on this PR (wolfSSL#10898) and on wolfSSL/scripts#626. Verified (--enable-sp, gcc 15.2): ec_p521_kex diff 0, ec_p521_sign diff 55; make check passes. Generated by wolfSSL/scripts#626
1 parent 84a9496 commit fe810aa

7 files changed

Lines changed: 594 additions & 162 deletions

File tree

wolfcrypt/src/sp_arm32.c

Lines changed: 77 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)