@@ -485,6 +485,12 @@ static inline void php_hash_hmac_round(unsigned char *final, const php_hash_ops
485
485
ops -> hash_final (final , context );
486
486
}
487
487
488
+ static inline void php_hash_hmac_continue (unsigned char * final , const php_hash_ops * ops , void * start_context , void * context , const unsigned char * data , const zend_long data_size ) {
489
+ ops -> hash_copy (ops , start_context , context );
490
+ ops -> hash_update (context , data , data_size );
491
+ ops -> hash_final (final , context );
492
+ }
493
+
488
494
static void php_hash_do_hash_hmac (
489
495
zval * return_value , zend_string * algo , char * data , size_t data_len , char * key , size_t key_len , zend_bool raw_output , bool isfilename
490
496
) /* {{{ */ {
@@ -974,12 +980,12 @@ PHP_FUNCTION(hash_pbkdf2)
974
980
{
975
981
zend_string * returnval , * algo ;
976
982
char * salt , * pass = NULL ;
977
- unsigned char * computed_salt , * digest , * temp , * result , * K1 , * K2 = NULL ;
983
+ unsigned char * computed_salt , * digest , * temp , * result , * K = NULL ;
978
984
zend_long loops , i , j , iterations , digest_length = 0 , length = 0 ;
979
985
size_t pass_len , salt_len = 0 ;
980
986
zend_bool raw_output = 0 ;
981
987
const php_hash_ops * ops ;
982
- void * context ;
988
+ void * context , * inner_context , * outer_context ;
983
989
984
990
if (zend_parse_parameters (ZEND_NUM_ARGS (), "Sssl|lb" , & algo , & pass , & pass_len , & salt , & salt_len , & iterations , & length , & raw_output ) == FAILURE ) {
985
991
RETURN_THROWS ();
@@ -1006,18 +1012,29 @@ PHP_FUNCTION(hash_pbkdf2)
1006
1012
RETURN_THROWS ();
1007
1013
}
1008
1014
1015
+ /* inner_context: hash of the key block ^ 0x36
1016
+ * outer_context: hash of the key block ^ 0x5c
1017
+ * context: misc scratch hashing context */
1018
+ inner_context = php_hash_alloc_context (ops );
1019
+ outer_context = php_hash_alloc_context (ops );
1009
1020
context = php_hash_alloc_context (ops );
1010
1021
ops -> hash_init (context );
1011
1022
1012
- K1 = emalloc (ops -> block_size );
1013
- K2 = emalloc (ops -> block_size );
1023
+ K = emalloc (ops -> block_size );
1014
1024
digest = emalloc (ops -> digest_size );
1015
1025
temp = emalloc (ops -> digest_size );
1016
1026
1017
1027
/* Setup Keys that will be used for all hmac rounds */
1018
- php_hash_hmac_prep_key (K1 , ops , context , (unsigned char * ) pass , pass_len );
1019
- /* Convert K1 to opad -- 0x6A = 0x36 ^ 0x5C */
1020
- php_hash_string_xor_char (K2 , K1 , 0x6A , ops -> block_size );
1028
+ php_hash_hmac_prep_key (K , ops , context , (unsigned char * ) pass , pass_len );
1029
+
1030
+ ops -> hash_init (inner_context );
1031
+ ops -> hash_update (inner_context , K , ops -> block_size );
1032
+
1033
+ /* Convert K from ipad to opad -- 0x6A = 0x36 ^ 0x5C */
1034
+ php_hash_string_xor_char (K , K , 0x6A , ops -> block_size );
1035
+
1036
+ ops -> hash_init (outer_context );
1037
+ ops -> hash_update (outer_context , K , ops -> block_size );
1021
1038
1022
1039
/* Setup Main Loop to build a long enough result */
1023
1040
if (length == 0 ) {
@@ -1047,8 +1064,8 @@ PHP_FUNCTION(hash_pbkdf2)
1047
1064
computed_salt [salt_len + 2 ] = (unsigned char ) ((i & 0xFF00 ) >> 8 );
1048
1065
computed_salt [salt_len + 3 ] = (unsigned char ) (i & 0xFF );
1049
1066
1050
- php_hash_hmac_round (digest , ops , context , K1 , computed_salt , (zend_long ) salt_len + 4 );
1051
- php_hash_hmac_round (digest , ops , context , K2 , digest , ops -> digest_size );
1067
+ php_hash_hmac_continue (digest , ops , inner_context , context , computed_salt , (long ) salt_len + 4 );
1068
+ php_hash_hmac_continue (digest , ops , outer_context , context , digest , ops -> digest_size );
1052
1069
/* } */
1053
1070
1054
1071
/* temp = digest */
@@ -1060,8 +1077,8 @@ PHP_FUNCTION(hash_pbkdf2)
1060
1077
*/
1061
1078
for (j = 1 ; j < iterations ; j ++ ) {
1062
1079
/* digest = hash_hmac(digest, password) { */
1063
- php_hash_hmac_round (digest , ops , context , K1 , digest , ops -> digest_size );
1064
- php_hash_hmac_round (digest , ops , context , K2 , digest , ops -> digest_size );
1080
+ php_hash_hmac_continue (digest , ops , inner_context , context , digest , ops -> digest_size );
1081
+ php_hash_hmac_continue (digest , ops , outer_context , context , digest , ops -> digest_size );
1065
1082
/* } */
1066
1083
/* temp ^= digest */
1067
1084
php_hash_string_xor (temp , temp , digest , ops -> digest_size );
@@ -1070,12 +1087,15 @@ PHP_FUNCTION(hash_pbkdf2)
1070
1087
memcpy (result + ((i - 1 ) * ops -> digest_size ), temp , ops -> digest_size );
1071
1088
}
1072
1089
/* Zero potentially sensitive variables */
1073
- ZEND_SECURE_ZERO (K1 , ops -> block_size );
1074
- ZEND_SECURE_ZERO (K2 , ops -> block_size );
1090
+ ZEND_SECURE_ZERO (K , ops -> block_size );
1075
1091
ZEND_SECURE_ZERO (computed_salt , salt_len + 4 );
1076
- efree (K1 );
1077
- efree (K2 );
1092
+ ZEND_SECURE_ZERO (inner_context , ops -> context_size );
1093
+ ZEND_SECURE_ZERO (outer_context , ops -> context_size );
1094
+ ZEND_SECURE_ZERO (context , ops -> context_size );
1095
+ efree (K );
1078
1096
efree (computed_salt );
1097
+ efree (inner_context );
1098
+ efree (outer_context );
1079
1099
efree (context );
1080
1100
efree (digest );
1081
1101
efree (temp );
0 commit comments