Harden return value of uECC_vli_equal()

Previously it was returning 0 or 1, so flipping a single bit in the return
value reversed its meaning. Now it's returning the diff itself.

This is safe because in the two places it's used (signature verification and
point validation), invalid values will have a large number of bits differing
from the expected value, so diff will have a large Hamming weight.

An alternative would be to return for example -!(diff == 0), but the
comparison itself is prone to attacks (glitching the appropriate flag in the
CPU flags register, or the conditional branch if the comparison uses one). So
we'd need to protect the comparison, and it's simpler to just skip it and
return diff itself.
This commit is contained in:
Manuel Pégourié-Gonnard 2019-11-06 10:42:02 +01:00
parent 10d8e8ed64
commit 2b6312b7d9
2 changed files with 2 additions and 2 deletions

View file

@ -422,7 +422,7 @@ uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
* @param left IN -- left term in comparison * @param left IN -- left term in comparison
* @param right IN -- right term in comparison * @param right IN -- right term in comparison
* @param num_words IN -- number of words * @param num_words IN -- number of words
* @return Returns 0 if left == right, 1 otherwise. * @return Returns 0 if left == right, non-zero otherwise.
*/ */
uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right); uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right);

View file

@ -185,7 +185,7 @@ uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right)
for (i = NUM_ECC_WORDS - 1; i >= 0; --i) { for (i = NUM_ECC_WORDS - 1; i >= 0; --i) {
diff |= (left[i] ^ right[i]); diff |= (left[i] ^ right[i]);
} }
return !(diff == 0); return diff;
} }
uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond) uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond)