summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Andreev <narf@devilix.net>2014-02-06 01:38:27 +0100
committerAndrey Andreev <narf@devilix.net>2014-02-06 01:38:27 +0100
commit7c5544817de29222aa2d79ac7445122d57ad62c6 (patch)
treedd7ae9b077aa3318dabdb5beff4233ff171f29e9
parent8d33a9a4a8ac924678ae5bba6387ca7fce206f4b (diff)
CI_Encryption: Time-attack-safe HMAC verification
-rw-r--r--system/libraries/Encryption.php22
1 files changed, 18 insertions, 4 deletions
diff --git a/system/libraries/Encryption.php b/system/libraries/Encryption.php
index 36975e585..f5950ee46 100644
--- a/system/libraries/Encryption.php
+++ b/system/libraries/Encryption.php
@@ -481,17 +481,31 @@ class CI_Encryption {
if (isset($params['hmac_digest']))
{
- isset($params['hmac_key']) OR $params['hmac_key'] = $this->hkdf($this->_key, 'sha512', NULL, NULL, 'authentication');
-
// This might look illogical, but it is done during encryption as well ...
// The 'base64' value is effectively an inverted "raw data" parameter
$digest_size = ($params['base64'])
? $this->_digests[$params['hmac_digest']] * 2
: $this->_digests[$params['hmac_digest']];
- $hmac = substr($data, 0, $digest_size);
+
+ if (strlen($data) <= $digest_size)
+ {
+ return FALSE;
+ }
+
+ $hmac_input = substr($data, 0, $digest_size);
$data = substr($data, $digest_size);
- if ($hmac !== hash_hmac($params['hmac_digest'], $data, $params['hmac_key'], ! $params['base64']))
+ isset($params['hmac_key']) OR $params['hmac_key'] = $this->hkdf($this->_key, 'sha512', NULL, NULL, 'authentication');
+ $hmac_check = hash_hmac($params['hmac_digest'], $data, $params['hmac_key'], ! $params['base64']);
+
+ // Time-attack-safe comparison
+ $diff = 0;
+ for ($i = 0; $i < $digest_size; $i++)
+ {
+ $diff |= ord($hmac_input[$i]) ^ ord($hmac_check[$i]);
+ }
+
+ if ($diff !== 0)
{
return FALSE;
}