Skip to content

Commit 2bb7fb6

Browse files
committed
always fallback to the pure Python implementation
1 parent 1082bd5 commit 2bb7fb6

File tree

3 files changed

+26
-33
lines changed

3 files changed

+26
-33
lines changed

Lib/hmac.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -242,22 +242,24 @@ def digest(key, msg, digest):
242242
try:
243243
return _hashopenssl.hmac_digest(key, msg, digest)
244244
except OverflowError:
245-
try:
246-
return _hashopenssl.hmac_new(key, msg, digest).digest()
247-
except _hashopenssl.UnsupportedDigestmodError:
248-
pass
245+
# OpenSSL's HMAC limits the size of the key to INT_MAX.
246+
# Instead of falling back to HACL* implementation which
247+
# may still not be supported due to a too large key, we
248+
# directly switch to the pure Python fallback instead
249+
# even if we could have used streaming HMAC for small keys
250+
# but large messages.
251+
return _compute_digest_fallback(key, msg, digest)
249252
except _hashopenssl.UnsupportedDigestmodError:
250253
pass
251254

252255
if _hmac and isinstance(digest, str):
253256
try:
254257
return _hmac.compute_digest(key, msg, digest)
255-
except OverflowError:
256-
try:
257-
return _hmac.new(key, msg, digest).digest()
258-
except _hmac.UnknownHashError:
259-
pass
260-
except _hmac.UnknownHashError:
258+
except (OverflowError, _hmac.UnknownHashError):
259+
# HACL* HMAC limits the size of the key to UINT32_MAX
260+
# so we fallback to the pure Python implementation even
261+
# if streaming HMAC may have been used for small keys
262+
# and large messages.
261263
pass
262264

263265
return _compute_digest_fallback(key, msg, digest)

Lib/test/test_hmac.py

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,37 +1506,28 @@ def test_with_fallback(self):
15061506
@hashlib_helper.requires_openssl_hashdigest("md5")
15071507
@bigmemtest(size=_4G, memuse=2, dry_run=False)
15081508
def test_hmac_digest_overflow_error_openssl_only(self, size):
1509-
self.do_test_hmac_digest_overflow_error_fast(size, openssl=True)
1509+
hmac = import_fresh_module("hmac", blocked=["_hmac"])
1510+
self.do_test_hmac_digest_overflow_error_switch_to_slow(hmac, size)
15101511

15111512
@hashlib_helper.requires_builtin_hashdigest("_md5", "md5")
15121513
@bigmemtest(size=_4G , memuse=2, dry_run=False)
15131514
def test_hmac_digest_overflow_error_builtin_only(self, size):
1514-
self.do_test_hmac_digest_overflow_error_fast(size, openssl=False)
1515-
1516-
def do_test_hmac_digest_overflow_error_fast(self, size, *, openssl):
1517-
"""Check that C hmac.digest() works for large inputs."""
1518-
1519-
if openssl:
1520-
hmac = import_fresh_module("hmac", blocked=["_hashlib"])
1521-
c_module_name, c_method_name = "_hmac", "new"
1522-
else:
1523-
hmac = import_fresh_module("hmac", blocked=["_hmac"])
1524-
c_module_name, c_method_name = "_hashlib", "hmac_new"
1515+
hmac = import_fresh_module("hmac", blocked=["_hashlib"])
1516+
self.do_test_hmac_digest_overflow_error_switch_to_slow(hmac, size)
15251517

1526-
cext = import_helper.import_module(c_module_name)
1527-
cnew = getattr(cext, c_method_name)
1518+
def do_test_hmac_digest_overflow_error_switch_to_slow(self, hmac, size):
1519+
"""Check that hmac.digest() falls back to pure Python."""
15281520

15291521
bigkey = b'K' * size
15301522
bigmsg = b'M' * size
15311523

15321524
with patch.object(hmac, "_compute_digest_fallback") as slow:
1533-
with patch.object(cext, c_method_name, wraps=cnew) as new:
1534-
self.assertIsInstance(hmac.digest(bigkey, b'm', "md5"), bytes)
1535-
new.assert_called_once()
1536-
with patch.object(cext, c_method_name, wraps=cnew) as new:
1537-
self.assertIsInstance(hmac.digest(b'k', bigmsg, "md5"), bytes)
1538-
new.assert_called_once()
1539-
slow.assert_not_called()
1525+
self.assertIsInstance(hmac.digest(bigkey, b'm', "md5"), bytes)
1526+
slow.assert_called_once()
1527+
1528+
with patch.object(hmac, "_compute_digest_fallback") as slow:
1529+
self.assertIsInstance(hmac.digest(b'k', bigmsg, "md5"), bytes)
1530+
slow.assert_called_once()
15401531

15411532
@hashlib_helper.requires_hashdigest("md5", openssl=True)
15421533
@bigmemtest(size=_4G, memuse=2, dry_run=False)
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
One-shot :func:`hmac.digest` now properly handles large keys and messages
2-
by delegating to :func:`hmac.new` when possible. Patch by Bénédikt Tran.
1+
One-shot :func:`hmac.digest` now properly handles large keys and messages.
2+
Patch by Bénédikt Tran.

0 commit comments

Comments
 (0)