diff options
author | Jeff Forcier <jeff@bitprophet.org> | 2014-02-14 11:53:59 -0800 |
---|---|---|
committer | Jeff Forcier <jeff@bitprophet.org> | 2014-02-14 11:53:59 -0800 |
commit | 4e9af2f7ca91613ea4c60ca22b96adc2247b1ba2 (patch) | |
tree | 7867d5d252825df16830e4aed09ad79ab2f089ec | |
parent | 4a5f007c029cfabac35161d8147d616c79009bd8 (diff) | |
parent | 30518280f1356465f0acfdb4816843b61303a633 (diff) |
Merge branch '1.10' into 1.11
Conflicts:
sites/www/changelog.rst
-rw-r--r-- | paramiko/hostkeys.py | 4 | ||||
-rw-r--r-- | paramiko/packet.py | 2 | ||||
-rw-r--r-- | paramiko/util.py | 9 | ||||
-rw-r--r-- | sites/www/changelog.rst | 4 |
4 files changed, 16 insertions, 3 deletions
diff --git a/paramiko/hostkeys.py b/paramiko/hostkeys.py index f967a3da..c34b1738 100644 --- a/paramiko/hostkeys.py +++ b/paramiko/hostkeys.py @@ -28,7 +28,7 @@ import UserDict from paramiko.common import * from paramiko.dsskey import DSSKey from paramiko.rsakey import RSAKey -from paramiko.util import get_logger +from paramiko.util import get_logger, constant_time_bytes_eq class InvalidHostKey(Exception): @@ -243,7 +243,7 @@ class HostKeys (UserDict.DictMixin): entries = [] for e in self._entries: for h in e.hostnames: - if (h.startswith('|1|') and (self.hash_host(hostname, h) == h)) or (h == hostname): + if h.startswith('|1|') and constant_time_bytes_eq(self.hash_host(hostname, h), h) or h == hostname: entries.append(e) if len(entries) == 0: return None diff --git a/paramiko/packet.py b/paramiko/packet.py index 6ab7363d..af807956 100644 --- a/paramiko/packet.py +++ b/paramiko/packet.py @@ -357,7 +357,7 @@ class Packetizer (object): mac = post_packet[:self.__mac_size_in] mac_payload = struct.pack('>II', self.__sequence_number_in, packet_size) + packet my_mac = compute_hmac(self.__mac_key_in, mac_payload, self.__mac_engine_in)[:self.__mac_size_in] - if my_mac != mac: + if not util.constant_time_bytes_eq(my_mac, mac): raise SSHException('Mismatched MAC') padding = ord(packet[0]) payload = packet[1:packet_size - padding] diff --git a/paramiko/util.py b/paramiko/util.py index 85ee6b06..9db512de 100644 --- a/paramiko/util.py +++ b/paramiko/util.py @@ -309,3 +309,12 @@ class Counter (object): def new(cls, nbits, initial_value=1L, overflow=0L): return cls(nbits, initial_value=initial_value, overflow=overflow) new = classmethod(new) + + +def constant_time_bytes_eq(a, b): + if len(a) != len(b): + return False + res = 0 + for i in xrange(len(a)): + res |= ord(a[i]) ^ ord(b[i]) + return res == 0 diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst index efd6610b..9d41cb22 100644 --- a/sites/www/changelog.rst +++ b/sites/www/changelog.rst @@ -2,6 +2,10 @@ Changelog ========= +* :bug:`-` Use constant-time hash comparison operations where possible, to + protect against `timing-based attacks + <http://codahale.com/a-lesson-in-timing-attacks/>`_. Thanks to Alex Gaynor + for the patch. * :release:`1.11.4 <2014-02-14>` * :release:`1.10.6 <2014-02-14>` * :bug:`252` (`Fabric #1020 <https://github.com/fabric/fabric/issues/1020>`_) |