Skip to content

Commit 65dcb39

Browse files
committed
Introduction of timing attack safe bcmp implementation.
Nothing new but to refactor usage b/w hash and password extensions but using volatile pointers to be a bit safer, allowing to expand its usage eventually.
1 parent 9362d6f commit 65dcb39

File tree

5 files changed

+43
-8
lines changed

5 files changed

+43
-8
lines changed

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1610,7 +1610,7 @@ PHP_ADD_SOURCES(main, main.c snprintf.c spprintf.c \
16101610
fopen_wrappers.c alloca.c php_scandir.c \
16111611
php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
16121612
strlcat.c explicit_bzero.c reentrancy.c php_variables.c php_ticks.c \
1613-
network.c php_open_temporary_file.c \
1613+
network.c php_open_temporary_file.c safe_bcmp.c \
16141614
output.c getopt.c php_syslog.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
16151615

16161616
PHP_ADD_SOURCES_X(main, fastcgi.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1, PHP_FASTCGI_OBJS, no)

ext/hash/hash.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,7 +1109,6 @@ PHP_FUNCTION(hash_equals)
11091109
zval *known_zval, *user_zval;
11101110
char *known_str, *user_str;
11111111
int result = 0;
1112-
size_t j;
11131112

11141113
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &known_zval, &user_zval) == FAILURE) {
11151114
RETURN_THROWS();
@@ -1134,9 +1133,7 @@ PHP_FUNCTION(hash_equals)
11341133
user_str = Z_STRVAL_P(user_zval);
11351134

11361135
/* This is security sensitive code. Do not optimize this for speed. */
1137-
for (j = 0; j < Z_STRLEN_P(known_zval); j++) {
1138-
result |= known_str[j] ^ user_str[j];
1139-
}
1136+
result = php_safe_bcmp(known_str, user_str, Z_STRLEN_P(known_zval));
11401137

11411138
RETURN_BOOL(0 == result);
11421139
}

ext/standard/password.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,7 @@ static bool php_password_bcrypt_verify(const zend_string *password, const zend_s
169169
* resistance towards timing attacks. This is a constant time
170170
* equality check that will always check every byte of both
171171
* values. */
172-
for (i = 0; i < ZSTR_LEN(hash); i++) {
173-
status |= (ZSTR_VAL(ret)[i] ^ ZSTR_VAL(hash)[i]);
174-
}
172+
status = php_safe_bcmp(ZSTR_VAL(ret), ZSTR_VAL(hash), ZSTR_LEN(hash));
175173

176174
zend_string_free(ret);
177175
return status == 0;

main/php.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ END_EXTERN_C()
179179
#define explicit_bzero php_explicit_bzero
180180
#endif
181181

182+
BEGIN_EXTERN_C()
183+
PHPAPI int php_safe_bcmp(const void *a, const void *b, size_t siz);
184+
END_EXTERN_C()
185+
182186
#ifndef HAVE_STRTOK_R
183187
BEGIN_EXTERN_C()
184188
char *strtok_r(char *s, const char *delim, char **last);

main/safe_bcmp.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| PHP Version 8 |
4+
+----------------------------------------------------------------------+
5+
| Copyright (c) The PHP Group |
6+
+----------------------------------------------------------------------+
7+
| This source file is subject to version 3.01 of the PHP license, |
8+
| that is bundled with this package in the file LICENSE, and is |
9+
| available through the world-wide-web at the following url: |
10+
| http://www.php.net/license/3_01.txt |
11+
| If you did not receive a copy of the PHP license and are unable to |
12+
| obtain it through the world-wide-web, please send a note to |
13+
| [email protected] so we can mail you a copy immediately. |
14+
+----------------------------------------------------------------------+
15+
| Author: |
16+
+----------------------------------------------------------------------+
17+
*/
18+
19+
#include "php.h"
20+
21+
#include <string.h>
22+
23+
PHPAPI int php_safe_bcmp(const void *a, const void *b, size_t siz)
24+
{
25+
const volatile unsigned char *ua = (const volatile unsigned char *)a;
26+
const volatile unsigned char *ub = (const volatile unsigned char *)b;
27+
size_t i = 0;
28+
int r = 0;
29+
30+
while (i < siz) {
31+
r |= ua[i] ^ ub[i];
32+
++i;
33+
}
34+
35+
return r;
36+
}

0 commit comments

Comments
 (0)