From c8d379daa5f6e8f2c474b2a8f5b7aed8cc44c0b8 Mon Sep 17 00:00:00 2001
From: terrafrost <terrafrost@gmail.com>
Date: Fri, 28 Jan 2022 14:39:16 -0600
Subject: [PATCH 1/2] Crypt/Base: add OFB8 as a new mode

---
 phpseclib/Crypt/Base.php          | 118 ++++++++++++++++++++++++++++--
 tests/Unit/Crypt/AES/TestCase.php |   2 +
 2 files changed, 115 insertions(+), 5 deletions(-)

diff --git a/phpseclib/Crypt/Base.php b/phpseclib/Crypt/Base.php
index 8822b9b8..6335a248 100644
--- a/phpseclib/Crypt/Base.php
+++ b/phpseclib/Crypt/Base.php
@@ -79,7 +79,11 @@ abstract class Base
     /**
      * Encrypt / decrypt using the Cipher Feedback mode (8bit)
      */
-    const MODE_CFB8 = 38;
+    const MODE_CFB8 = 6;
+    /**
+     * Encrypt / decrypt using the Output Feedback mode (8bit)
+     */
+    const MODE_OFB8 = 7;
     /**
      * Encrypt / decrypt using the Output Feedback mode.
      *
@@ -484,6 +488,7 @@ abstract class Base
             case self::MODE_CTR:
             case self::MODE_CFB:
             case self::MODE_CFB8:
+            case self::MODE_OFB8:
             case self::MODE_OFB:
             case self::MODE_STREAM:
                 $this->mode = $mode;
@@ -773,8 +778,25 @@ abstract class Base
                         }
                     }
                     return $ciphertext;
+                case self::MODE_OFB8:
+                    $ciphertext = '';
+                    $len = strlen($plaintext);
+                    $iv = $this->encryptIV;
+
+                    for ($i = 0; $i < $len; ++$i) {
+                        $xor = openssl_encrypt($iv, $this->cipher_name_openssl_ecb, $this->key, $this->openssl_options, $this->decryptIV);
+                        $ciphertext.= $plaintext[$i] ^ $xor;
+                        $iv = substr($iv, 1) . $xor[0];
+                    }
+
+                    if ($this->continuousBuffer) {
+                        $this->encryptIV = $iv;
+                    }
+                    break;
                 case self::MODE_OFB:
                     return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
+                case self::MODE_OFB8:
+                    // OpenSSL has built in support for cfb8 but not ofb8
             }
         }
 
@@ -959,12 +981,14 @@ abstract class Base
                 }
                 break;
             case self::MODE_CFB8:
+                // compared to regular CFB, which encrypts a block at a time,
+                // here, we're encrypting a byte at a time
                 $ciphertext = '';
                 $len = strlen($plaintext);
                 $iv = $this->encryptIV;
 
                 for ($i = 0; $i < $len; ++$i) {
-                    $ciphertext .= ($c = $plaintext[$i] ^ $this->_encryptBlock($iv));
+                    $ciphertext.= ($c = $plaintext[$i] ^ $this->_encryptBlock($iv));
                     $iv = substr($iv, 1) . $c;
                 }
 
@@ -976,6 +1000,21 @@ abstract class Base
                     }
                 }
                 break;
+            case self::MODE_OFB8:
+                $ciphertext = '';
+                $len = strlen($plaintext);
+                $iv = $this->encryptIV;
+
+                for ($i = 0; $i < $len; ++$i) {
+                    $xor = $this->_encryptBlock($iv);
+                    $ciphertext.= $plaintext[$i] ^ $xor;
+                    $iv = substr($iv, 1) . $xor[0];
+                }
+
+                if ($this->continuousBuffer) {
+                    $this->encryptIV = $iv;
+                }
+                break;
             case self::MODE_OFB:
                 $xor = $this->encryptIV;
                 if (strlen($buffer['xor'])) {
@@ -1116,6 +1155,21 @@ abstract class Base
                         }
                     }
                     break;
+                case self::MODE_OFB8:
+                    $plaintext = '';
+                    $len = strlen($ciphertext);
+                    $iv = $this->decryptIV;
+
+                    for ($i = 0; $i < $len; ++$i) {
+                        $xor = openssl_encrypt($iv, $this->cipher_name_openssl_ecb, $this->key, $this->openssl_options, $this->decryptIV);
+                        $plaintext.= $ciphertext[$i] ^ $xor;
+                        $iv = substr($iv, 1) . $xor[0];
+                    }
+
+                    if ($this->continuousBuffer) {
+                        $this->decryptIV = $iv;
+                    }
+                    break;
                 case self::MODE_OFB:
                     $plaintext = $this->_openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
             }
@@ -1290,7 +1344,7 @@ abstract class Base
                 $iv = $this->decryptIV;
 
                 for ($i = 0; $i < $len; ++$i) {
-                    $plaintext .= $ciphertext[$i] ^ $this->_encryptBlock($iv);
+                    $plaintext.= $ciphertext[$i] ^ $this->_encryptBlock($iv);
                     $iv = substr($iv, 1) . $ciphertext[$i];
                 }
 
@@ -1302,6 +1356,21 @@ abstract class Base
                     }
                 }
                 break;
+            case self::MODE_OFB8:
+                $plaintext = '';
+                $len = strlen($ciphertext);
+                $iv = $this->decryptIV;
+
+                for ($i = 0; $i < $len; ++$i) {
+                    $xor = $this->_encryptBlock($iv);
+                    $plaintext.= $ciphertext[$i] ^ $xor;
+                    $iv = substr($iv, 1) . $xor[0];
+                }
+
+                if ($this->continuousBuffer) {
+                    $this->decryptIV = $iv;
+                }
+                break;
             case self::MODE_OFB:
                 $xor = $this->decryptIV;
                 if (strlen($buffer['xor'])) {
@@ -1864,6 +1933,7 @@ abstract class Base
                 self::MODE_CFB    => 'ncfb',
                 self::MODE_CFB8   => MCRYPT_MODE_CFB,
                 self::MODE_OFB    => MCRYPT_MODE_NOFB,
+                self::MODE_OFB8   => MCRYPT_MODE_OFB,
                 self::MODE_STREAM => MCRYPT_MODE_STREAM,
             );
 
@@ -2446,7 +2516,7 @@ abstract class Base
                     for ($_i = 0; $_i < $_len; ++$_i) {
                         $in = $_iv;
                         '.$encrypt_block.'
-                        $_ciphertext .= ($_c = $_text[$_i] ^ $in);
+                        $_ciphertext.= ($_c = $_text[$_i] ^ $in);
                         $_iv = substr($_iv, 1) . $_c;
                     }
 
@@ -2468,7 +2538,7 @@ abstract class Base
                     for ($_i = 0; $_i < $_len; ++$_i) {
                         $in = $_iv;
                         '.$encrypt_block.'
-                        $_plaintext .= $_text[$_i] ^ $in;
+                        $_plaintext.= $_text[$_i] ^ $in;
                         $_iv = substr($_iv, 1) . $_text[$_i];
                     }
 
@@ -2480,6 +2550,44 @@ abstract class Base
                         }
                     }
 
+                    return $_plaintext;
+                    ';
+                break;
+            case self::MODE_OFB8:
+                $encrypt = $init_encrypt . '
+                    $_ciphertext = "";
+                    $_len = strlen($_text);
+                    $_iv = $self->encryptIV;
+
+                    for ($_i = 0; $_i < $_len; ++$_i) {
+                        $in = $_iv;
+                        '.$encrypt_block.'
+                        $_ciphertext.= $_text[$_i] ^ $in;
+                        $_iv = substr($_iv, 1) . $in[0];
+                    }
+
+                    if ($self->continuousBuffer) {
+                        $self->encryptIV = $_iv;
+                    }
+
+                    return $_ciphertext;
+                    ';
+                $decrypt = $init_encrypt . '
+                    $_plaintext = "";
+                    $_len = strlen($_text);
+                    $_iv = $self->decryptIV;
+
+                    for ($_i = 0; $_i < $_len; ++$_i) {
+                        $in = $_iv;
+                        '.$encrypt_block.'
+                        $_plaintext.= $_text[$_i] ^ $in;
+                        $_iv = substr($_iv, 1) . $in[0];
+                    }
+
+                    if ($self->continuousBuffer) {
+                        $self->decryptIV = $_iv;
+                    }
+
                     return $_plaintext;
                     ';
                 break;
diff --git a/tests/Unit/Crypt/AES/TestCase.php b/tests/Unit/Crypt/AES/TestCase.php
index 1c7a4563..ff877a5f 100644
--- a/tests/Unit/Crypt/AES/TestCase.php
+++ b/tests/Unit/Crypt/AES/TestCase.php
@@ -40,6 +40,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
             Base::MODE_OFB,
             Base::MODE_CFB,
             Base::MODE_CFB8,
+            Base::MODE_OFB8,
         );
         $plaintexts = array(
             '',
@@ -138,6 +139,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
             Base::MODE_OFB,
             Base::MODE_CFB,
             Base::MODE_CFB8,
+            Base::MODE_OFB8,
         );
 
         $combos = array(

From 56ed69fbe725f86592236629a864a0f0e674a801 Mon Sep 17 00:00:00 2001
From: terrafrost <terrafrost@gmail.com>
Date: Sat, 29 Jan 2022 07:40:37 -0600
Subject: [PATCH 2/2] fix bad merge

---
 phpseclib/Crypt/Common/SymmetricKey.php | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/phpseclib/Crypt/Common/SymmetricKey.php b/phpseclib/Crypt/Common/SymmetricKey.php
index e052cfdc..08dec4bc 100644
--- a/phpseclib/Crypt/Common/SymmetricKey.php
+++ b/phpseclib/Crypt/Common/SymmetricKey.php
@@ -101,7 +101,7 @@ abstract class SymmetricKey
      * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
      * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
      */
-    const MODE_CFB8 = 6;
+    const MODE_CFB8 = 7;
     /**
      * Encrypt / decrypt using the Output Feedback mode (8bit)
      *
@@ -109,7 +109,7 @@ abstract class SymmetricKey
      * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
      * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
      */
-    const MODE_OFB8 = 7; 
+    const MODE_OFB8 = 8;
     /**
      * Encrypt / decrypt using the Output Feedback mode.
      *
@@ -3054,7 +3054,7 @@ abstract class SymmetricKey
                 $encrypt = $init_encrypt . '
                     $_ciphertext = "";
                     $_len = strlen($_text);
-                    $_iv = $self->encryptIV;
+                    $_iv = $this->encryptIV;
 
                     for ($_i = 0; $_i < $_len; ++$_i) {
                         $in = $_iv;
@@ -3063,8 +3063,8 @@ abstract class SymmetricKey
                         $_iv = substr($_iv, 1) . $in[0];
                     }
 
-                    if ($self->continuousBuffer) {
-                        $self->encryptIV = $_iv;
+                    if ($this->continuousBuffer) {
+                        $this->encryptIV = $_iv;
                     }
 
                     return $_ciphertext;
@@ -3072,7 +3072,7 @@ abstract class SymmetricKey
                 $decrypt = $init_encrypt . '
                     $_plaintext = "";
                     $_len = strlen($_text);
-                    $_iv = $self->decryptIV;
+                    $_iv = $this->decryptIV;
 
                     for ($_i = 0; $_i < $_len; ++$_i) {
                         $in = $_iv;
@@ -3081,8 +3081,8 @@ abstract class SymmetricKey
                         $_iv = substr($_iv, 1) . $in[0];
                     }
 
-                    if ($self->continuousBuffer) {
-                        $self->decryptIV = $_iv;
+                    if ($this->continuousBuffer) {
+                        $this->decryptIV = $_iv;
                     }
 
                     return $_plaintext;