Re: com php-src: Add hash_equals() to perform string comparisons that are not vulnerable to timing attacks.: NEWS UPGRADING ext/hash/hash.c
ext/hash/php_hash.h ext/hash/tests/hash_equals.phpt

From: Date: Wed, 19 Mar 2014 01:40:49 +0000
Subject: Re: com php-src: Add hash_equals() to perform string comparisons that are not vulnerable to timing attacks.: NEWS UPGRADING ext/hash/hash.c
ext/hash/php_hash.h ext/hash/tests/hash_equals.phpt
References: 1  Groups: php.cvs php.internals 
Request: Send a blank email to php-cvs+get-76523@lists.php.net to get a copy of this message
Hi all, Anyone mind if I make a PHPAPI for this? -- Yasuo Ohgaki yohgaki@ohgaki.net On Mon, Mar 17, 2014 at 5:37 PM, Adam Harvey <aharvey@php.net> wrote: > Commit: 2148a88b3d6d8b25151e2da168c37f5e3bdfd22b > Author: Rouven Weßling <me@rouvenwessling.de> Sun, 10 Nov 2013 > 22:37:10 +0100 > Parents: 2499b6518c4b0112c79295145d5f09d3658c31f4 > Branches: PHP-5.6 master > > Link: > > http://git.php.net/?p=php-src.git;a=commitdiff;h=2148a88b3d6d8b25151e2da168c37f5e3bdfd22b > > Log: > Add hash_equals() to perform string comparisons that are not vulnerable to > timing attacks. > > Changed paths: > M NEWS > M UPGRADING > M ext/hash/hash.c > M ext/hash/php_hash.h > A ext/hash/tests/hash_equals.phpt > > > Diff: > diff --git a/NEWS b/NEWS > index c5fbb6c..a2f563b 100644 > --- a/NEWS > +++ b/NEWS > @@ -30,6 +30,8 @@ PHP > NEWS > - Hash: > . Fixed bug #66698 (Missing FNV1a32 and FNV1a64 hash functions). > (Michael M Slusarz). > + . Implemented timing attack safe string comparison function > + (RFC: https://wiki.php.net/rfc/timing_attack). (Rouven > Weßling) > > - Intl: > . Fixed bug #66873 (A reproductible crash in UConverter when given > invalid > diff --git a/UPGRADING b/UPGRADING > index 9cfc0a6..8b20f51 100755 > --- a/UPGRADING > +++ b/UPGRADING > @@ -71,6 +71,9 @@ PHP 5.6 UPGRADE NOTES > - Added use function and use const. > (https://wiki.php.net/rfc/use_function) > > +- Added a function for timing attack safe string comparison > + (https://wiki.php.net/rfc/timing_attack) > + > - Added gost-crypto (CryptoPro S-box) hash algorithm. > > - Stream wrappers verify peer certificates and host names by default in > @@ -182,6 +185,9 @@ PHP 5.6 UPGRADE NOTES > 5. New Functions > ======================================== > > +- Hash > + Added hash_equals($known_string, $user_string) > + > - GMP: > Added gmp_root($a, $nth) and gmp_rootrem($a, $nth) for calculating nth > roots. > > diff --git a/ext/hash/hash.c b/ext/hash/hash.c > index 41c7a70..f14437d 100644 > --- a/ext/hash/hash.c > +++ b/ext/hash/hash.c > @@ -728,6 +728,46 @@ PHP_FUNCTION(hash_pbkdf2) > } > /* }}} */ > > +/* {{{ proto bool hash_equals(string known_string, string user_string) > + Compares two strings using the same time whether they're equal or not.. > + A difference in length will leak */ > +PHP_FUNCTION(hash_equals) > +{ > + zval *known_zval, *user_zval; > + char *known_str, *user_str; > + int result = 0, j; > + > + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", > &known_zval, &user_zval) == FAILURE) { > + return; > + } > + > + /* We only allow comparing string to prevent unexpected results. */ > + if (Z_TYPE_P(known_zval) != IS_STRING) { > + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected > known_string to be a string, %s given", zend_zval_type_name(known_zval)); > + RETURN_FALSE; > + } > + > + if (Z_TYPE_P(user_zval) != IS_STRING) { > + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected > user_string to be a string, %s given", zend_zval_type_name(user_zval)); > + RETURN_FALSE; > + } > + > + if (Z_STRLEN_P(known_zval) != Z_STRLEN_P(user_zval)) { > + RETURN_FALSE; > + } > + > + known_str = Z_STRVAL_P(known_zval); > + user_str = Z_STRVAL_P(user_zval); > + > + /* This is security sensitive code. Do not optimize this for > speed. */ > + for (j = 0; j < Z_STRLEN_P(known_zval); j++) { > + result |= known_str[j] ^ user_str[j]; > + } > + > + RETURN_BOOL(0 == result); > +} > +/* }}} */ > + > /* Module Housekeeping */ > > static void php_hash_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ > @@ -1152,6 +1192,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_pbkdf2, 0, 0, 4) > ZEND_ARG_INFO(0, raw_output) > ZEND_END_ARG_INFO() > > +ZEND_BEGIN_ARG_INFO(arginfo_hash_equals, 0) > + ZEND_ARG_INFO(0, known_string) > + ZEND_ARG_INFO(0, user_string) > +ZEND_END_ARG_INFO() > + > /* BC Land */ > #ifdef PHP_MHASH_BC > ZEND_BEGIN_ARG_INFO(arginfo_mhash_get_block_size, 0) > @@ -1199,6 +1244,7 @@ const zend_function_entry hash_functions[] = { > > PHP_FE(hash_algos, > arginfo_hash_algos) > PHP_FE(hash_pbkdf2, > arginfo_hash_pbkdf2) > + PHP_FE(hash_equals, > arginfo_hash_equals) > > /* BC Land */ > #ifdef PHP_HASH_MD5_NOT_IN_CORE > diff --git a/ext/hash/php_hash.h b/ext/hash/php_hash.h > index c5cb660..c75b930 100644 > --- a/ext/hash/php_hash.h > +++ b/ext/hash/php_hash.h > @@ -136,6 +136,7 @@ PHP_FUNCTION(hash_update_file); > PHP_FUNCTION(hash_final); > PHP_FUNCTION(hash_algos); > PHP_FUNCTION(hash_pbkdf2); > +PHP_FUNCTION(hash_equals); > > PHP_HASH_API const php_hash_ops *php_hash_fetch_ops(const char *algo, int > algo_len); > PHP_HASH_API void php_hash_register_algo(const char *algo, const > php_hash_ops *ops); > diff --git a/ext/hash/tests/hash_equals.phpt > b/ext/hash/tests/hash_equals.phpt > new file mode 100644 > index 0000000..8f87985 > --- /dev/null > +++ b/ext/hash/tests/hash_equals.phpt > @@ -0,0 +1,43 @@ > +--TEST-- > +hash_equals() function > +--FILE-- > +<?php > +var_dump(hash_equals("same", "same")); > +var_dump(hash_equals("not1same", "not2same")); > +var_dump(hash_equals("short", "longer")); > +var_dump(hash_equals("longer", "short")); > +var_dump(hash_equals("", "notempty")); > +var_dump(hash_equals("notempty", "")); > +var_dump(hash_equals("", "")); > +var_dump(hash_equals(123, "NaN")); > +var_dump(hash_equals("NaN", 123)); > +var_dump(hash_equals(123, 123)); > +var_dump(hash_equals(null, "")); > +var_dump(hash_equals(null, 123)); > +var_dump(hash_equals(null, null)); > +--EXPECTF-- > +bool(true) > +bool(false) > +bool(false) > +bool(false) > +bool(false) > +bool(false) > +bool(true) > + > +Warning: hash_equals(): Expected known_string to be a string, integer > given in %s on line %d > +bool(false) > + > +Warning: hash_equals(): Expected user_string to be a string, integer > given in %s on line %d > +bool(false) > + > +Warning: hash_equals(): Expected known_string to be a string, integer > given in %s on line %d > +bool(false) > + > +Warning: hash_equals(): Expected known_string to be a string, null given > in %s on line %d > +bool(false) > + > +Warning: hash_equals(): Expected known_string to be a string, null given > in %s on line %d > +bool(false) > + > +Warning: hash_equals(): Expected known_string to be a string, null given > in %s on line %d > +bool(false) > > > -- > PHP CVS Mailing List (http://www.php.net/) > To unsubscribe, visit: http://www.php.net/unsub.php > >

« previous php.cvs (#76523) next »