diff --git a/src/utils/os.h b/src/utils/os.h index f019e26b1..f196209b7 100644 --- a/src/utils/os.h +++ b/src/utils/os.h @@ -584,6 +584,23 @@ static inline void os_remove_in_array(void *ptr, size_t nmemb, size_t size, */ size_t os_strlcpy(char *dest, const char *src, size_t siz); +/** + * os_memcmp_const - Constant time memory comparison + * @a: First buffer to compare + * @b: Second buffer to compare + * @len: Number of octets to compare + * Returns: 0 if buffers are equal, non-zero if not + * + * This function is meant for comparing passwords or hash values where + * difference in execution time could provide external observer information + * about the location of the difference in the memory buffers. The return value + * does not behave like os_memcmp(), i.e., os_memcmp_const() cannot be used to + * sort items into a defined order. Unlike os_memcmp(), execution time of + * os_memcmp_const() does not depend on the contents of the compared memory + * buffers, but only on the total compared length. + */ +int os_memcmp_const(const void *a, const void *b, size_t len); + #ifdef OS_REJECT_C_LIB_FUNCTIONS #define malloc OS_DO_NOT_USE_malloc diff --git a/src/utils/os_internal.c b/src/utils/os_internal.c index 2cb0d1262..90b6688ad 100644 --- a/src/utils/os_internal.c +++ b/src/utils/os_internal.c @@ -463,6 +463,20 @@ size_t os_strlcpy(char *dest, const char *src, size_t siz) } +int os_memcmp_const(const void *a, const void *b, size_t len) +{ + const u8 *aa = a; + const u8 *bb = b; + size_t i; + u8 res; + + for (res = 0, i = 0; i < len; i++) + res |= aa[i] ^ bb[i]; + + return res; +} + + char * os_strstr(const char *haystack, const char *needle) { size_t len = os_strlen(needle); diff --git a/src/utils/os_none.c b/src/utils/os_none.c index 228c4724c..26491115a 100644 --- a/src/utils/os_none.c +++ b/src/utils/os_none.c @@ -218,6 +218,11 @@ size_t os_strlcpy(char *dest, const char *src, size_t size) } +int os_memcmp_const(const void *a, const void *b, size_t len) +{ + return 0; +} + char * os_strstr(const char *haystack, const char *needle) { return NULL; diff --git a/src/utils/os_unix.c b/src/utils/os_unix.c index 008ec6b08..d3860aec1 100644 --- a/src/utils/os_unix.c +++ b/src/utils/os_unix.c @@ -450,6 +450,20 @@ size_t os_strlcpy(char *dest, const char *src, size_t siz) } +int os_memcmp_const(const void *a, const void *b, size_t len) +{ + const u8 *aa = a; + const u8 *bb = b; + size_t i; + u8 res; + + for (res = 0, i = 0; i < len; i++) + res |= aa[i] ^ bb[i]; + + return res; +} + + #ifdef WPA_TRACE void * os_malloc(size_t size) diff --git a/src/utils/os_win32.c b/src/utils/os_win32.c index 1cfa7a5f8..55937dec6 100644 --- a/src/utils/os_win32.c +++ b/src/utils/os_win32.c @@ -244,3 +244,17 @@ size_t os_strlcpy(char *dest, const char *src, size_t siz) return s - src - 1; } + + +int os_memcmp_const(const void *a, const void *b, size_t len) +{ + const u8 *aa = a; + const u8 *bb = b; + size_t i; + u8 res; + + for (res = 0, i = 0; i < len; i++) + res |= aa[i] ^ bb[i]; + + return res; +}