diff --git a/wolfcrypt/src/sp_arm32.c b/wolfcrypt/src/sp_arm32.c index b28a365439..bdf99e5993 100644 --- a/wolfcrypt/src/sp_arm32.c +++ b/wolfcrypt/src/sp_arm32.c @@ -206,18 +206,32 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -225,14 +239,18 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -18967,18 +18985,32 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -18986,14 +19018,18 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -46995,18 +47031,32 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -47014,14 +47064,18 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -67752,18 +67806,32 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -67771,14 +67839,18 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -90882,18 +90954,32 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -90901,14 +90987,18 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -117735,18 +117825,32 @@ static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -117754,14 +117858,18 @@ static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -147538,18 +147646,32 @@ static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -147557,14 +147679,18 @@ static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { diff --git a/wolfcrypt/src/sp_arm64.c b/wolfcrypt/src/sp_arm64.c index bdf1ec8338..ff49d1da3c 100644 --- a/wolfcrypt/src/sp_arm64.c +++ b/wolfcrypt/src/sp_arm64.c @@ -272,18 +272,32 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 64 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffffffffffffl; s = 64U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 64U) <= (word32)DIGIT_BIT) { s += 64U; r[j] &= 0xffffffffffffffffl; @@ -291,14 +305,18 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -7087,18 +7105,32 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 64 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffffffffffffl; s = 64U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 64U) <= (word32)DIGIT_BIT) { s += 64U; r[j] &= 0xffffffffffffffffl; @@ -7106,14 +7138,18 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -16613,18 +16649,32 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 64 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffffffffffffl; s = 64U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 64U) <= (word32)DIGIT_BIT) { s += 64U; r[j] &= 0xffffffffffffffffl; @@ -16632,14 +16682,18 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -22045,18 +22099,32 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 64 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffffffffffffl; s = 64U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 64U) <= (word32)DIGIT_BIT) { s += 64U; r[j] &= 0xffffffffffffffffl; @@ -22064,14 +22132,18 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -43107,18 +43179,32 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 64 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffffffffffffl; s = 64U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 64U) <= (word32)DIGIT_BIT) { s += 64U; r[j] &= 0xffffffffffffffffl; @@ -43126,14 +43212,18 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -70360,18 +70450,32 @@ static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 64 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffffffffffffl; s = 64U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 64U) <= (word32)DIGIT_BIT) { s += 64U; r[j] &= 0xffffffffffffffffl; @@ -70379,14 +70483,18 @@ static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -114934,18 +115042,32 @@ static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 64 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffffffffffffl; s = 64U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 64U) <= (word32)DIGIT_BIT) { s += 64U; r[j] &= 0xffffffffffffffffl; @@ -114953,14 +115075,18 @@ static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { diff --git a/wolfcrypt/src/sp_armthumb.c b/wolfcrypt/src/sp_armthumb.c index b7dd33133e..98609fbfd7 100644 --- a/wolfcrypt/src/sp_armthumb.c +++ b/wolfcrypt/src/sp_armthumb.c @@ -206,18 +206,32 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -225,14 +239,18 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -30390,18 +30408,32 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -30409,14 +30441,18 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -83477,18 +83513,32 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -83496,14 +83546,18 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -97700,18 +97754,32 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -97719,14 +97787,18 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -109184,18 +109256,32 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -109203,14 +109289,18 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -120233,18 +120323,32 @@ static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -120252,14 +120356,18 @@ static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -202175,18 +202283,32 @@ static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -202194,14 +202316,18 @@ static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { diff --git a/wolfcrypt/src/sp_c32.c b/wolfcrypt/src/sp_c32.c index 00b2225961..935380dfe4 100644 --- a/wolfcrypt/src/sp_c32.c +++ b/wolfcrypt/src/sp_c32.c @@ -301,18 +301,32 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 29 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0x1fffffff; s = 29U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 29U) <= (word32)DIGIT_BIT) { s += 29U; r[j] &= 0x1fffffff; @@ -320,14 +334,18 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -5362,18 +5380,32 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 29 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0x1fffffff; s = 29U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 29U) <= (word32)DIGIT_BIT) { s += 29U; r[j] &= 0x1fffffff; @@ -5381,14 +5413,18 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -8965,18 +9001,32 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 28 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xfffffff; s = 28U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 28U) <= (word32)DIGIT_BIT) { s += 28U; r[j] &= 0xfffffff; @@ -8984,14 +9034,18 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -13197,18 +13251,32 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 29 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0x1fffffff; s = 29U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 29U) <= (word32)DIGIT_BIT) { s += 29U; r[j] &= 0x1fffffff; @@ -13216,14 +13284,18 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -16707,18 +16779,32 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 26 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0x3ffffff; s = 26U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 26U) <= (word32)DIGIT_BIT) { s += 26U; r[j] &= 0x3ffffff; @@ -16726,14 +16812,18 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -21356,18 +21446,32 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 29 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0x1fffffff; s = 29U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 29U) <= (word32)DIGIT_BIT) { s += 29U; r[j] &= 0x1fffffff; @@ -21375,14 +21479,18 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -28548,18 +28656,32 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 26 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0x3ffffff; s = 26U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 26U) <= (word32)DIGIT_BIT) { s += 26U; r[j] &= 0x3ffffff; @@ -28567,14 +28689,18 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -36114,18 +36240,32 @@ static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 25 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0x1ffffff; s = 25U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 25U) <= (word32)DIGIT_BIT) { s += 25U; r[j] &= 0x1ffffff; @@ -36133,14 +36273,18 @@ static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -44891,18 +45035,32 @@ static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 25 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0x1ffffff; s = 25U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 25U) <= (word32)DIGIT_BIT) { s += 25U; r[j] &= 0x1ffffff; @@ -44910,14 +45068,18 @@ static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { diff --git a/wolfcrypt/src/sp_c64.c b/wolfcrypt/src/sp_c64.c index 539ade5eb5..eae0e6d60d 100644 --- a/wolfcrypt/src/sp_c64.c +++ b/wolfcrypt/src/sp_c64.c @@ -228,18 +228,32 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 61 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0x1fffffffffffffffL; s = 61U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 61U) <= (word32)DIGIT_BIT) { s += 61U; r[j] &= 0x1fffffffffffffffL; @@ -247,14 +261,18 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -3805,18 +3823,32 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 57 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0x1ffffffffffffffL; s = 57U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 57U) <= (word32)DIGIT_BIT) { s += 57U; r[j] &= 0x1ffffffffffffffL; @@ -3824,14 +3856,18 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -7367,18 +7403,32 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 60 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xfffffffffffffffL; s = 60U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 60U) <= (word32)DIGIT_BIT) { s += 60U; r[j] &= 0xfffffffffffffffL; @@ -7386,14 +7436,18 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -10875,18 +10929,32 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 57 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0x1ffffffffffffffL; s = 57U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 57U) <= (word32)DIGIT_BIT) { s += 57U; r[j] &= 0x1ffffffffffffffL; @@ -10894,14 +10962,18 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -14622,18 +14694,32 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 59 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0x7ffffffffffffffL; s = 59U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 59U) <= (word32)DIGIT_BIT) { s += 59U; r[j] &= 0x7ffffffffffffffL; @@ -14641,14 +14727,18 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -18028,18 +18118,32 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 53 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0x1fffffffffffffL; s = 53U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 53U) <= (word32)DIGIT_BIT) { s += 53U; r[j] &= 0x1fffffffffffffL; @@ -18047,14 +18151,18 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -22212,18 +22320,32 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 52 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xfffffffffffffL; s = 52U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 52U) <= (word32)DIGIT_BIT) { s += 52U; r[j] &= 0xfffffffffffffL; @@ -22231,14 +22353,18 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -28921,18 +29047,32 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 55 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0x7fffffffffffffL; s = 55U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 55U) <= (word32)DIGIT_BIT) { s += 55U; r[j] &= 0x7fffffffffffffL; @@ -28940,14 +29080,18 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -36326,18 +36470,32 @@ static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 58 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0x3ffffffffffffffL; s = 58U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 58U) <= (word32)DIGIT_BIT) { s += 58U; r[j] &= 0x3ffffffffffffffL; @@ -36345,14 +36503,18 @@ static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -44171,18 +44333,32 @@ static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 57 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0x1ffffffffffffffL; s = 57U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 57U) <= (word32)DIGIT_BIT) { s += 57U; r[j] &= 0x1ffffffffffffffL; @@ -44190,14 +44366,18 @@ static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { diff --git a/wolfcrypt/src/sp_cortexm.c b/wolfcrypt/src/sp_cortexm.c index 101c974bf1..1f70514abf 100644 --- a/wolfcrypt/src/sp_cortexm.c +++ b/wolfcrypt/src/sp_cortexm.c @@ -206,18 +206,32 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -225,14 +239,18 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -10387,18 +10405,32 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -10406,14 +10438,18 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -23534,18 +23570,32 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -23553,14 +23603,18 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -33792,18 +33846,32 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -33811,14 +33879,18 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -45426,18 +45498,32 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -45445,14 +45531,18 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -57366,18 +57456,32 @@ static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -57385,14 +57489,18 @@ static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -72227,18 +72335,32 @@ static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 32 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint32)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffff; s = 32U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 32U) <= (word32)DIGIT_BIT) { s += 32U; r[j] &= 0xffffffff; @@ -72246,14 +72368,18 @@ static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { diff --git a/wolfcrypt/src/sp_x86_64.c b/wolfcrypt/src/sp_x86_64.c index b3a3132bba..abbacd10ee 100644 --- a/wolfcrypt/src/sp_x86_64.c +++ b/wolfcrypt/src/sp_x86_64.c @@ -195,18 +195,32 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 64 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffffffffffffl; s = 64U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 64U) <= (word32)DIGIT_BIT) { s += 64U; r[j] &= 0xffffffffffffffffl; @@ -214,14 +228,18 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -3026,18 +3044,32 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 64 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffffffffffffl; s = 64U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 64U) <= (word32)DIGIT_BIT) { s += 64U; r[j] &= 0xffffffffffffffffl; @@ -3045,14 +3077,18 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -5792,18 +5828,32 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 64 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffffffffffffl; s = 64U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 64U) <= (word32)DIGIT_BIT) { s += 64U; r[j] &= 0xffffffffffffffffl; @@ -5811,14 +5861,18 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -7887,18 +7941,32 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 64 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffffffffffffl; s = 64U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 64U) <= (word32)DIGIT_BIT) { s += 64U; r[j] &= 0xffffffffffffffffl; @@ -7906,14 +7974,18 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -26799,18 +26871,32 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 64 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffffffffffffl; s = 64U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 64U) <= (word32)DIGIT_BIT) { s += 64U; r[j] &= 0xffffffffffffffffl; @@ -26818,14 +26904,18 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -51581,18 +51671,32 @@ static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 64 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffffffffffffl; s = 64U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 64U) <= (word32)DIGIT_BIT) { s += 64U; r[j] &= 0xffffffffffffffffl; @@ -51600,14 +51704,18 @@ static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) { @@ -92753,18 +92861,32 @@ static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) #elif DIGIT_BIT > 64 unsigned int i; int j = 0; + int o = 0; word32 s = 0; + /* Digit holder and mask are full mp_digit width (the type of a->dp[]) so + * the wide-digit split shifts below are not truncated when DIGIT_BIT is + * wider than the sp word (e.g. sp_c32.c over a 64-bit mp_digit). */ + mp_digit d; + /* mask = all ones while the read index is a valid digit (index < a->used), + * else zero. It is recomputed at the end of each iteration and reused: it + * zeros the digit at or after a->used, and negated (-mask is 0 or 1) it + * advances the read index only while another digit remains, so o never + * reads past the last valid digit. The first digit is always valid, so mask + * starts as all ones and no pre-loop calculation is needed. */ + mp_digit mask = (mp_digit)0 - 1; r[0] = 0; - for (i = 0; i < (unsigned int)a->used && j < size; i++) { - r[j] |= ((sp_uint64)a->dp[i] << s); + /* Loop a fixed number of times (bounded by the output size, not by + * a->used) so a secret value is converted in constant time. */ + for (i = 0; j < size; i++) { + d = a->dp[o] & mask; + r[j] |= (sp_digit)(d << s); r[j] &= 0xffffffffffffffffl; s = 64U - s; if (j + 1 >= size) { break; } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); while ((s + 64U) <= (word32)DIGIT_BIT) { s += 64U; r[j] &= 0xffffffffffffffffl; @@ -92772,14 +92894,18 @@ static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) break; } if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + r[++j] = (sp_digit)(d >> s); } else { r[++j] = (sp_digit)0; } } s = (word32)DIGIT_BIT - s; + /* Recompute mask for the next read index, then advance o by -mask + * (0 or 1) so it only moves while another digit remains. */ + mask = (mp_digit)0 - (((mp_digit)(i + 1U) - (mp_digit)(unsigned int)a->used) >> + (sizeof(mp_digit) * 8 - 1)); + o += (int)((mp_digit)0 - mask); } for (j++; j < size; j++) {