From 580eb94fd33cecbfb27acc230730cd18134884ea Mon Sep 17 00:00:00 2001 From: terrafrost Date: Sun, 8 Sep 2019 11:23:29 -0500 Subject: [PATCH] SSH2: add umac-64 / umac-128 support --- phpseclib/Crypt/Hash.php | 2 ++ phpseclib/Net/SSH2.php | 57 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/phpseclib/Crypt/Hash.php b/phpseclib/Crypt/Hash.php index 79413903..2059c5cd 100644 --- a/phpseclib/Crypt/Hash.php +++ b/phpseclib/Crypt/Hash.php @@ -582,6 +582,7 @@ class Hash // $length = strlen($m[$i]); $pad = 32 - ($length % 32); + $pad%= 32; $m[$i] = str_pad($m[$i], $length + $pad, "\0"); // zeropad $m[$i] = pack('N*', ...unpack('V*', $m[$i])); // ENDIAN-SWAP @@ -688,6 +689,7 @@ class Hash $m_2 = substr($m, 0x20000) . "\x80"; $length = strlen($m_2); $pad = 16 - ($length % 16); + $pad%= 16; $m_2 = str_pad($m_2, $length + $pad, "\0"); // zeropad $y = self::poly(64, self::$maxwordrange64, $k64, $m_1); $y = str_pad($y, 16, "\0", STR_PAD_LEFT); diff --git a/phpseclib/Net/SSH2.php b/phpseclib/Net/SSH2.php index f323ef00..b6346d2c 100644 --- a/phpseclib/Net/SSH2.php +++ b/phpseclib/Net/SSH2.php @@ -1781,6 +1781,18 @@ class SSH2 $createKeyLength = 0; // ie. $mac_algorithm == 'none' switch ($mac_algorithm) { + case 'umac-64@openssh.com': + $this->hmac_create = new Hash('umac-64'); + $createKeyLength = 16; + break; + case 'umac-128@openssh.com': + $this->hmac_create = new Hash('umac-128'); + $createKeyLength = 16; + break; + case 'hmac-sha2-512': + $this->hmac_create = new Hash('sha512'); + $createKeyLength = 64; + break; case 'hmac-sha2-256': $this->hmac_create = new Hash('sha256'); $createKeyLength = 32; @@ -1826,6 +1838,21 @@ class SSH2 $checkKeyLength = 0; $this->hmac_size = 0; switch ($mac_algorithm) { + case 'umac-64@openssh.com': + $this->hmac_check = new Hash('umac-64'); + $checkKeyLength = 16; + $this->hmac_size = 8; + break; + case 'umac-128@openssh.com': + $this->hmac_check = new Hash('umac-128'); + $checkKeyLength = 16; + $this->hmac_size = 16; + break; + case 'hmac-sha2-512': + $this->hmac_check = new Hash('sha512'); + $checkKeyLength = 64; + $this->hmac_size = 64; + break; case 'hmac-sha2-256': $this->hmac_check = new Hash('sha256'); $checkKeyLength = 32; @@ -3228,8 +3255,18 @@ class SSH2 if ($hmac === false || strlen($hmac) != $this->hmac_size) { $this->bitmap = 0; throw new \RuntimeException('Error reading socket'); - } elseif ($hmac != $this->hmac_check->hash(pack('NNCa*', $this->get_seq_no, $packet_length, $padding_length, $payload . $padding))) { - throw new \RuntimeException('Invalid HMAC'); + } + + $reconstructed = pack('NCa*', $packet_length, $padding_length, $payload . $padding); + if (($this->hmac_check->getHash() & "\xFF\xFF\xFF\xFF") == 'umac') { + $this->hmac_check->setNonce("\0\0\0\0" . pack('N', $this->get_seq_no)); + if ($hmac != $this->hmac_check->hash($reconstructed)) { + throw new \RuntimeException('Invalid UMAC'); + } + } else { + if ($hmac != $this->hmac_check->hash(pack('Na*', $this->get_seq_no, $reconstructed))) { + throw new \RuntimeException('Invalid HMAC'); + } } } @@ -3792,7 +3829,16 @@ class SSH2 // we subtract 4 from packet_length because the packet_length field isn't supposed to include itself $packet = pack('NCa*', $packet_length - 4, $padding_length, $data . $padding); - $hmac = $this->hmac_create instanceof Hash ? $this->hmac_create->hash(pack('Na*', $this->send_seq_no, $packet)) : ''; + if (!$this->hmac_create instanceof Hash) { + $hmac = ''; + } else { + if (($this->hmac_create->getHash() & "\xFF\xFF\xFF\xFF") == 'umac') { + $this->hmac_create->setNonce("\0\0\0\0" . pack('N', $this->send_seq_no)); + $hmac = $this->hmac_create->hash($packet); + } else { + $hmac = $this->hmac_create->hash(pack('Na*', $this->send_seq_no, $packet)); + } + } $this->send_seq_no++; if ($this->encrypt) { @@ -4396,8 +4442,13 @@ class SSH2 { return [ // from : + 'hmac-sha2-512',// OPTIONAL HMAC-SHA512 (digest length = key length = 64) 'hmac-sha2-256',// RECOMMENDED HMAC-SHA256 (digest length = key length = 32) + // from : + 'umac-64@openssh.com', + 'umac-128@openssh.com', + 'hmac-sha1-96', // RECOMMENDED first 96 bits of HMAC-SHA1 (digest length = 12, key length = 20) 'hmac-sha1', // REQUIRED HMAC-SHA1 (digest length = key length = 20) 'hmac-md5-96', // OPTIONAL first 96 bits of HMAC-MD5 (digest length = 12, key length = 16)