Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-40479: Fix hashlib's usedforsecurity for OpenSSL 3.0.0 (GH-30455) #30455

Merged
merged 10 commits into from
Jan 13, 2022
4 changes: 2 additions & 2 deletions Doc/library/hashlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ More condensed:

Using :func:`new` with an algorithm provided by OpenSSL:

>>> h = hashlib.new('sha512_256')
>>> h = hashlib.new('sha256')
>>> h.update(b"Nobody inspects the spammish repetition")
>>> h.hexdigest()
'19197dc4d03829df858011c6c87600f994a858103bbc19005f20987aa19a97e2'
'031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406'

Hashlib provides the following constant attributes:

Expand Down
13 changes: 7 additions & 6 deletions Lib/test/test_hashlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,15 @@
builtin_hashlib = None

try:
from _hashlib import HASH, HASHXOF, openssl_md_meth_names
from _hashlib import HASH, HASHXOF, openssl_md_meth_names, get_fips_mode
except ImportError:
HASH = None
HASHXOF = None
openssl_md_meth_names = frozenset()

def get_fips_mode():
return 0

try:
import _blake2
except ImportError:
Expand Down Expand Up @@ -192,10 +195,7 @@ def hash_constructors(self):

@property
def is_fips_mode(self):
if hasattr(self._hashlib, "get_fips_mode"):
return self._hashlib.get_fips_mode()
else:
return None
return get_fips_mode()

def test_hash_array(self):
a = array.array("b", range(10))
Expand Down Expand Up @@ -1017,7 +1017,7 @@ def _test_pbkdf2_hmac(self, pbkdf2, supported):
self.assertEqual(out, expected,
(digest_name, password, salt, rounds))

with self.assertRaisesRegex(ValueError, 'unsupported hash type'):
with self.assertRaisesRegex(ValueError, '.*unsupported.*'):
pbkdf2('unknown', b'pass', b'salt', 1)

if 'sha1' in supported:
Expand Down Expand Up @@ -1057,6 +1057,7 @@ def test_pbkdf2_hmac_c(self):

@unittest.skipUnless(hasattr(hashlib, 'scrypt'),
' test requires OpenSSL > 1.1')
@unittest.skipIf(get_fips_mode(), reason="scrypt is blocked in FIPS mode")
def test_scrypt(self):
for password, salt, n, r, p, expected in self.scrypt_test_vectors:
result = hashlib.scrypt(password, salt=salt, n=n, r=r, p=p)
Expand Down
6 changes: 3 additions & 3 deletions Lib/test/test_imaplib.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ def cmd_AUTHENTICATE(self, tag, args):
self.assertEqual(code, 'OK')
self.assertEqual(server.response, b'ZmFrZQ==\r\n') # b64 encoded 'fake'

@hashlib_helper.requires_hashdigest('md5')
@hashlib_helper.requires_hashdigest('md5', openssl=True)
def test_login_cram_md5_bytes(self):
class AuthHandler(SimpleIMAPHandler):
capabilities = 'LOGINDISABLED AUTH=CRAM-MD5'
Expand All @@ -405,7 +405,7 @@ def cmd_AUTHENTICATE(self, tag, args):
ret, _ = client.login_cram_md5("tim", b"tanstaaftanstaaf")
self.assertEqual(ret, "OK")

@hashlib_helper.requires_hashdigest('md5')
@hashlib_helper.requires_hashdigest('md5', openssl=True)
def test_login_cram_md5_plain_text(self):
class AuthHandler(SimpleIMAPHandler):
capabilities = 'LOGINDISABLED AUTH=CRAM-MD5'
Expand Down Expand Up @@ -851,7 +851,7 @@ def cmd_AUTHENTICATE(self, tag, args):
b'ZmFrZQ==\r\n') # b64 encoded 'fake'

@threading_helper.reap_threads
@hashlib_helper.requires_hashdigest('md5')
@hashlib_helper.requires_hashdigest('md5', openssl=True)
def test_login_cram_md5(self):

class AuthHandler(SimpleIMAPHandler):
Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_poplib.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,11 +318,11 @@ def test_noop(self):
def test_rpop(self):
self.assertOK(self.client.rpop('foo'))

@hashlib_helper.requires_hashdigest('md5')
@hashlib_helper.requires_hashdigest('md5', openssl=True)
def test_apop_normal(self):
self.assertOK(self.client.apop('foo', 'dummypassword'))

@hashlib_helper.requires_hashdigest('md5')
@hashlib_helper.requires_hashdigest('md5', openssl=True)
def test_apop_REDOS(self):
# Replace welcome with very long evil welcome.
# NB The upper bound on welcome length is currently 2048.
Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_smtplib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1171,7 +1171,7 @@ def auth_buggy(challenge=None):
finally:
smtp.close()

@hashlib_helper.requires_hashdigest('md5')
@hashlib_helper.requires_hashdigest('md5', openssl=True)
def testAUTH_CRAM_MD5(self):
self.serv.add_feature("AUTH CRAM-MD5")
smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost',
Expand All @@ -1180,7 +1180,7 @@ def testAUTH_CRAM_MD5(self):
self.assertEqual(resp, (235, b'Authentication Succeeded'))
smtp.close()

@hashlib_helper.requires_hashdigest('md5')
@hashlib_helper.requires_hashdigest('md5', openssl=True)
def testAUTH_multiple(self):
# Test that multiple authentication methods are tried.
self.serv.add_feature("AUTH BOGUS PLAIN LOGIN CRAM-MD5")
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_tools/test_md5sum.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

skip_if_missing()

@hashlib_helper.requires_hashdigest('md5')
@hashlib_helper.requires_hashdigest('md5', openssl=True)
class MD5SumTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_urllib2_localnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ def test_basic_auth_httperror(self):
self.assertRaises(urllib.error.HTTPError, urllib.request.urlopen, self.server_url)


@hashlib_helper.requires_hashdigest("md5")
@hashlib_helper.requires_hashdigest("md5", openssl=True)
class ProxyAuthTests(unittest.TestCase):
URL = "http://localhost"

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix :mod:`hashlib` *usedforsecurity* option to work correctly with OpenSSL
3.0.0 in FIPS mode.
Loading