From 15817a416e21e07c31d4100544d81377beed06f5 Mon Sep 17 00:00:00 2001 From: terrafrost Date: Sun, 3 Mar 2013 11:30:03 -0600 Subject: [PATCH 1/3] DES: Fix memory leak in OFB mode --- phpseclib/Crypt/DES.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/phpseclib/Crypt/DES.php b/phpseclib/Crypt/DES.php index c8254327..4349fad2 100644 --- a/phpseclib/Crypt/DES.php +++ b/phpseclib/Crypt/DES.php @@ -656,8 +656,10 @@ class Crypt_DES { $xor = $this->encryptIV; if (strlen($buffer['xor'])) { for ($i = 0; $i < strlen($plaintext); $i+=8) { - $xor = $this->_processBlock($xor, CRYPT_DES_ENCRYPT); - $buffer['xor'].= $xor; + if (strlen($block) > strlen($buffer['xor'])) { + $xor = $this->_processBlock($xor, CRYPT_DES_ENCRYPT); + $buffer['xor'].= $xor; + } $key = $this->_string_shift($buffer['xor'], 8); $ciphertext.= substr($plaintext, $i, 8) ^ $key; } @@ -843,8 +845,10 @@ class Crypt_DES { $xor = $this->decryptIV; if (strlen($buffer['xor'])) { for ($i = 0; $i < strlen($ciphertext); $i+=8) { - $xor = $this->_processBlock($xor, CRYPT_DES_ENCRYPT); - $buffer['xor'].= $xor; + if (strlen($block) > strlen($buffer['xor'])) { + $xor = $this->_processBlock($xor, CRYPT_DES_ENCRYPT); + $buffer['xor'].= $xor; + } $key = $this->_string_shift($buffer['xor'], 8); $plaintext.= substr($ciphertext, $i, 8) ^ $key; } From c4b3288851630eb5113c03a40d4e60ad083419e1 Mon Sep 17 00:00:00 2001 From: terrafrost Date: Sun, 3 Mar 2013 17:30:30 -0600 Subject: [PATCH 2/3] TripleDES, Rijndael: Fix overflow in OFB mode --- phpseclib/Crypt/Rijndael.php | 34 +++++++++++++++++++++------------- phpseclib/Crypt/TripleDES.php | 20 ++++++++++++-------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/phpseclib/Crypt/Rijndael.php b/phpseclib/Crypt/Rijndael.php index 682c8900..9ac4e1b2 100644 --- a/phpseclib/Crypt/Rijndael.php +++ b/phpseclib/Crypt/Rijndael.php @@ -900,8 +900,10 @@ class Crypt_Rijndael { $xor = $this->encryptIV; if (strlen($buffer['xor'])) { for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $xor = $this->_encryptBlock($xor); - $buffer['xor'].= $xor; + if (strlen($block) > strlen($buffer['xor'])) { + $xor = $this->_encryptBlock($xor); + $buffer['xor'].= $xor; + } $key = $this->_string_shift($buffer['xor'], $block_size); $ciphertext.= substr($plaintext, $i, $block_size) ^ $key; } @@ -1038,8 +1040,10 @@ class Crypt_Rijndael { $xor = $this->decryptIV; if (strlen($buffer['xor'])) { for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { - $xor = $this->_encryptBlock($xor); - $buffer['xor'].= $xor; + if (strlen($block) > strlen($buffer['xor'])) { + $xor = $this->_encryptBlock($xor); + $buffer['xor'].= $xor; + } $key = $this->_string_shift($buffer['xor'], $block_size); $plaintext.= substr($ciphertext, $i, $block_size) ^ $key; } @@ -1139,7 +1143,7 @@ class Crypt_Rijndael { $l = ($l + 1) % $Nb; } - // 100% ugly switch/case code... but ~5% faster (meaning: ~half second faster de/encrypting 1MB text, tested with php5.4.9 on linux/32bit with an AMD Athlon II P360 CPU) then the commented smart code below. Don't know it's worth or not + // 100% ugly switch/case code... but ~5% faster ("smart code" below commented out) switch ($Nb) { case 8: return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]); @@ -1969,10 +1973,12 @@ class Crypt_Rijndael { if (strlen($buffer["xor"])) { for ($i = 0; $i < $plaintext_len; $i+= '.$block_size.') { - $in = $xor; - '.$_encryptBlock.' - $xor = $in; - $buffer["xor"].= $xor; + if (strlen($block) > strlen($buffer["xor"])) { + $in = $xor; + '.$_encryptBlock.' + $xor = $in; + $buffer["xor"].= $xor; + } $key = $self->_string_shift($buffer["xor"], '.$block_size.'); $ciphertext.= substr($text, $i, '.$block_size.') ^ $key; } @@ -2002,10 +2008,12 @@ class Crypt_Rijndael { if (strlen($buffer["xor"])) { for ($i = 0; $i < $ciphertext_len; $i+= '.$block_size.') { - $in = $xor; - '.$_encryptBlock.' - $xor = $in; - $buffer["xor"].= $xor; + if (strlen($block) > strlen($buffer["xor"])) { + $in = $xor; + '.$_encryptBlock.' + $xor = $in; + $buffer["xor"].= $xor; + } $key = $self->_string_shift($buffer["xor"], '.$block_size.'); $plaintext.= substr($text, $i, '.$block_size.') ^ $key; } diff --git a/phpseclib/Crypt/TripleDES.php b/phpseclib/Crypt/TripleDES.php index 476ff53c..5af43ec9 100644 --- a/phpseclib/Crypt/TripleDES.php +++ b/phpseclib/Crypt/TripleDES.php @@ -669,10 +669,12 @@ class Crypt_TripleDES { $xor = $this->encryptIV; if (strlen($buffer['xor'])) { for ($i = 0; $i < strlen($plaintext); $i+=8) { - $xor = $des[0]->_processBlock($xor, CRYPT_DES_ENCRYPT); - $xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT); - $xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT); - $buffer['xor'].= $xor; + if (strlen($block) > strlen($buffer['xor'])) { + $xor = $des[0]->_processBlock($xor, CRYPT_DES_ENCRYPT); + $xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT); + $xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT); + $buffer['xor'].= $xor; + } $key = $this->_string_shift($buffer['xor'], 8); $ciphertext.= substr($plaintext, $i, 8) ^ $key; } @@ -880,10 +882,12 @@ class Crypt_TripleDES { $xor = $this->decryptIV; if (strlen($buffer['xor'])) { for ($i = 0; $i < strlen($ciphertext); $i+=8) { - $xor = $des[0]->_processBlock($xor, CRYPT_DES_ENCRYPT); - $xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT); - $xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT); - $buffer['xor'].= $xor; + if (strlen($block) > strlen($buffer['xor'])) { + $xor = $des[0]->_processBlock($xor, CRYPT_DES_ENCRYPT); + $xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT); + $xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT); + $buffer['xor'].= $xor; + } $key = $this->_string_shift($buffer['xor'], 8); $plaintext.= substr($ciphertext, $i, 8) ^ $key; } From 5f64ab67abe1cb4354b07d636039964c3d63522b Mon Sep 17 00:00:00 2001 From: terrafrost Date: Mon, 4 Mar 2013 08:25:40 -0600 Subject: [PATCH 3/3] DES: $block wasn't defined --- phpseclib/Crypt/DES.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/phpseclib/Crypt/DES.php b/phpseclib/Crypt/DES.php index 4349fad2..0b353b87 100644 --- a/phpseclib/Crypt/DES.php +++ b/phpseclib/Crypt/DES.php @@ -656,12 +656,13 @@ class Crypt_DES { $xor = $this->encryptIV; if (strlen($buffer['xor'])) { for ($i = 0; $i < strlen($plaintext); $i+=8) { + $block = substr($plaintext, $i, 8); if (strlen($block) > strlen($buffer['xor'])) { $xor = $this->_processBlock($xor, CRYPT_DES_ENCRYPT); $buffer['xor'].= $xor; } $key = $this->_string_shift($buffer['xor'], 8); - $ciphertext.= substr($plaintext, $i, 8) ^ $key; + $ciphertext.= $block ^ $key; } } else { for ($i = 0; $i < strlen($plaintext); $i+=8) { @@ -845,12 +846,13 @@ class Crypt_DES { $xor = $this->decryptIV; if (strlen($buffer['xor'])) { for ($i = 0; $i < strlen($ciphertext); $i+=8) { + $block = substr($plaintext, $i, 8); if (strlen($block) > strlen($buffer['xor'])) { $xor = $this->_processBlock($xor, CRYPT_DES_ENCRYPT); $buffer['xor'].= $xor; } $key = $this->_string_shift($buffer['xor'], 8); - $plaintext.= substr($ciphertext, $i, 8) ^ $key; + $plaintext.= $block ^ $key; } } else { for ($i = 0; $i < strlen($ciphertext); $i+=8) {