mirror of
http://github.com/valkey-io/valkey
synced 2024-11-23 03:33:28 +00:00
Update time independent string compare to use hash length (#9759)
* Update time independent string compare to use hash length
This commit is contained in:
parent
a18c91d642
commit
4ad166235e
41
src/acl.c
41
src/acl.c
@ -144,7 +144,7 @@ void ACLFreeLogEntry(void *le);
|
||||
int ACLSetSelector(aclSelector *selector, const char *op, size_t oplen);
|
||||
|
||||
/* The length of the string representation of a hashed password. */
|
||||
#define HASH_PASSWORD_LEN SHA256_BLOCK_SIZE*2
|
||||
#define HASH_PASSWORD_LEN (SHA256_BLOCK_SIZE*2)
|
||||
|
||||
/* =============================================================================
|
||||
* Helper functions for the rest of the ACL implementation
|
||||
@ -153,42 +153,13 @@ int ACLSetSelector(aclSelector *selector, const char *op, size_t oplen);
|
||||
/* Return zero if strings are the same, non-zero if they are not.
|
||||
* The comparison is performed in a way that prevents an attacker to obtain
|
||||
* information about the nature of the strings just monitoring the execution
|
||||
* time of the function.
|
||||
*
|
||||
* Note that limiting the comparison length to strings up to 512 bytes we
|
||||
* can avoid leaking any information about the password length and any
|
||||
* possible branch misprediction related leak.
|
||||
* time of the function. Note: The two strings must be the same length.
|
||||
*/
|
||||
int time_independent_strcmp(char *a, char *b) {
|
||||
char bufa[CONFIG_AUTHPASS_MAX_LEN], bufb[CONFIG_AUTHPASS_MAX_LEN];
|
||||
/* The above two strlen perform len(a) + len(b) operations where either
|
||||
* a or b are fixed (our password) length, and the difference is only
|
||||
* relative to the length of the user provided string, so no information
|
||||
* leak is possible in the following two lines of code. */
|
||||
unsigned int alen = strlen(a);
|
||||
unsigned int blen = strlen(b);
|
||||
unsigned int j;
|
||||
int time_independent_strcmp(char *a, char *b, int len) {
|
||||
int diff = 0;
|
||||
|
||||
/* We can't compare strings longer than our static buffers.
|
||||
* Note that this will never pass the first test in practical circumstances
|
||||
* so there is no info leak. */
|
||||
if (alen > sizeof(bufa) || blen > sizeof(bufb)) return 1;
|
||||
|
||||
memset(bufa,0,sizeof(bufa)); /* Constant time. */
|
||||
memset(bufb,0,sizeof(bufb)); /* Constant time. */
|
||||
/* Again the time of the following two copies is proportional to
|
||||
* len(a) + len(b) so no info is leaked. */
|
||||
memcpy(bufa,a,alen);
|
||||
memcpy(bufb,b,blen);
|
||||
|
||||
/* Always compare all the chars in the two buffers without
|
||||
* conditional expressions. */
|
||||
for (j = 0; j < sizeof(bufa); j++) {
|
||||
diff |= (bufa[j] ^ bufb[j]);
|
||||
for (int j = 0; j < len; j++) {
|
||||
diff |= (a[j] ^ b[j]);
|
||||
}
|
||||
/* Length must be equal as well. */
|
||||
diff |= alen ^ blen;
|
||||
return diff; /* If zero strings are the same. */
|
||||
}
|
||||
|
||||
@ -1414,7 +1385,7 @@ int ACLCheckUserCredentials(robj *username, robj *password) {
|
||||
sds hashed = ACLHashPassword(password->ptr,sdslen(password->ptr));
|
||||
while((ln = listNext(&li))) {
|
||||
sds thispass = listNodeValue(ln);
|
||||
if (!time_independent_strcmp(hashed, thispass)) {
|
||||
if (!time_independent_strcmp(hashed, thispass, HASH_PASSWORD_LEN)) {
|
||||
sdsfree(hashed);
|
||||
return C_OK;
|
||||
}
|
||||
|
@ -114,7 +114,6 @@ typedef long long ustime_t; /* microsecond time type. */
|
||||
#define LOG_MAX_LEN 1024 /* Default maximum length of syslog messages.*/
|
||||
#define AOF_REWRITE_ITEMS_PER_CMD 64
|
||||
#define AOF_ANNOTATION_LINE_MAX_LEN 1024
|
||||
#define CONFIG_AUTHPASS_MAX_LEN 512
|
||||
#define CONFIG_RUN_ID_SIZE 40
|
||||
#define RDB_EOF_MARK_SIZE 40
|
||||
#define CONFIG_REPL_BACKLOG_MIN_SIZE (1024*16) /* 16k */
|
||||
|
Loading…
Reference in New Issue
Block a user