From: Arran Cudbard-Bell Date: Thu, 4 Jun 2020 18:12:25 +0000 (-0500) Subject: Add mul + mod without overflow and fixup rlm_passwd hash function X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d920f520bd304a602db08ba610bafedc7fc5bb80;p=thirdparty%2Ffreeradius-server.git Add mul + mod without overflow and fixup rlm_passwd hash function --- diff --git a/src/lib/util/misc.c b/src/lib/util/misc.c index cb386b0cd49..75edb0d0c05 100644 --- a/src/lib/util/misc.c +++ b/src/lib/util/misc.c @@ -997,6 +997,8 @@ int fr_size_from_str(size_t *out, char const *str) } /** Multiply, checking for overflow + * + * Multiplication will only occur if it would not overflow. * * @param[out] result of multiplication. * @param[in] lhs First operand. @@ -1008,9 +1010,37 @@ int fr_size_from_str(size_t *out, char const *str) */ bool fr_multiply(uint64_t *result, uint64_t lhs, uint64_t rhs) { - *result = lhs * rhs; + if (rhs > 0 && (UINT64_MAX / rhs) < lhs) return true; + + *result = lhs * rhs; /* ubsan would flag this */ + + return false; +} + +/** Multiply with modulo wrap + * + * Avoids multiplication overflow. + * + * @param[in] lhs First operand. + * @param[in] rhs Second operand. + * @param[in] mod Modulo. + * @return + * - Result. + */ +uint64_t fr_multiply_mod(uint64_t lhs, uint64_t rhs, uint64_t mod) +{ + uint64_t res; + + lhs %= mod; + + while (rhs > 0) { + if (rhs & 0x01) res = (res + lhs) % mod; + + lhs = (lhs * 2) % mod; + rhs /= 2; + } - return rhs > 0 && (UINT64_MAX / rhs) < lhs; + return res % mod; } /** Compares two pointers diff --git a/src/lib/util/misc.h b/src/lib/util/misc.h index af1e64664ab..42eb10aeee6 100644 --- a/src/lib/util/misc.h +++ b/src/lib/util/misc.h @@ -207,6 +207,8 @@ size_t fr_snprint_uint128(char *out, size_t outlen, uint128_t const num); int fr_unix_time_from_str(fr_unix_time_t *date, char const *date_str); bool fr_multiply(uint64_t *result, uint64_t lhs, uint64_t rhs); +uint64_t fr_multiply_mod(uint64_t lhs, uint64_t rhs, uint64_t mod); + int fr_size_from_str(size_t *out, char const *str); int8_t fr_pointer_cmp(void const *a, void const *b); void fr_quick_sort(void const *to_sort[], int min_idx, int max_idx, fr_cmp_t cmp); diff --git a/src/modules/rlm_passwd/rlm_passwd.c b/src/modules/rlm_passwd/rlm_passwd.c index 91865cd5c57..808823e55f6 100644 --- a/src/modules/rlm_passwd/rlm_passwd.c +++ b/src/modules/rlm_passwd/rlm_passwd.c @@ -131,11 +131,11 @@ static void destroy_password (struct mypasswd * pass) static unsigned int hash(char const * username, unsigned int tablesize) { - int h=1; - while (*username) { - h = h * 7907 + *username++; - } - return h%tablesize; + uint64_t h = 1; + + while (*username) h = fr_multiply_mod(h, (7907 + *username++), tablesize); + + return (unsigned int)h; } static void release_hash_table(struct hashtable * ht){