|
|
b7e076 |
From 53d108c5103c99079f1f231b0e731f3f47a142fc Mon Sep 17 00:00:00 2001
|
|
|
b7e076 |
From: "Miss Islington (bot)"
|
|
|
b7e076 |
<31488909+miss-islington@users.noreply.github.com>
|
|
|
b7e076 |
Date: Wed, 25 Sep 2019 08:50:31 -0700
|
|
|
3d909f |
Subject: [PATCH 01/37] [3.8] bpo-38270: Check for hash digest algorithms and
|
|
|
b7e076 |
avoid MD5 (GH-16382) (GH-16393)
|
|
|
b7e076 |
|
|
|
b7e076 |
Make it easier to run and test Python on systems with restrict crypto policies:
|
|
|
b7e076 |
|
|
|
b7e076 |
* add requires_hashdigest to test.support to check if a hash digest algorithm is available and working
|
|
|
b7e076 |
* avoid MD5 in test_hmac
|
|
|
b7e076 |
* replace MD5 with SHA256 in test_tarfile
|
|
|
b7e076 |
* mark network tests that require MD5 for MD5-based digest auth or CRAM-MD5
|
|
|
b7e076 |
|
|
|
b7e076 |
https://bugs.python.org/issue38270
|
|
|
b7e076 |
(cherry picked from commit c64a1a61e6fc542cada40eb069a239317e1af36e)
|
|
|
b7e076 |
|
|
|
b7e076 |
Co-authored-by: Christian Heimes <christian@python.org>
|
|
|
b7e076 |
|
|
|
b7e076 |
https://bugs.python.org/issue38270
|
|
|
b7e076 |
|
|
|
b7e076 |
Automerge-Triggered-By: @tiran
|
|
|
b7e076 |
---
|
|
|
b7e076 |
Lib/test/support/__init__.py | 22 ++++++++++
|
|
|
b7e076 |
Lib/test/test_hmac.py | 67 +++++++++++++++++++------------
|
|
|
b7e076 |
Lib/test/test_imaplib.py | 6 ++-
|
|
|
b7e076 |
Lib/test/test_poplib.py | 2 +
|
|
|
b7e076 |
Lib/test/test_smtplib.py | 11 ++++-
|
|
|
b7e076 |
Lib/test/test_tarfile.py | 56 ++++++++++++++------------
|
|
|
b7e076 |
Lib/test/test_urllib2_localnet.py | 1 +
|
|
|
b7e076 |
7 files changed, 112 insertions(+), 53 deletions(-)
|
|
|
b7e076 |
|
|
|
b7e076 |
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
|
|
|
3d909f |
index 66c0fed841..a43819904e 100644
|
|
|
b7e076 |
--- a/Lib/test/support/__init__.py
|
|
|
b7e076 |
+++ b/Lib/test/support/__init__.py
|
|
|
b7e076 |
@@ -11,6 +11,7 @@ import faulthandler
|
|
|
b7e076 |
import fnmatch
|
|
|
b7e076 |
import functools
|
|
|
b7e076 |
import gc
|
|
|
b7e076 |
+import hashlib
|
|
|
b7e076 |
import importlib
|
|
|
b7e076 |
import importlib.util
|
|
|
b7e076 |
import io
|
|
|
b7e076 |
@@ -627,6 +628,27 @@ def requires_mac_ver(*min_version):
|
|
|
b7e076 |
return wrapper
|
|
|
b7e076 |
return decorator
|
|
|
b7e076 |
|
|
|
b7e076 |
+def requires_hashdigest(digestname):
|
|
|
b7e076 |
+ """Decorator raising SkipTest if a hashing algorithm is not available
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+ The hashing algorithm could be missing or blocked by a strict crypto
|
|
|
b7e076 |
+ policy.
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+ ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS
|
|
|
b7e076 |
+ ValueError: unsupported hash type md4
|
|
|
b7e076 |
+ """
|
|
|
b7e076 |
+ def decorator(func):
|
|
|
b7e076 |
+ @functools.wraps(func)
|
|
|
b7e076 |
+ def wrapper(*args, **kwargs):
|
|
|
b7e076 |
+ try:
|
|
|
b7e076 |
+ hashlib.new(digestname)
|
|
|
b7e076 |
+ except ValueError:
|
|
|
b7e076 |
+ raise unittest.SkipTest(
|
|
|
b7e076 |
+ f"hash digest '{digestname}' is not available."
|
|
|
b7e076 |
+ )
|
|
|
b7e076 |
+ return func(*args, **kwargs)
|
|
|
b7e076 |
+ return wrapper
|
|
|
b7e076 |
+ return decorator
|
|
|
b7e076 |
|
|
|
b7e076 |
# Don't use "localhost", since resolving it uses the DNS under recent
|
|
|
b7e076 |
# Windows versions (see issue #18792).
|
|
|
b7e076 |
diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py
|
|
|
3d909f |
index 067e13f107..81c3485f76 100644
|
|
|
b7e076 |
--- a/Lib/test/test_hmac.py
|
|
|
b7e076 |
+++ b/Lib/test/test_hmac.py
|
|
|
b7e076 |
@@ -4,6 +4,8 @@ import hashlib
|
|
|
b7e076 |
import unittest
|
|
|
b7e076 |
import warnings
|
|
|
b7e076 |
|
|
|
b7e076 |
+from test.support import requires_hashdigest
|
|
|
b7e076 |
+
|
|
|
b7e076 |
|
|
|
b7e076 |
def ignore_warning(func):
|
|
|
b7e076 |
@functools.wraps(func)
|
|
|
b7e076 |
@@ -17,6 +19,7 @@ def ignore_warning(func):
|
|
|
b7e076 |
|
|
|
b7e076 |
class TestVectorsTestCase(unittest.TestCase):
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('md5')
|
|
|
b7e076 |
def test_md5_vectors(self):
|
|
|
b7e076 |
# Test the HMAC module against test vectors from the RFC.
|
|
|
b7e076 |
|
|
|
b7e076 |
@@ -63,6 +66,7 @@ class TestVectorsTestCase(unittest.TestCase):
|
|
|
b7e076 |
b"and Larger Than One Block-Size Data"),
|
|
|
b7e076 |
"6f630fad67cda0ee1fb1f562db3aa53e")
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('sha1')
|
|
|
b7e076 |
def test_sha_vectors(self):
|
|
|
b7e076 |
def shatest(key, data, digest):
|
|
|
b7e076 |
h = hmac.HMAC(key, data, digestmod=hashlib.sha1)
|
|
|
b7e076 |
@@ -230,23 +234,28 @@ class TestVectorsTestCase(unittest.TestCase):
|
|
|
b7e076 |
'134676fb6de0446065c97440fa8c6a58',
|
|
|
b7e076 |
})
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('sha224')
|
|
|
b7e076 |
def test_sha224_rfc4231(self):
|
|
|
b7e076 |
self._rfc4231_test_cases(hashlib.sha224, 'sha224', 28, 64)
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('sha256')
|
|
|
b7e076 |
def test_sha256_rfc4231(self):
|
|
|
b7e076 |
self._rfc4231_test_cases(hashlib.sha256, 'sha256', 32, 64)
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('sha384')
|
|
|
b7e076 |
def test_sha384_rfc4231(self):
|
|
|
b7e076 |
self._rfc4231_test_cases(hashlib.sha384, 'sha384', 48, 128)
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('sha512')
|
|
|
b7e076 |
def test_sha512_rfc4231(self):
|
|
|
b7e076 |
self._rfc4231_test_cases(hashlib.sha512, 'sha512', 64, 128)
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('sha256')
|
|
|
b7e076 |
def test_legacy_block_size_warnings(self):
|
|
|
b7e076 |
class MockCrazyHash(object):
|
|
|
b7e076 |
"""Ain't no block_size attribute here."""
|
|
|
b7e076 |
def __init__(self, *args):
|
|
|
b7e076 |
- self._x = hashlib.sha1(*args)
|
|
|
b7e076 |
+ self._x = hashlib.sha256(*args)
|
|
|
b7e076 |
self.digest_size = self._x.digest_size
|
|
|
b7e076 |
def update(self, v):
|
|
|
b7e076 |
self._x.update(v)
|
|
|
b7e076 |
@@ -273,76 +282,80 @@ class TestVectorsTestCase(unittest.TestCase):
|
|
|
b7e076 |
self.assertEqual(h.hexdigest().upper(), digest)
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
+
|
|
|
b7e076 |
class ConstructorTestCase(unittest.TestCase):
|
|
|
b7e076 |
|
|
|
b7e076 |
+ expected = (
|
|
|
b7e076 |
+ "6c845b47f52b3b47f6590c502db7825aad757bf4fadc8fa972f7cd2e76a5bdeb"
|
|
|
b7e076 |
+ )
|
|
|
b7e076 |
@ignore_warning
|
|
|
b7e076 |
+ @requires_hashdigest('sha256')
|
|
|
b7e076 |
def test_normal(self):
|
|
|
b7e076 |
# Standard constructor call.
|
|
|
b7e076 |
- failed = 0
|
|
|
b7e076 |
try:
|
|
|
b7e076 |
- h = hmac.HMAC(b"key")
|
|
|
b7e076 |
+ hmac.HMAC(b"key", digestmod='sha256')
|
|
|
b7e076 |
except Exception:
|
|
|
b7e076 |
self.fail("Standard constructor call raised exception.")
|
|
|
b7e076 |
|
|
|
b7e076 |
@ignore_warning
|
|
|
b7e076 |
+ @requires_hashdigest('sha256')
|
|
|
b7e076 |
def test_with_str_key(self):
|
|
|
b7e076 |
# Pass a key of type str, which is an error, because it expects a key
|
|
|
b7e076 |
# of type bytes
|
|
|
b7e076 |
with self.assertRaises(TypeError):
|
|
|
b7e076 |
- h = hmac.HMAC("key")
|
|
|
b7e076 |
+ h = hmac.HMAC("key", digestmod='sha256')
|
|
|
b7e076 |
|
|
|
b7e076 |
- @ignore_warning
|
|
|
b7e076 |
+ @requires_hashdigest('sha256')
|
|
|
b7e076 |
def test_dot_new_with_str_key(self):
|
|
|
b7e076 |
# Pass a key of type str, which is an error, because it expects a key
|
|
|
b7e076 |
# of type bytes
|
|
|
b7e076 |
with self.assertRaises(TypeError):
|
|
|
b7e076 |
- h = hmac.new("key")
|
|
|
b7e076 |
+ h = hmac.HMAC("key", digestmod='sha256')
|
|
|
b7e076 |
|
|
|
b7e076 |
@ignore_warning
|
|
|
b7e076 |
+ @requires_hashdigest('sha256')
|
|
|
b7e076 |
def test_withtext(self):
|
|
|
b7e076 |
# Constructor call with text.
|
|
|
b7e076 |
try:
|
|
|
b7e076 |
- h = hmac.HMAC(b"key", b"hash this!")
|
|
|
b7e076 |
+ h = hmac.HMAC(b"key", b"hash this!", digestmod='sha256')
|
|
|
b7e076 |
except Exception:
|
|
|
b7e076 |
self.fail("Constructor call with text argument raised exception.")
|
|
|
b7e076 |
- self.assertEqual(h.hexdigest(), '34325b639da4cfd95735b381e28cb864')
|
|
|
b7e076 |
+ self.assertEqual(h.hexdigest(), self.expected)
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('sha256')
|
|
|
b7e076 |
def test_with_bytearray(self):
|
|
|
b7e076 |
try:
|
|
|
b7e076 |
h = hmac.HMAC(bytearray(b"key"), bytearray(b"hash this!"),
|
|
|
b7e076 |
- digestmod="md5")
|
|
|
b7e076 |
+ digestmod="sha256")
|
|
|
b7e076 |
except Exception:
|
|
|
b7e076 |
self.fail("Constructor call with bytearray arguments raised exception.")
|
|
|
b7e076 |
- self.assertEqual(h.hexdigest(), '34325b639da4cfd95735b381e28cb864')
|
|
|
b7e076 |
+ self.assertEqual(h.hexdigest(), self.expected)
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('sha256')
|
|
|
b7e076 |
def test_with_memoryview_msg(self):
|
|
|
b7e076 |
try:
|
|
|
b7e076 |
- h = hmac.HMAC(b"key", memoryview(b"hash this!"), digestmod="md5")
|
|
|
b7e076 |
+ h = hmac.HMAC(b"key", memoryview(b"hash this!"), digestmod="sha256")
|
|
|
b7e076 |
except Exception:
|
|
|
b7e076 |
self.fail("Constructor call with memoryview msg raised exception.")
|
|
|
b7e076 |
- self.assertEqual(h.hexdigest(), '34325b639da4cfd95735b381e28cb864')
|
|
|
b7e076 |
+ self.assertEqual(h.hexdigest(), self.expected)
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('sha256')
|
|
|
b7e076 |
def test_withmodule(self):
|
|
|
b7e076 |
# Constructor call with text and digest module.
|
|
|
b7e076 |
try:
|
|
|
b7e076 |
- h = hmac.HMAC(b"key", b"", hashlib.sha1)
|
|
|
b7e076 |
+ h = hmac.HMAC(b"key", b"", hashlib.sha256)
|
|
|
b7e076 |
except Exception:
|
|
|
b7e076 |
- self.fail("Constructor call with hashlib.sha1 raised exception.")
|
|
|
b7e076 |
+ self.fail("Constructor call with hashlib.sha256 raised exception.")
|
|
|
b7e076 |
|
|
|
b7e076 |
-class SanityTestCase(unittest.TestCase):
|
|
|
b7e076 |
|
|
|
b7e076 |
- @ignore_warning
|
|
|
b7e076 |
- def test_default_is_md5(self):
|
|
|
b7e076 |
- # Testing if HMAC defaults to MD5 algorithm.
|
|
|
b7e076 |
- # NOTE: this whitebox test depends on the hmac class internals
|
|
|
b7e076 |
- h = hmac.HMAC(b"key")
|
|
|
b7e076 |
- self.assertEqual(h.digest_cons, hashlib.md5)
|
|
|
b7e076 |
+class SanityTestCase(unittest.TestCase):
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('sha256')
|
|
|
b7e076 |
def test_exercise_all_methods(self):
|
|
|
b7e076 |
# Exercising all methods once.
|
|
|
b7e076 |
# This must not raise any exceptions
|
|
|
b7e076 |
try:
|
|
|
b7e076 |
- h = hmac.HMAC(b"my secret key", digestmod="md5")
|
|
|
b7e076 |
+ h = hmac.HMAC(b"my secret key", digestmod="sha256")
|
|
|
b7e076 |
h.update(b"compute the hash of this text!")
|
|
|
b7e076 |
dig = h.digest()
|
|
|
b7e076 |
dig = h.hexdigest()
|
|
|
b7e076 |
@@ -350,11 +363,13 @@ class SanityTestCase(unittest.TestCase):
|
|
|
b7e076 |
except Exception:
|
|
|
b7e076 |
self.fail("Exception raised during normal usage of HMAC class.")
|
|
|
b7e076 |
|
|
|
b7e076 |
+
|
|
|
b7e076 |
class CopyTestCase(unittest.TestCase):
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('sha256')
|
|
|
b7e076 |
def test_attributes(self):
|
|
|
b7e076 |
# Testing if attributes are of same type.
|
|
|
b7e076 |
- h1 = hmac.HMAC(b"key", digestmod="md5")
|
|
|
b7e076 |
+ h1 = hmac.HMAC(b"key", digestmod="sha256")
|
|
|
b7e076 |
h2 = h1.copy()
|
|
|
b7e076 |
self.assertTrue(h1.digest_cons == h2.digest_cons,
|
|
|
b7e076 |
"digest constructors don't match.")
|
|
|
b7e076 |
@@ -363,9 +378,10 @@ class CopyTestCase(unittest.TestCase):
|
|
|
b7e076 |
self.assertEqual(type(h1.outer), type(h2.outer),
|
|
|
b7e076 |
"Types of outer don't match.")
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('sha256')
|
|
|
b7e076 |
def test_realcopy(self):
|
|
|
b7e076 |
# Testing if the copy method created a real copy.
|
|
|
b7e076 |
- h1 = hmac.HMAC(b"key", digestmod="md5")
|
|
|
b7e076 |
+ h1 = hmac.HMAC(b"key", digestmod="sha256")
|
|
|
b7e076 |
h2 = h1.copy()
|
|
|
b7e076 |
# Using id() in case somebody has overridden __eq__/__ne__.
|
|
|
b7e076 |
self.assertTrue(id(h1) != id(h2), "No real copy of the HMAC instance.")
|
|
|
b7e076 |
@@ -374,9 +390,10 @@ class CopyTestCase(unittest.TestCase):
|
|
|
b7e076 |
self.assertTrue(id(h1.outer) != id(h2.outer),
|
|
|
b7e076 |
"No real copy of the attribute 'outer'.")
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('sha256')
|
|
|
b7e076 |
def test_equality(self):
|
|
|
b7e076 |
# Testing if the copy has the same digests.
|
|
|
b7e076 |
- h1 = hmac.HMAC(b"key", digestmod="md5")
|
|
|
b7e076 |
+ h1 = hmac.HMAC(b"key", digestmod="sha256")
|
|
|
b7e076 |
h1.update(b"some random text")
|
|
|
b7e076 |
h2 = h1.copy()
|
|
|
b7e076 |
self.assertEqual(h1.digest(), h2.digest(),
|
|
|
b7e076 |
diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py
|
|
|
3d909f |
index 0593a3756b..086cc0ac4e 100644
|
|
|
b7e076 |
--- a/Lib/test/test_imaplib.py
|
|
|
b7e076 |
+++ b/Lib/test/test_imaplib.py
|
|
|
b7e076 |
@@ -14,7 +14,8 @@ import calendar
|
|
|
b7e076 |
import inspect
|
|
|
b7e076 |
|
|
|
b7e076 |
from test.support import (reap_threads, verbose, transient_internet,
|
|
|
b7e076 |
- run_with_tz, run_with_locale, cpython_only)
|
|
|
b7e076 |
+ run_with_tz, run_with_locale, cpython_only,
|
|
|
b7e076 |
+ requires_hashdigest)
|
|
|
b7e076 |
import unittest
|
|
|
b7e076 |
from unittest import mock
|
|
|
b7e076 |
from datetime import datetime, timezone, timedelta
|
|
|
b7e076 |
@@ -369,6 +370,7 @@ class NewIMAPTestsMixin():
|
|
|
b7e076 |
self.assertEqual(code, 'OK')
|
|
|
b7e076 |
self.assertEqual(server.response, b'ZmFrZQ==\r\n') # b64 encoded 'fake'
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('md5')
|
|
|
b7e076 |
def test_login_cram_md5_bytes(self):
|
|
|
b7e076 |
class AuthHandler(SimpleIMAPHandler):
|
|
|
b7e076 |
capabilities = 'LOGINDISABLED AUTH=CRAM-MD5'
|
|
|
b7e076 |
@@ -386,6 +388,7 @@ class NewIMAPTestsMixin():
|
|
|
b7e076 |
ret, _ = client.login_cram_md5("tim", b"tanstaaftanstaaf")
|
|
|
b7e076 |
self.assertEqual(ret, "OK")
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('md5')
|
|
|
b7e076 |
def test_login_cram_md5_plain_text(self):
|
|
|
b7e076 |
class AuthHandler(SimpleIMAPHandler):
|
|
|
b7e076 |
capabilities = 'LOGINDISABLED AUTH=CRAM-MD5'
|
|
|
b7e076 |
@@ -797,6 +800,7 @@ class ThreadedNetworkedTests(unittest.TestCase):
|
|
|
b7e076 |
b'ZmFrZQ==\r\n') # b64 encoded 'fake'
|
|
|
b7e076 |
|
|
|
b7e076 |
@reap_threads
|
|
|
b7e076 |
+ @requires_hashdigest('md5')
|
|
|
b7e076 |
def test_login_cram_md5(self):
|
|
|
b7e076 |
|
|
|
b7e076 |
class AuthHandler(SimpleIMAPHandler):
|
|
|
b7e076 |
diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py
|
|
|
3d909f |
index 234c855545..b8146be3a8 100644
|
|
|
b7e076 |
--- a/Lib/test/test_poplib.py
|
|
|
b7e076 |
+++ b/Lib/test/test_poplib.py
|
|
|
b7e076 |
@@ -304,9 +304,11 @@ class TestPOP3Class(TestCase):
|
|
|
b7e076 |
def test_rpop(self):
|
|
|
b7e076 |
self.assertOK(self.client.rpop('foo'))
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @test_support.requires_hashdigest('md5')
|
|
|
b7e076 |
def test_apop_normal(self):
|
|
|
b7e076 |
self.assertOK(self.client.apop('foo', 'dummypassword'))
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @test_support.requires_hashdigest('md5')
|
|
|
b7e076 |
def test_apop_REDOS(self):
|
|
|
b7e076 |
# Replace welcome with very long evil welcome.
|
|
|
b7e076 |
# NB The upper bound on welcome length is currently 2048.
|
|
|
b7e076 |
diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py
|
|
|
3d909f |
index 87047514e7..64b3201254 100644
|
|
|
b7e076 |
--- a/Lib/test/test_smtplib.py
|
|
|
b7e076 |
+++ b/Lib/test/test_smtplib.py
|
|
|
b7e076 |
@@ -4,6 +4,7 @@ import email.mime.text
|
|
|
b7e076 |
from email.message import EmailMessage
|
|
|
b7e076 |
from email.base64mime import body_encode as encode_base64
|
|
|
b7e076 |
import email.utils
|
|
|
b7e076 |
+import hashlib
|
|
|
b7e076 |
import hmac
|
|
|
b7e076 |
import socket
|
|
|
b7e076 |
import smtpd
|
|
|
b7e076 |
@@ -18,6 +19,7 @@ import textwrap
|
|
|
b7e076 |
|
|
|
b7e076 |
import unittest
|
|
|
b7e076 |
from test import support, mock_socket
|
|
|
b7e076 |
+from test.support import requires_hashdigest
|
|
|
b7e076 |
from unittest.mock import Mock
|
|
|
b7e076 |
|
|
|
b7e076 |
HOST = "localhost"
|
|
|
b7e076 |
@@ -968,6 +970,7 @@ class SMTPSimTests(unittest.TestCase):
|
|
|
b7e076 |
self.assertEqual(resp, (235, b'Authentication Succeeded'))
|
|
|
b7e076 |
smtp.close()
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @requires_hashdigest('md5')
|
|
|
b7e076 |
def testAUTH_CRAM_MD5(self):
|
|
|
b7e076 |
self.serv.add_feature("AUTH CRAM-MD5")
|
|
|
b7e076 |
smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15)
|
|
|
b7e076 |
@@ -984,7 +987,13 @@ class SMTPSimTests(unittest.TestCase):
|
|
|
b7e076 |
smtp.close()
|
|
|
b7e076 |
|
|
|
b7e076 |
def test_auth_function(self):
|
|
|
b7e076 |
- supported = {'CRAM-MD5', 'PLAIN', 'LOGIN'}
|
|
|
b7e076 |
+ supported = {'PLAIN', 'LOGIN'}
|
|
|
b7e076 |
+ try:
|
|
|
b7e076 |
+ hashlib.md5()
|
|
|
b7e076 |
+ except ValueError:
|
|
|
b7e076 |
+ pass
|
|
|
b7e076 |
+ else:
|
|
|
b7e076 |
+ supported.add('CRAM-MD5')
|
|
|
b7e076 |
for mechanism in supported:
|
|
|
b7e076 |
self.serv.add_feature("AUTH {}".format(mechanism))
|
|
|
b7e076 |
for mechanism in supported:
|
|
|
b7e076 |
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
|
|
|
3d909f |
index 4cd7d5370f..b5e855e0d7 100644
|
|
|
b7e076 |
--- a/Lib/test/test_tarfile.py
|
|
|
b7e076 |
+++ b/Lib/test/test_tarfile.py
|
|
|
b7e076 |
@@ -1,7 +1,7 @@
|
|
|
b7e076 |
import sys
|
|
|
b7e076 |
import os
|
|
|
b7e076 |
import io
|
|
|
b7e076 |
-from hashlib import md5
|
|
|
b7e076 |
+from hashlib import sha256
|
|
|
b7e076 |
from contextlib import contextmanager
|
|
|
b7e076 |
from random import Random
|
|
|
b7e076 |
import pathlib
|
|
|
b7e076 |
@@ -11,7 +11,7 @@ import unittest.mock
|
|
|
b7e076 |
import tarfile
|
|
|
b7e076 |
|
|
|
b7e076 |
from test import support
|
|
|
b7e076 |
-from test.support import script_helper
|
|
|
b7e076 |
+from test.support import script_helper, requires_hashdigest
|
|
|
b7e076 |
|
|
|
b7e076 |
# Check for our compression modules.
|
|
|
b7e076 |
try:
|
|
|
b7e076 |
@@ -27,8 +27,8 @@ try:
|
|
|
b7e076 |
except ImportError:
|
|
|
b7e076 |
lzma = None
|
|
|
b7e076 |
|
|
|
b7e076 |
-def md5sum(data):
|
|
|
b7e076 |
- return md5(data).hexdigest()
|
|
|
b7e076 |
+def sha256sum(data):
|
|
|
b7e076 |
+ return sha256(data).hexdigest()
|
|
|
b7e076 |
|
|
|
b7e076 |
TEMPDIR = os.path.abspath(support.TESTFN) + "-tardir"
|
|
|
b7e076 |
tarextdir = TEMPDIR + '-extract-test'
|
|
|
b7e076 |
@@ -39,8 +39,12 @@ xzname = os.path.join(TEMPDIR, "testtar.tar.xz")
|
|
|
b7e076 |
tmpname = os.path.join(TEMPDIR, "tmp.tar")
|
|
|
b7e076 |
dotlessname = os.path.join(TEMPDIR, "testtar")
|
|
|
b7e076 |
|
|
|
b7e076 |
-md5_regtype = "65f477c818ad9e15f7feab0c6d37742f"
|
|
|
b7e076 |
-md5_sparse = "a54fbc4ca4f4399a90e1b27164012fc6"
|
|
|
b7e076 |
+sha256_regtype = (
|
|
|
b7e076 |
+ "e09e4bc8b3c9d9177e77256353b36c159f5f040531bbd4b024a8f9b9196c71ce"
|
|
|
b7e076 |
+)
|
|
|
b7e076 |
+sha256_sparse = (
|
|
|
b7e076 |
+ "4f05a776071146756345ceee937b33fc5644f5a96b9780d1c7d6a32cdf164d7b"
|
|
|
b7e076 |
+)
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
class TarTest:
|
|
|
b7e076 |
@@ -95,7 +99,7 @@ class UstarReadTest(ReadTest, unittest.TestCase):
|
|
|
b7e076 |
data = fobj.read()
|
|
|
b7e076 |
self.assertEqual(len(data), tarinfo.size,
|
|
|
b7e076 |
"regular file extraction failed")
|
|
|
b7e076 |
- self.assertEqual(md5sum(data), md5_regtype,
|
|
|
b7e076 |
+ self.assertEqual(sha256sum(data), sha256_regtype,
|
|
|
b7e076 |
"regular file extraction failed")
|
|
|
b7e076 |
|
|
|
b7e076 |
def test_fileobj_readlines(self):
|
|
|
b7e076 |
@@ -180,7 +184,7 @@ class UstarReadTest(ReadTest, unittest.TestCase):
|
|
|
b7e076 |
with self.tar.extractfile("ustar/regtype") as fobj:
|
|
|
b7e076 |
fobj = io.TextIOWrapper(fobj)
|
|
|
b7e076 |
data = fobj.read().encode("iso8859-1")
|
|
|
b7e076 |
- self.assertEqual(md5sum(data), md5_regtype)
|
|
|
b7e076 |
+ self.assertEqual(sha256sum(data), sha256_regtype)
|
|
|
b7e076 |
try:
|
|
|
b7e076 |
fobj.seek(100)
|
|
|
b7e076 |
except AttributeError:
|
|
|
b7e076 |
@@ -546,13 +550,13 @@ class MiscReadTestBase(CommonReadTest):
|
|
|
b7e076 |
self.addCleanup(support.unlink, os.path.join(TEMPDIR, "ustar/lnktype"))
|
|
|
b7e076 |
with open(os.path.join(TEMPDIR, "ustar/lnktype"), "rb") as f:
|
|
|
b7e076 |
data = f.read()
|
|
|
b7e076 |
- self.assertEqual(md5sum(data), md5_regtype)
|
|
|
b7e076 |
+ self.assertEqual(sha256sum(data), sha256_regtype)
|
|
|
b7e076 |
|
|
|
b7e076 |
tar.extract("ustar/symtype", TEMPDIR)
|
|
|
b7e076 |
self.addCleanup(support.unlink, os.path.join(TEMPDIR, "ustar/symtype"))
|
|
|
b7e076 |
with open(os.path.join(TEMPDIR, "ustar/symtype"), "rb") as f:
|
|
|
b7e076 |
data = f.read()
|
|
|
b7e076 |
- self.assertEqual(md5sum(data), md5_regtype)
|
|
|
b7e076 |
+ self.assertEqual(sha256sum(data), sha256_regtype)
|
|
|
b7e076 |
|
|
|
b7e076 |
def test_extractall(self):
|
|
|
b7e076 |
# Test if extractall() correctly restores directory permissions
|
|
|
b7e076 |
@@ -687,7 +691,7 @@ class StreamReadTest(CommonReadTest, unittest.TestCase):
|
|
|
b7e076 |
data = fobj.read()
|
|
|
b7e076 |
self.assertEqual(len(data), tarinfo.size,
|
|
|
b7e076 |
"regular file extraction failed")
|
|
|
b7e076 |
- self.assertEqual(md5sum(data), md5_regtype,
|
|
|
b7e076 |
+ self.assertEqual(sha256sum(data), sha256_regtype,
|
|
|
b7e076 |
"regular file extraction failed")
|
|
|
b7e076 |
|
|
|
b7e076 |
def test_provoke_stream_error(self):
|
|
|
b7e076 |
@@ -799,8 +803,8 @@ class MemberReadTest(ReadTest, unittest.TestCase):
|
|
|
b7e076 |
def _test_member(self, tarinfo, chksum=None, **kwargs):
|
|
|
b7e076 |
if chksum is not None:
|
|
|
b7e076 |
with self.tar.extractfile(tarinfo) as f:
|
|
|
b7e076 |
- self.assertEqual(md5sum(f.read()), chksum,
|
|
|
b7e076 |
- "wrong md5sum for %s" % tarinfo.name)
|
|
|
b7e076 |
+ self.assertEqual(sha256sum(f.read()), chksum,
|
|
|
b7e076 |
+ "wrong sha256sum for %s" % tarinfo.name)
|
|
|
b7e076 |
|
|
|
b7e076 |
kwargs["mtime"] = 0o7606136617
|
|
|
b7e076 |
kwargs["uid"] = 1000
|
|
|
b7e076 |
@@ -815,11 +819,11 @@ class MemberReadTest(ReadTest, unittest.TestCase):
|
|
|
b7e076 |
|
|
|
b7e076 |
def test_find_regtype(self):
|
|
|
b7e076 |
tarinfo = self.tar.getmember("ustar/regtype")
|
|
|
b7e076 |
- self._test_member(tarinfo, size=7011, chksum=md5_regtype)
|
|
|
b7e076 |
+ self._test_member(tarinfo, size=7011, chksum=sha256_regtype)
|
|
|
b7e076 |
|
|
|
b7e076 |
def test_find_conttype(self):
|
|
|
b7e076 |
tarinfo = self.tar.getmember("ustar/conttype")
|
|
|
b7e076 |
- self._test_member(tarinfo, size=7011, chksum=md5_regtype)
|
|
|
b7e076 |
+ self._test_member(tarinfo, size=7011, chksum=sha256_regtype)
|
|
|
b7e076 |
|
|
|
b7e076 |
def test_find_dirtype(self):
|
|
|
b7e076 |
tarinfo = self.tar.getmember("ustar/dirtype")
|
|
|
b7e076 |
@@ -851,28 +855,28 @@ class MemberReadTest(ReadTest, unittest.TestCase):
|
|
|
b7e076 |
|
|
|
b7e076 |
def test_find_sparse(self):
|
|
|
b7e076 |
tarinfo = self.tar.getmember("ustar/sparse")
|
|
|
b7e076 |
- self._test_member(tarinfo, size=86016, chksum=md5_sparse)
|
|
|
b7e076 |
+ self._test_member(tarinfo, size=86016, chksum=sha256_sparse)
|
|
|
b7e076 |
|
|
|
b7e076 |
def test_find_gnusparse(self):
|
|
|
b7e076 |
tarinfo = self.tar.getmember("gnu/sparse")
|
|
|
b7e076 |
- self._test_member(tarinfo, size=86016, chksum=md5_sparse)
|
|
|
b7e076 |
+ self._test_member(tarinfo, size=86016, chksum=sha256_sparse)
|
|
|
b7e076 |
|
|
|
b7e076 |
def test_find_gnusparse_00(self):
|
|
|
b7e076 |
tarinfo = self.tar.getmember("gnu/sparse-0.0")
|
|
|
b7e076 |
- self._test_member(tarinfo, size=86016, chksum=md5_sparse)
|
|
|
b7e076 |
+ self._test_member(tarinfo, size=86016, chksum=sha256_sparse)
|
|
|
b7e076 |
|
|
|
b7e076 |
def test_find_gnusparse_01(self):
|
|
|
b7e076 |
tarinfo = self.tar.getmember("gnu/sparse-0.1")
|
|
|
b7e076 |
- self._test_member(tarinfo, size=86016, chksum=md5_sparse)
|
|
|
b7e076 |
+ self._test_member(tarinfo, size=86016, chksum=sha256_sparse)
|
|
|
b7e076 |
|
|
|
b7e076 |
def test_find_gnusparse_10(self):
|
|
|
b7e076 |
tarinfo = self.tar.getmember("gnu/sparse-1.0")
|
|
|
b7e076 |
- self._test_member(tarinfo, size=86016, chksum=md5_sparse)
|
|
|
b7e076 |
+ self._test_member(tarinfo, size=86016, chksum=sha256_sparse)
|
|
|
b7e076 |
|
|
|
b7e076 |
def test_find_umlauts(self):
|
|
|
b7e076 |
tarinfo = self.tar.getmember("ustar/umlauts-"
|
|
|
b7e076 |
"\xc4\xd6\xdc\xe4\xf6\xfc\xdf")
|
|
|
b7e076 |
- self._test_member(tarinfo, size=7011, chksum=md5_regtype)
|
|
|
b7e076 |
+ self._test_member(tarinfo, size=7011, chksum=sha256_regtype)
|
|
|
b7e076 |
|
|
|
b7e076 |
def test_find_ustar_longname(self):
|
|
|
b7e076 |
name = "ustar/" + "12345/" * 39 + "1234567/longname"
|
|
|
b7e076 |
@@ -880,7 +884,7 @@ class MemberReadTest(ReadTest, unittest.TestCase):
|
|
|
b7e076 |
|
|
|
b7e076 |
def test_find_regtype_oldv7(self):
|
|
|
b7e076 |
tarinfo = self.tar.getmember("misc/regtype-old-v7")
|
|
|
b7e076 |
- self._test_member(tarinfo, size=7011, chksum=md5_regtype)
|
|
|
b7e076 |
+ self._test_member(tarinfo, size=7011, chksum=sha256_regtype)
|
|
|
b7e076 |
|
|
|
b7e076 |
def test_find_pax_umlauts(self):
|
|
|
b7e076 |
self.tar.close()
|
|
|
b7e076 |
@@ -888,7 +892,7 @@ class MemberReadTest(ReadTest, unittest.TestCase):
|
|
|
b7e076 |
encoding="iso8859-1")
|
|
|
b7e076 |
tarinfo = self.tar.getmember("pax/umlauts-"
|
|
|
b7e076 |
"\xc4\xd6\xdc\xe4\xf6\xfc\xdf")
|
|
|
b7e076 |
- self._test_member(tarinfo, size=7011, chksum=md5_regtype)
|
|
|
b7e076 |
+ self._test_member(tarinfo, size=7011, chksum=sha256_regtype)
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
class LongnameTest:
|
|
|
b7e076 |
@@ -950,8 +954,8 @@ class GNUReadTest(LongnameTest, ReadTest, unittest.TestCase):
|
|
|
b7e076 |
filename = os.path.join(TEMPDIR, name)
|
|
|
b7e076 |
with open(filename, "rb") as fobj:
|
|
|
b7e076 |
data = fobj.read()
|
|
|
b7e076 |
- self.assertEqual(md5sum(data), md5_sparse,
|
|
|
b7e076 |
- "wrong md5sum for %s" % name)
|
|
|
b7e076 |
+ self.assertEqual(sha256sum(data), sha256_sparse,
|
|
|
b7e076 |
+ "wrong sha256sum for %s" % name)
|
|
|
b7e076 |
|
|
|
b7e076 |
if self._fs_supports_holes():
|
|
|
b7e076 |
s = os.stat(filename)
|
|
|
b7e076 |
@@ -2431,7 +2435,7 @@ class LinkEmulationTest(ReadTest, unittest.TestCase):
|
|
|
b7e076 |
self.tar.extract(name, TEMPDIR)
|
|
|
b7e076 |
with open(os.path.join(TEMPDIR, name), "rb") as f:
|
|
|
b7e076 |
data = f.read()
|
|
|
b7e076 |
- self.assertEqual(md5sum(data), md5_regtype)
|
|
|
b7e076 |
+ self.assertEqual(sha256sum(data), sha256_regtype)
|
|
|
b7e076 |
|
|
|
b7e076 |
# See issues #1578269, #8879, and #17689 for some history on these skips
|
|
|
b7e076 |
@unittest.skipIf(hasattr(os.path, "islink"),
|
|
|
b7e076 |
diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py
|
|
|
3d909f |
index ef0091c493..895f97cc09 100644
|
|
|
b7e076 |
--- a/Lib/test/test_urllib2_localnet.py
|
|
|
b7e076 |
+++ b/Lib/test/test_urllib2_localnet.py
|
|
|
b7e076 |
@@ -325,6 +325,7 @@ class ProxyAuthTests(unittest.TestCase):
|
|
|
b7e076 |
PASSWD = "test123"
|
|
|
b7e076 |
REALM = "TestRealm"
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @support.requires_hashdigest("md5")
|
|
|
b7e076 |
def setUp(self):
|
|
|
b7e076 |
super(ProxyAuthTests, self).setUp()
|
|
|
b7e076 |
# Ignore proxy bypass settings in the environment.
|
|
|
b7e076 |
--
|
|
|
3d909f |
2.25.1
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
From 75d9613294e1cbd5aab9363cf3c435871a25f065 Mon Sep 17 00:00:00 2001
|
|
|
b7e076 |
From: Christian Heimes <christian@python.org>
|
|
|
b7e076 |
Date: Mon, 30 Sep 2019 09:10:38 +0200
|
|
|
3d909f |
Subject: [PATCH 02/37] [3.8] bpo-38270: More fixes for strict crypto policy
|
|
|
b7e076 |
(GH-16418) (#16437)
|
|
|
b7e076 |
|
|
|
b7e076 |
test_hmac and test_hashlib test built-in hashing implementations and
|
|
|
b7e076 |
OpenSSL-based hashing implementations. Add more checks to skip OpenSSL
|
|
|
b7e076 |
implementations when a strict crypto policy is active.
|
|
|
b7e076 |
|
|
|
b7e076 |
Use EVP_DigestInit_ex() instead of EVP_DigestInit() to initialize the
|
|
|
b7e076 |
EVP context. The EVP_DigestInit() function clears alls flags and breaks
|
|
|
b7e076 |
usedforsecurity flag again.
|
|
|
b7e076 |
|
|
|
b7e076 |
Signed-off-by: Christian Heimes <christian@python.org>
|
|
|
b7e076 |
|
|
|
b7e076 |
https://bugs.python.org/issue38270.
|
|
|
b7e076 |
(cherry picked from commit 90558158093c0ad893102158fd3c2dd9f864e82e)
|
|
|
b7e076 |
|
|
|
b7e076 |
Co-authored-by: Christian Heimes <christian@python.org>
|
|
|
b7e076 |
---
|
|
|
b7e076 |
Lib/test/support/__init__.py | 19 ++++++++++++++++---
|
|
|
b7e076 |
Lib/test/test_hashlib.py | 3 +++
|
|
|
b7e076 |
Lib/test/test_hmac.py | 12 ++++++------
|
|
|
b7e076 |
3 files changed, 25 insertions(+), 9 deletions(-)
|
|
|
b7e076 |
|
|
|
b7e076 |
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
|
|
|
3d909f |
index a43819904e..3342218cf0 100644
|
|
|
b7e076 |
--- a/Lib/test/support/__init__.py
|
|
|
b7e076 |
+++ b/Lib/test/support/__init__.py
|
|
|
b7e076 |
@@ -71,6 +71,11 @@ try:
|
|
|
b7e076 |
except ImportError:
|
|
|
b7e076 |
resource = None
|
|
|
b7e076 |
|
|
|
b7e076 |
+try:
|
|
|
b7e076 |
+ import _hashlib
|
|
|
b7e076 |
+except ImportError:
|
|
|
b7e076 |
+ _hashlib = None
|
|
|
b7e076 |
+
|
|
|
b7e076 |
__all__ = [
|
|
|
b7e076 |
# globals
|
|
|
b7e076 |
"PIPE_MAX_SIZE", "verbose", "max_memuse", "use_resources", "failfast",
|
|
|
b7e076 |
@@ -88,7 +93,8 @@ __all__ = [
|
|
|
b7e076 |
"create_empty_file", "can_symlink", "fs_is_case_insensitive",
|
|
|
b7e076 |
# unittest
|
|
|
b7e076 |
"is_resource_enabled", "requires", "requires_freebsd_version",
|
|
|
b7e076 |
- "requires_linux_version", "requires_mac_ver", "check_syntax_error",
|
|
|
b7e076 |
+ "requires_linux_version", "requires_mac_ver", "requires_hashdigest",
|
|
|
b7e076 |
+ "check_syntax_error",
|
|
|
b7e076 |
"TransientResource", "time_out", "socket_peer_reset", "ioerror_peer_reset",
|
|
|
b7e076 |
"transient_internet", "BasicTestRunner", "run_unittest", "run_doctest",
|
|
|
b7e076 |
"skip_unless_symlink", "requires_gzip", "requires_bz2", "requires_lzma",
|
|
|
b7e076 |
@@ -628,12 +634,16 @@ def requires_mac_ver(*min_version):
|
|
|
b7e076 |
return wrapper
|
|
|
b7e076 |
return decorator
|
|
|
b7e076 |
|
|
|
b7e076 |
-def requires_hashdigest(digestname):
|
|
|
b7e076 |
+def requires_hashdigest(digestname, openssl=None):
|
|
|
b7e076 |
"""Decorator raising SkipTest if a hashing algorithm is not available
|
|
|
b7e076 |
|
|
|
b7e076 |
The hashing algorithm could be missing or blocked by a strict crypto
|
|
|
b7e076 |
policy.
|
|
|
b7e076 |
|
|
|
b7e076 |
+ If 'openssl' is True, then the decorator checks that OpenSSL provides
|
|
|
b7e076 |
+ the algorithm. Otherwise the check falls back to built-in
|
|
|
b7e076 |
+ implementations.
|
|
|
b7e076 |
+
|
|
|
b7e076 |
ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS
|
|
|
b7e076 |
ValueError: unsupported hash type md4
|
|
|
b7e076 |
"""
|
|
|
b7e076 |
@@ -641,7 +651,10 @@ def requires_hashdigest(digestname):
|
|
|
b7e076 |
@functools.wraps(func)
|
|
|
b7e076 |
def wrapper(*args, **kwargs):
|
|
|
b7e076 |
try:
|
|
|
b7e076 |
- hashlib.new(digestname)
|
|
|
b7e076 |
+ if openssl and _hashlib is not None:
|
|
|
b7e076 |
+ _hashlib.new(digestname)
|
|
|
b7e076 |
+ else:
|
|
|
b7e076 |
+ hashlib.new(digestname)
|
|
|
b7e076 |
except ValueError:
|
|
|
b7e076 |
raise unittest.SkipTest(
|
|
|
b7e076 |
f"hash digest '{digestname}' is not available."
|
|
|
b7e076 |
diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
|
|
|
3d909f |
index 9711856853..1b1b4d5411 100644
|
|
|
b7e076 |
--- a/Lib/test/test_hashlib.py
|
|
|
b7e076 |
+++ b/Lib/test/test_hashlib.py
|
|
|
b7e076 |
@@ -8,6 +8,7 @@
|
|
|
b7e076 |
|
|
|
b7e076 |
import array
|
|
|
b7e076 |
from binascii import unhexlify
|
|
|
b7e076 |
+import functools
|
|
|
b7e076 |
import hashlib
|
|
|
b7e076 |
import importlib
|
|
|
b7e076 |
import itertools
|
|
|
b7e076 |
@@ -21,6 +22,7 @@ import unittest
|
|
|
b7e076 |
import warnings
|
|
|
b7e076 |
from test import support
|
|
|
b7e076 |
from test.support import _4G, bigmemtest, import_fresh_module
|
|
|
b7e076 |
+from test.support import requires_hashdigest
|
|
|
b7e076 |
from http.client import HTTPException
|
|
|
b7e076 |
|
|
|
b7e076 |
# Were we compiled --with-pydebug or with #define Py_DEBUG?
|
|
|
b7e076 |
@@ -117,6 +119,7 @@ class HashLibTestCase(unittest.TestCase):
|
|
|
b7e076 |
constructors.add(_test_algorithm_via_hashlib_new)
|
|
|
b7e076 |
|
|
|
b7e076 |
_hashlib = self._conditional_import_module('_hashlib')
|
|
|
b7e076 |
+ self._hashlib = _hashlib
|
|
|
b7e076 |
if _hashlib:
|
|
|
b7e076 |
# These two algorithms should always be present when this module
|
|
|
b7e076 |
# is compiled. If not, something was compiled wrong.
|
|
|
b7e076 |
diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py
|
|
|
3d909f |
index 81c3485f76..2a5a0d3d06 100644
|
|
|
b7e076 |
--- a/Lib/test/test_hmac.py
|
|
|
b7e076 |
+++ b/Lib/test/test_hmac.py
|
|
|
b7e076 |
@@ -19,7 +19,7 @@ def ignore_warning(func):
|
|
|
b7e076 |
|
|
|
b7e076 |
class TestVectorsTestCase(unittest.TestCase):
|
|
|
b7e076 |
|
|
|
b7e076 |
- @requires_hashdigest('md5')
|
|
|
b7e076 |
+ @requires_hashdigest('md5', openssl=True)
|
|
|
b7e076 |
def test_md5_vectors(self):
|
|
|
b7e076 |
# Test the HMAC module against test vectors from the RFC.
|
|
|
b7e076 |
|
|
|
b7e076 |
@@ -66,7 +66,7 @@ class TestVectorsTestCase(unittest.TestCase):
|
|
|
b7e076 |
b"and Larger Than One Block-Size Data"),
|
|
|
b7e076 |
"6f630fad67cda0ee1fb1f562db3aa53e")
|
|
|
b7e076 |
|
|
|
b7e076 |
- @requires_hashdigest('sha1')
|
|
|
b7e076 |
+ @requires_hashdigest('sha1', openssl=True)
|
|
|
b7e076 |
def test_sha_vectors(self):
|
|
|
b7e076 |
def shatest(key, data, digest):
|
|
|
b7e076 |
h = hmac.HMAC(key, data, digestmod=hashlib.sha1)
|
|
|
b7e076 |
@@ -234,19 +234,19 @@ class TestVectorsTestCase(unittest.TestCase):
|
|
|
b7e076 |
'134676fb6de0446065c97440fa8c6a58',
|
|
|
b7e076 |
})
|
|
|
b7e076 |
|
|
|
b7e076 |
- @requires_hashdigest('sha224')
|
|
|
b7e076 |
+ @requires_hashdigest('sha224', openssl=True)
|
|
|
b7e076 |
def test_sha224_rfc4231(self):
|
|
|
b7e076 |
self._rfc4231_test_cases(hashlib.sha224, 'sha224', 28, 64)
|
|
|
b7e076 |
|
|
|
b7e076 |
- @requires_hashdigest('sha256')
|
|
|
b7e076 |
+ @requires_hashdigest('sha256', openssl=True)
|
|
|
b7e076 |
def test_sha256_rfc4231(self):
|
|
|
b7e076 |
self._rfc4231_test_cases(hashlib.sha256, 'sha256', 32, 64)
|
|
|
b7e076 |
|
|
|
b7e076 |
- @requires_hashdigest('sha384')
|
|
|
b7e076 |
+ @requires_hashdigest('sha384', openssl=True)
|
|
|
b7e076 |
def test_sha384_rfc4231(self):
|
|
|
b7e076 |
self._rfc4231_test_cases(hashlib.sha384, 'sha384', 48, 128)
|
|
|
b7e076 |
|
|
|
b7e076 |
- @requires_hashdigest('sha512')
|
|
|
b7e076 |
+ @requires_hashdigest('sha512', openssl=True)
|
|
|
b7e076 |
def test_sha512_rfc4231(self):
|
|
|
b7e076 |
self._rfc4231_test_cases(hashlib.sha512, 'sha512', 64, 128)
|
|
|
b7e076 |
|
|
|
b7e076 |
--
|
|
|
3d909f |
2.25.1
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
From 19a40f7e820bb991c03e03c05dc832539b676983 Mon Sep 17 00:00:00 2001
|
|
|
b7e076 |
From: stratakis <cstratak@redhat.com>
|
|
|
b7e076 |
Date: Tue, 3 Dec 2019 16:35:54 +0100
|
|
|
3d909f |
Subject: [PATCH 03/37] bpo-38270: Fix indentation of test_hmac assertions
|
|
|
b7e076 |
(GH-17446)
|
|
|
b7e076 |
|
|
|
b7e076 |
Since https://github.com/python/cpython/commit/c64a1a61e6fc542cada40eb069a239317e1af36e two assertions were indented and thus ignored when running test_hmac.
|
|
|
b7e076 |
|
|
|
b7e076 |
This PR fixes it. As the change is quite trivial I didn't add a NEWS entry.
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
https://bugs.python.org/issue38270
|
|
|
b7e076 |
---
|
|
|
b7e076 |
Lib/test/test_hmac.py | 4 ++--
|
|
|
b7e076 |
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
|
b7e076 |
|
|
|
b7e076 |
diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py
|
|
|
3d909f |
index 2a5a0d3d06..338e0215a4 100644
|
|
|
b7e076 |
--- a/Lib/test/test_hmac.py
|
|
|
b7e076 |
+++ b/Lib/test/test_hmac.py
|
|
|
b7e076 |
@@ -329,7 +329,7 @@ class ConstructorTestCase(unittest.TestCase):
|
|
|
b7e076 |
digestmod="sha256")
|
|
|
b7e076 |
except Exception:
|
|
|
b7e076 |
self.fail("Constructor call with bytearray arguments raised exception.")
|
|
|
b7e076 |
- self.assertEqual(h.hexdigest(), self.expected)
|
|
|
b7e076 |
+ self.assertEqual(h.hexdigest(), self.expected)
|
|
|
b7e076 |
|
|
|
b7e076 |
@requires_hashdigest('sha256')
|
|
|
b7e076 |
def test_with_memoryview_msg(self):
|
|
|
b7e076 |
@@ -337,7 +337,7 @@ class ConstructorTestCase(unittest.TestCase):
|
|
|
b7e076 |
h = hmac.HMAC(b"key", memoryview(b"hash this!"), digestmod="sha256")
|
|
|
b7e076 |
except Exception:
|
|
|
b7e076 |
self.fail("Constructor call with memoryview msg raised exception.")
|
|
|
b7e076 |
- self.assertEqual(h.hexdigest(), self.expected)
|
|
|
b7e076 |
+ self.assertEqual(h.hexdigest(), self.expected)
|
|
|
b7e076 |
|
|
|
b7e076 |
@requires_hashdigest('sha256')
|
|
|
b7e076 |
def test_withmodule(self):
|
|
|
b7e076 |
--
|
|
|
3d909f |
2.25.1
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
From 5fa96205b380f2cb555ac346e6b7039746cb51ca Mon Sep 17 00:00:00 2001
|
|
|
b7e076 |
From: Petr Viktorin <pviktori@redhat.com>
|
|
|
b7e076 |
Date: Thu, 25 Jul 2019 16:19:52 +0200
|
|
|
3d909f |
Subject: [PATCH 04/37] Expose OpenSSL FIPS_mode() as hashlib.get_fips_mode()
|
|
|
b7e076 |
|
|
|
b7e076 |
---
|
|
|
b7e076 |
Lib/hashlib.py | 5 +++++
|
|
|
b7e076 |
Modules/_hashopenssl.c | 36 +++++++++++++++++++++++++++++++++
|
|
|
b7e076 |
Modules/clinic/_hashopenssl.c.h | 25 ++++++++++++++++++++++-
|
|
|
b7e076 |
3 files changed, 65 insertions(+), 1 deletion(-)
|
|
|
b7e076 |
|
|
|
b7e076 |
diff --git a/Lib/hashlib.py b/Lib/hashlib.py
|
|
|
3d909f |
index 98d2d7981a..ae17c58511 100644
|
|
|
b7e076 |
--- a/Lib/hashlib.py
|
|
|
b7e076 |
+++ b/Lib/hashlib.py
|
|
|
b7e076 |
@@ -236,6 +236,11 @@ try:
|
|
|
b7e076 |
except ImportError:
|
|
|
b7e076 |
pass
|
|
|
b7e076 |
|
|
|
b7e076 |
+try:
|
|
|
b7e076 |
+ from _hashlib import get_fips_mode
|
|
|
b7e076 |
+except ImportError:
|
|
|
b7e076 |
+ pass
|
|
|
b7e076 |
+
|
|
|
b7e076 |
|
|
|
b7e076 |
for __func_name in __always_supported:
|
|
|
b7e076 |
# try them all, some may not work due to the OpenSSL
|
|
|
b7e076 |
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
|
|
|
3d909f |
index 84edd72c85..4876a7f7aa 100644
|
|
|
b7e076 |
--- a/Modules/_hashopenssl.c
|
|
|
b7e076 |
+++ b/Modules/_hashopenssl.c
|
|
|
b7e076 |
@@ -25,6 +25,9 @@
|
|
|
b7e076 |
#include <openssl/objects.h>
|
|
|
b7e076 |
#include "openssl/err.h"
|
|
|
b7e076 |
|
|
|
b7e076 |
+/* Expose FIPS_mode */
|
|
|
b7e076 |
+#include <openssl/crypto.h>
|
|
|
b7e076 |
+
|
|
|
b7e076 |
#include "clinic/_hashopenssl.c.h"
|
|
|
b7e076 |
/*[clinic input]
|
|
|
b7e076 |
module _hashlib
|
|
|
b7e076 |
@@ -987,6 +990,38 @@ GEN_CONSTRUCTOR(sha256)
|
|
|
b7e076 |
GEN_CONSTRUCTOR(sha384)
|
|
|
b7e076 |
GEN_CONSTRUCTOR(sha512)
|
|
|
b7e076 |
|
|
|
b7e076 |
+/*[clinic input]
|
|
|
b7e076 |
+_hashlib.get_fips_mode
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+Determine the OpenSSL FIPS mode of operation.
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+Effectively any non-zero return value indicates FIPS mode;
|
|
|
b7e076 |
+values other than 1 may have additional significance.
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+See OpenSSL documentation for the FIPS_mode() function for details.
|
|
|
b7e076 |
+[clinic start generated code]*/
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+static PyObject *
|
|
|
b7e076 |
+_hashlib_get_fips_mode_impl(PyObject *module)
|
|
|
b7e076 |
+/*[clinic end generated code: output=ad8a7793310d3f98 input=f42a2135df2a5e11]*/
|
|
|
b7e076 |
+{
|
|
|
b7e076 |
+ int result = FIPS_mode();
|
|
|
b7e076 |
+ if (result == 0) {
|
|
|
b7e076 |
+ // "If the library was built without support of the FIPS Object Module,
|
|
|
b7e076 |
+ // then the function will return 0 with an error code of
|
|
|
b7e076 |
+ // CRYPTO_R_FIPS_MODE_NOT_SUPPORTED (0x0f06d065)."
|
|
|
b7e076 |
+ // But 0 is also a valid result value.
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+ unsigned long errcode = ERR_peek_last_error();
|
|
|
b7e076 |
+ if (errcode) {
|
|
|
b7e076 |
+ _setException(PyExc_ValueError);
|
|
|
b7e076 |
+ return NULL;
|
|
|
b7e076 |
+ }
|
|
|
b7e076 |
+ }
|
|
|
b7e076 |
+ return PyLong_FromLong(result);
|
|
|
b7e076 |
+}
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+
|
|
|
b7e076 |
/* List of functions exported by this module */
|
|
|
b7e076 |
|
|
|
b7e076 |
static struct PyMethodDef EVP_functions[] = {
|
|
|
b7e076 |
@@ -996,6 +1031,7 @@ static struct PyMethodDef EVP_functions[] = {
|
|
|
b7e076 |
pbkdf2_hmac__doc__},
|
|
|
b7e076 |
#endif
|
|
|
b7e076 |
_HASHLIB_SCRYPT_METHODDEF
|
|
|
b7e076 |
+ _HASHLIB_GET_FIPS_MODE_METHODDEF
|
|
|
b7e076 |
CONSTRUCTOR_METH_DEF(md5),
|
|
|
b7e076 |
CONSTRUCTOR_METH_DEF(sha1),
|
|
|
b7e076 |
CONSTRUCTOR_METH_DEF(sha224),
|
|
|
b7e076 |
diff --git a/Modules/clinic/_hashopenssl.c.h b/Modules/clinic/_hashopenssl.c.h
|
|
|
3d909f |
index 0445352604..8828e2776e 100644
|
|
|
b7e076 |
--- a/Modules/clinic/_hashopenssl.c.h
|
|
|
b7e076 |
+++ b/Modules/clinic/_hashopenssl.c.h
|
|
|
b7e076 |
@@ -54,7 +54,30 @@ exit:
|
|
|
b7e076 |
|
|
|
b7e076 |
#endif /* (OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(OPENSSL_NO_SCRYPT) && !defined(LIBRESSL_VERSION_NUMBER)) */
|
|
|
b7e076 |
|
|
|
b7e076 |
+PyDoc_STRVAR(_hashlib_get_fips_mode__doc__,
|
|
|
b7e076 |
+"get_fips_mode($module, /)\n"
|
|
|
b7e076 |
+"--\n"
|
|
|
b7e076 |
+"\n"
|
|
|
b7e076 |
+"Determine the OpenSSL FIPS mode of operation.\n"
|
|
|
b7e076 |
+"\n"
|
|
|
b7e076 |
+"Effectively any non-zero return value indicates FIPS mode;\n"
|
|
|
b7e076 |
+"values other than 1 may have additional significance.\n"
|
|
|
b7e076 |
+"\n"
|
|
|
b7e076 |
+"See OpenSSL documentation for the FIPS_mode() function for details.");
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+#define _HASHLIB_GET_FIPS_MODE_METHODDEF \
|
|
|
b7e076 |
+ {"get_fips_mode", (PyCFunction)_hashlib_get_fips_mode, METH_NOARGS, _hashlib_get_fips_mode__doc__},
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+static PyObject *
|
|
|
b7e076 |
+_hashlib_get_fips_mode_impl(PyObject *module);
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+static PyObject *
|
|
|
b7e076 |
+_hashlib_get_fips_mode(PyObject *module, PyObject *Py_UNUSED(ignored))
|
|
|
b7e076 |
+{
|
|
|
b7e076 |
+ return _hashlib_get_fips_mode_impl(module);
|
|
|
b7e076 |
+}
|
|
|
b7e076 |
+
|
|
|
b7e076 |
#ifndef _HASHLIB_SCRYPT_METHODDEF
|
|
|
b7e076 |
#define _HASHLIB_SCRYPT_METHODDEF
|
|
|
b7e076 |
#endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */
|
|
|
b7e076 |
-/*[clinic end generated code: output=118cd7036fa0fb52 input=a9049054013a1b77]*/
|
|
|
b7e076 |
+/*[clinic end generated code: output=7d683c930bbb7c36 input=a9049054013a1b77]*/
|
|
|
b7e076 |
--
|
|
|
3d909f |
2.25.1
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
From e60cc93037b913ca2a410d73b52d8301ab0d76cd Mon Sep 17 00:00:00 2001
|
|
|
b7e076 |
From: Charalampos Stratakis <cstratak@redhat.com>
|
|
|
b7e076 |
Date: Thu, 25 Jul 2019 17:04:06 +0200
|
|
|
3d909f |
Subject: [PATCH 05/37] Use python's fall backs for the crypto it implements
|
|
|
b7e076 |
only if we are not in FIPS mode
|
|
|
b7e076 |
|
|
|
b7e076 |
---
|
|
|
b7e076 |
Lib/hashlib.py | 209 +++++++++++++++------------------------
|
|
|
b7e076 |
Lib/test/test_hashlib.py | 1 +
|
|
|
b7e076 |
2 files changed, 81 insertions(+), 129 deletions(-)
|
|
|
b7e076 |
|
|
|
b7e076 |
diff --git a/Lib/hashlib.py b/Lib/hashlib.py
|
|
|
3d909f |
index ae17c58511..7db1e02601 100644
|
|
|
b7e076 |
--- a/Lib/hashlib.py
|
|
|
b7e076 |
+++ b/Lib/hashlib.py
|
|
|
b7e076 |
@@ -67,56 +67,64 @@ algorithms_available = set(__always_supported)
|
|
|
b7e076 |
__all__ = __always_supported + ('new', 'algorithms_guaranteed',
|
|
|
b7e076 |
'algorithms_available', 'pbkdf2_hmac')
|
|
|
b7e076 |
|
|
|
b7e076 |
-
|
|
|
b7e076 |
-__builtin_constructor_cache = {}
|
|
|
b7e076 |
-
|
|
|
b7e076 |
-def __get_builtin_constructor(name):
|
|
|
b7e076 |
- cache = __builtin_constructor_cache
|
|
|
b7e076 |
- constructor = cache.get(name)
|
|
|
b7e076 |
- if constructor is not None:
|
|
|
b7e076 |
- return constructor
|
|
|
b7e076 |
- try:
|
|
|
b7e076 |
- if name in ('SHA1', 'sha1'):
|
|
|
b7e076 |
- import _sha1
|
|
|
b7e076 |
- cache['SHA1'] = cache['sha1'] = _sha1.sha1
|
|
|
b7e076 |
- elif name in ('MD5', 'md5'):
|
|
|
b7e076 |
- import _md5
|
|
|
b7e076 |
- cache['MD5'] = cache['md5'] = _md5.md5
|
|
|
b7e076 |
- elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'):
|
|
|
b7e076 |
- import _sha256
|
|
|
b7e076 |
- cache['SHA224'] = cache['sha224'] = _sha256.sha224
|
|
|
b7e076 |
- cache['SHA256'] = cache['sha256'] = _sha256.sha256
|
|
|
b7e076 |
- elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'):
|
|
|
b7e076 |
- import _sha512
|
|
|
b7e076 |
- cache['SHA384'] = cache['sha384'] = _sha512.sha384
|
|
|
b7e076 |
- cache['SHA512'] = cache['sha512'] = _sha512.sha512
|
|
|
b7e076 |
- elif name in ('blake2b', 'blake2s'):
|
|
|
b7e076 |
- import _blake2
|
|
|
b7e076 |
- cache['blake2b'] = _blake2.blake2b
|
|
|
b7e076 |
- cache['blake2s'] = _blake2.blake2s
|
|
|
b7e076 |
- elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
|
|
|
b7e076 |
- 'shake_128', 'shake_256'}:
|
|
|
b7e076 |
- import _sha3
|
|
|
b7e076 |
- cache['sha3_224'] = _sha3.sha3_224
|
|
|
b7e076 |
- cache['sha3_256'] = _sha3.sha3_256
|
|
|
b7e076 |
- cache['sha3_384'] = _sha3.sha3_384
|
|
|
b7e076 |
- cache['sha3_512'] = _sha3.sha3_512
|
|
|
b7e076 |
- cache['shake_128'] = _sha3.shake_128
|
|
|
b7e076 |
- cache['shake_256'] = _sha3.shake_256
|
|
|
b7e076 |
- except ImportError:
|
|
|
b7e076 |
- pass # no extension module, this hash is unsupported.
|
|
|
b7e076 |
-
|
|
|
b7e076 |
- constructor = cache.get(name)
|
|
|
b7e076 |
- if constructor is not None:
|
|
|
b7e076 |
- return constructor
|
|
|
b7e076 |
-
|
|
|
b7e076 |
- raise ValueError('unsupported hash type ' + name)
|
|
|
b7e076 |
+try:
|
|
|
b7e076 |
+ from _hashlib import get_fips_mode
|
|
|
b7e076 |
+except ImportError:
|
|
|
b7e076 |
+ def get_fips_mode():
|
|
|
b7e076 |
+ return 0
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+if not get_fips_mode():
|
|
|
b7e076 |
+ __builtin_constructor_cache = {}
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+ def __get_builtin_constructor(name):
|
|
|
b7e076 |
+ cache = __builtin_constructor_cache
|
|
|
b7e076 |
+ constructor = cache.get(name)
|
|
|
b7e076 |
+ if constructor is not None:
|
|
|
b7e076 |
+ return constructor
|
|
|
b7e076 |
+ try:
|
|
|
b7e076 |
+ if name in ('SHA1', 'sha1'):
|
|
|
b7e076 |
+ import _sha1
|
|
|
b7e076 |
+ cache['SHA1'] = cache['sha1'] = _sha1.sha1
|
|
|
b7e076 |
+ elif name in ('MD5', 'md5'):
|
|
|
b7e076 |
+ import _md5
|
|
|
b7e076 |
+ cache['MD5'] = cache['md5'] = _md5.md5
|
|
|
b7e076 |
+ elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'):
|
|
|
b7e076 |
+ import _sha256
|
|
|
b7e076 |
+ cache['SHA224'] = cache['sha224'] = _sha256.sha224
|
|
|
b7e076 |
+ cache['SHA256'] = cache['sha256'] = _sha256.sha256
|
|
|
b7e076 |
+ elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'):
|
|
|
b7e076 |
+ import _sha512
|
|
|
b7e076 |
+ cache['SHA384'] = cache['sha384'] = _sha512.sha384
|
|
|
b7e076 |
+ cache['SHA512'] = cache['sha512'] = _sha512.sha512
|
|
|
b7e076 |
+ elif name in ('blake2b', 'blake2s'):
|
|
|
b7e076 |
+ import _blake2
|
|
|
b7e076 |
+ cache['blake2b'] = _blake2.blake2b
|
|
|
b7e076 |
+ cache['blake2s'] = _blake2.blake2s
|
|
|
b7e076 |
+ elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
|
|
|
b7e076 |
+ 'shake_128', 'shake_256'}:
|
|
|
b7e076 |
+ import _sha3
|
|
|
b7e076 |
+ cache['sha3_224'] = _sha3.sha3_224
|
|
|
b7e076 |
+ cache['sha3_256'] = _sha3.sha3_256
|
|
|
b7e076 |
+ cache['sha3_384'] = _sha3.sha3_384
|
|
|
b7e076 |
+ cache['sha3_512'] = _sha3.sha3_512
|
|
|
b7e076 |
+ cache['shake_128'] = _sha3.shake_128
|
|
|
b7e076 |
+ cache['shake_256'] = _sha3.shake_256
|
|
|
b7e076 |
+ except ImportError:
|
|
|
b7e076 |
+ pass # no extension module, this hash is unsupported.
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+ constructor = cache.get(name)
|
|
|
b7e076 |
+ if constructor is not None:
|
|
|
b7e076 |
+ return constructor
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+ raise ValueError('unsupported hash type ' + name)
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
def __get_openssl_constructor(name):
|
|
|
b7e076 |
- if name in {'blake2b', 'blake2s'}:
|
|
|
b7e076 |
- # Prefer our blake2 implementation.
|
|
|
b7e076 |
- return __get_builtin_constructor(name)
|
|
|
b7e076 |
+ if not get_fips_mode():
|
|
|
b7e076 |
+ if name in {'blake2b', 'blake2s'}:
|
|
|
b7e076 |
+ # Prefer our blake2 implementation.
|
|
|
b7e076 |
+ return __get_builtin_constructor(name)
|
|
|
b7e076 |
try:
|
|
|
b7e076 |
f = getattr(_hashlib, 'openssl_' + name)
|
|
|
b7e076 |
# Allow the C module to raise ValueError. The function will be
|
|
|
b7e076 |
@@ -125,27 +133,30 @@ def __get_openssl_constructor(name):
|
|
|
b7e076 |
# Use the C function directly (very fast)
|
|
|
b7e076 |
return f
|
|
|
b7e076 |
except (AttributeError, ValueError):
|
|
|
b7e076 |
+ if get_fips_mode():
|
|
|
b7e076 |
+ raise
|
|
|
b7e076 |
return __get_builtin_constructor(name)
|
|
|
b7e076 |
|
|
|
b7e076 |
-
|
|
|
b7e076 |
-def __py_new(name, data=b'', **kwargs):
|
|
|
b7e076 |
- """new(name, data=b'', **kwargs) - Return a new hashing object using the
|
|
|
b7e076 |
- named algorithm; optionally initialized with data (which must be
|
|
|
b7e076 |
- a bytes-like object).
|
|
|
b7e076 |
- """
|
|
|
b7e076 |
- return __get_builtin_constructor(name)(data, **kwargs)
|
|
|
b7e076 |
+if not get_fips_mode():
|
|
|
b7e076 |
+ def __py_new(name, data=b'', **kwargs):
|
|
|
b7e076 |
+ """new(name, data=b'', **kwargs) - Return a new hashing object using the
|
|
|
b7e076 |
+ named algorithm; optionally initialized with data (which must be
|
|
|
b7e076 |
+ a bytes-like object).
|
|
|
b7e076 |
+ """
|
|
|
b7e076 |
+ return __get_builtin_constructor(name)(data, **kwargs)
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
def __hash_new(name, data=b'', **kwargs):
|
|
|
b7e076 |
"""new(name, data=b'') - Return a new hashing object using the named algorithm;
|
|
|
b7e076 |
optionally initialized with data (which must be a bytes-like object).
|
|
|
b7e076 |
"""
|
|
|
b7e076 |
- if name in {'blake2b', 'blake2s'}:
|
|
|
b7e076 |
- # Prefer our blake2 implementation.
|
|
|
b7e076 |
- # OpenSSL 1.1.0 comes with a limited implementation of blake2b/s.
|
|
|
b7e076 |
- # It does neither support keyed blake2 nor advanced features like
|
|
|
b7e076 |
- # salt, personal, tree hashing or SSE.
|
|
|
b7e076 |
- return __get_builtin_constructor(name)(data, **kwargs)
|
|
|
b7e076 |
+ if not get_fips_mode():
|
|
|
b7e076 |
+ if name in {'blake2b', 'blake2s'}:
|
|
|
b7e076 |
+ # Prefer our blake2 implementation.
|
|
|
b7e076 |
+ # OpenSSL 1.1.0 comes with a limited implementation of blake2b/s.
|
|
|
b7e076 |
+ # It does neither support keyed blake2 nor advanced features like
|
|
|
b7e076 |
+ # salt, personal, tree hashing or SSE.
|
|
|
b7e076 |
+ return __get_builtin_constructor(name)(data, **kwargs)
|
|
|
b7e076 |
try:
|
|
|
b7e076 |
return _hashlib.new(name, data)
|
|
|
b7e076 |
except ValueError:
|
|
|
b7e076 |
@@ -153,6 +164,8 @@ def __hash_new(name, data=b'', **kwargs):
|
|
|
b7e076 |
# hash, try using our builtin implementations.
|
|
|
b7e076 |
# This allows for SHA224/256 and SHA384/512 support even though
|
|
|
b7e076 |
# the OpenSSL library prior to 0.9.8 doesn't provide them.
|
|
|
b7e076 |
+ if get_fips_mode():
|
|
|
b7e076 |
+ raise
|
|
|
b7e076 |
return __get_builtin_constructor(name)(data)
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
@@ -163,72 +176,14 @@ try:
|
|
|
b7e076 |
algorithms_available = algorithms_available.union(
|
|
|
b7e076 |
_hashlib.openssl_md_meth_names)
|
|
|
b7e076 |
except ImportError:
|
|
|
b7e076 |
+ if get_fips_mode():
|
|
|
b7e076 |
+ raise
|
|
|
b7e076 |
new = __py_new
|
|
|
b7e076 |
__get_hash = __get_builtin_constructor
|
|
|
b7e076 |
|
|
|
b7e076 |
-try:
|
|
|
b7e076 |
- # OpenSSL's PKCS5_PBKDF2_HMAC requires OpenSSL 1.0+ with HMAC and SHA
|
|
|
b7e076 |
- from _hashlib import pbkdf2_hmac
|
|
|
b7e076 |
-except ImportError:
|
|
|
b7e076 |
- _trans_5C = bytes((x ^ 0x5C) for x in range(256))
|
|
|
b7e076 |
- _trans_36 = bytes((x ^ 0x36) for x in range(256))
|
|
|
b7e076 |
-
|
|
|
b7e076 |
- def pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None):
|
|
|
b7e076 |
- """Password based key derivation function 2 (PKCS #5 v2.0)
|
|
|
b7e076 |
|
|
|
b7e076 |
- This Python implementations based on the hmac module about as fast
|
|
|
b7e076 |
- as OpenSSL's PKCS5_PBKDF2_HMAC for short passwords and much faster
|
|
|
b7e076 |
- for long passwords.
|
|
|
b7e076 |
- """
|
|
|
b7e076 |
- if not isinstance(hash_name, str):
|
|
|
b7e076 |
- raise TypeError(hash_name)
|
|
|
b7e076 |
-
|
|
|
b7e076 |
- if not isinstance(password, (bytes, bytearray)):
|
|
|
b7e076 |
- password = bytes(memoryview(password))
|
|
|
b7e076 |
- if not isinstance(salt, (bytes, bytearray)):
|
|
|
b7e076 |
- salt = bytes(memoryview(salt))
|
|
|
b7e076 |
-
|
|
|
b7e076 |
- # Fast inline HMAC implementation
|
|
|
b7e076 |
- inner = new(hash_name)
|
|
|
b7e076 |
- outer = new(hash_name)
|
|
|
b7e076 |
- blocksize = getattr(inner, 'block_size', 64)
|
|
|
b7e076 |
- if len(password) > blocksize:
|
|
|
b7e076 |
- password = new(hash_name, password).digest()
|
|
|
b7e076 |
- password = password + b'\x00' * (blocksize - len(password))
|
|
|
b7e076 |
- inner.update(password.translate(_trans_36))
|
|
|
b7e076 |
- outer.update(password.translate(_trans_5C))
|
|
|
b7e076 |
-
|
|
|
b7e076 |
- def prf(msg, inner=inner, outer=outer):
|
|
|
b7e076 |
- # PBKDF2_HMAC uses the password as key. We can re-use the same
|
|
|
b7e076 |
- # digest objects and just update copies to skip initialization.
|
|
|
b7e076 |
- icpy = inner.copy()
|
|
|
b7e076 |
- ocpy = outer.copy()
|
|
|
b7e076 |
- icpy.update(msg)
|
|
|
b7e076 |
- ocpy.update(icpy.digest())
|
|
|
b7e076 |
- return ocpy.digest()
|
|
|
b7e076 |
-
|
|
|
b7e076 |
- if iterations < 1:
|
|
|
b7e076 |
- raise ValueError(iterations)
|
|
|
b7e076 |
- if dklen is None:
|
|
|
b7e076 |
- dklen = outer.digest_size
|
|
|
b7e076 |
- if dklen < 1:
|
|
|
b7e076 |
- raise ValueError(dklen)
|
|
|
b7e076 |
-
|
|
|
b7e076 |
- dkey = b''
|
|
|
b7e076 |
- loop = 1
|
|
|
b7e076 |
- from_bytes = int.from_bytes
|
|
|
b7e076 |
- while len(dkey) < dklen:
|
|
|
b7e076 |
- prev = prf(salt + loop.to_bytes(4, 'big'))
|
|
|
b7e076 |
- # endianess doesn't matter here as long to / from use the same
|
|
|
b7e076 |
- rkey = int.from_bytes(prev, 'big')
|
|
|
b7e076 |
- for i in range(iterations - 1):
|
|
|
b7e076 |
- prev = prf(prev)
|
|
|
b7e076 |
- # rkey = rkey ^ prev
|
|
|
b7e076 |
- rkey ^= from_bytes(prev, 'big')
|
|
|
b7e076 |
- loop += 1
|
|
|
b7e076 |
- dkey += rkey.to_bytes(inner.digest_size, 'big')
|
|
|
b7e076 |
-
|
|
|
b7e076 |
- return dkey[:dklen]
|
|
|
b7e076 |
+# OpenSSL's PKCS5_PBKDF2_HMAC requires OpenSSL 1.0+ with HMAC and SHA
|
|
|
b7e076 |
+from _hashlib import pbkdf2_hmac
|
|
|
b7e076 |
|
|
|
b7e076 |
try:
|
|
|
b7e076 |
# OpenSSL's scrypt requires OpenSSL 1.1+
|
|
|
b7e076 |
@@ -236,12 +191,6 @@ try:
|
|
|
b7e076 |
except ImportError:
|
|
|
b7e076 |
pass
|
|
|
b7e076 |
|
|
|
b7e076 |
-try:
|
|
|
b7e076 |
- from _hashlib import get_fips_mode
|
|
|
b7e076 |
-except ImportError:
|
|
|
b7e076 |
- pass
|
|
|
b7e076 |
-
|
|
|
b7e076 |
-
|
|
|
b7e076 |
for __func_name in __always_supported:
|
|
|
b7e076 |
# try them all, some may not work due to the OpenSSL
|
|
|
b7e076 |
# version not supporting that algorithm.
|
|
|
b7e076 |
@@ -254,4 +203,6 @@ for __func_name in __always_supported:
|
|
|
b7e076 |
|
|
|
b7e076 |
# Cleanup locals()
|
|
|
b7e076 |
del __always_supported, __func_name, __get_hash
|
|
|
b7e076 |
-del __py_new, __hash_new, __get_openssl_constructor
|
|
|
b7e076 |
+del __hash_new, __get_openssl_constructor
|
|
|
b7e076 |
+if not get_fips_mode():
|
|
|
b7e076 |
+ del __py_new
|
|
|
b7e076 |
diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
|
|
|
3d909f |
index 1b1b4d5411..4e6b5b607a 100644
|
|
|
b7e076 |
--- a/Lib/test/test_hashlib.py
|
|
|
b7e076 |
+++ b/Lib/test/test_hashlib.py
|
|
|
b7e076 |
@@ -933,6 +933,7 @@ class KDFTests(unittest.TestCase):
|
|
|
b7e076 |
iterations=1, dklen=None)
|
|
|
b7e076 |
self.assertEqual(out, self.pbkdf2_results['sha1'][0][0])
|
|
|
b7e076 |
|
|
|
b7e076 |
+ @unittest.skip("The python implementation of pbkdf2_hmac has been removed")
|
|
|
b7e076 |
def test_pbkdf2_hmac_py(self):
|
|
|
b7e076 |
self._test_pbkdf2_hmac(py_hashlib.pbkdf2_hmac)
|
|
|
b7e076 |
|
|
|
b7e076 |
--
|
|
|
3d909f |
2.25.1
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
From 4803386d980b9ad1a9bdde829e8642676acd8bf4 Mon Sep 17 00:00:00 2001
|
|
|
b7e076 |
From: Petr Viktorin <pviktori@redhat.com>
|
|
|
b7e076 |
Date: Thu, 25 Jul 2019 17:19:06 +0200
|
|
|
3d909f |
Subject: [PATCH 06/37] Disable Python's hash implementations in FIPS mode,
|
|
|
b7e076 |
forcing OpenSSL
|
|
|
b7e076 |
|
|
|
b7e076 |
---
|
|
|
b7e076 |
Include/_hashopenssl.h | 66 ++++++++++++++++++++++++++++++++++
|
|
|
b7e076 |
Modules/_blake2/blake2b_impl.c | 5 +++
|
|
|
b7e076 |
Modules/_blake2/blake2module.c | 3 ++
|
|
|
b7e076 |
Modules/_blake2/blake2s_impl.c | 5 +++
|
|
|
b7e076 |
Modules/_hashopenssl.c | 36 +------------------
|
|
|
b7e076 |
Modules/_sha3/sha3module.c | 5 +++
|
|
|
b7e076 |
setup.py | 31 ++++++++--------
|
|
|
b7e076 |
7 files changed, 101 insertions(+), 50 deletions(-)
|
|
|
b7e076 |
create mode 100644 Include/_hashopenssl.h
|
|
|
b7e076 |
|
|
|
b7e076 |
diff --git a/Include/_hashopenssl.h b/Include/_hashopenssl.h
|
|
|
b7e076 |
new file mode 100644
|
|
|
3d909f |
index 0000000000..a726c0d3fb
|
|
|
b7e076 |
--- /dev/null
|
|
|
b7e076 |
+++ b/Include/_hashopenssl.h
|
|
|
b7e076 |
@@ -0,0 +1,66 @@
|
|
|
b7e076 |
+#ifndef Py_HASHOPENSSL_H
|
|
|
b7e076 |
+#define Py_HASHOPENSSL_H
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+#include "Python.h"
|
|
|
b7e076 |
+#include <openssl/crypto.h>
|
|
|
b7e076 |
+#include <openssl/err.h>
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+/* LCOV_EXCL_START */
|
|
|
b7e076 |
+static PyObject *
|
|
|
b7e076 |
+_setException(PyObject *exc)
|
|
|
b7e076 |
+{
|
|
|
b7e076 |
+ unsigned long errcode;
|
|
|
b7e076 |
+ const char *lib, *func, *reason;
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+ errcode = ERR_peek_last_error();
|
|
|
b7e076 |
+ if (!errcode) {
|
|
|
b7e076 |
+ PyErr_SetString(exc, "unknown reasons");
|
|
|
b7e076 |
+ return NULL;
|
|
|
b7e076 |
+ }
|
|
|
b7e076 |
+ ERR_clear_error();
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+ lib = ERR_lib_error_string(errcode);
|
|
|
b7e076 |
+ func = ERR_func_error_string(errcode);
|
|
|
b7e076 |
+ reason = ERR_reason_error_string(errcode);
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+ if (lib && func) {
|
|
|
b7e076 |
+ PyErr_Format(exc, "[%s: %s] %s", lib, func, reason);
|
|
|
b7e076 |
+ }
|
|
|
b7e076 |
+ else if (lib) {
|
|
|
b7e076 |
+ PyErr_Format(exc, "[%s] %s", lib, reason);
|
|
|
b7e076 |
+ }
|
|
|
b7e076 |
+ else {
|
|
|
b7e076 |
+ PyErr_SetString(exc, reason);
|
|
|
b7e076 |
+ }
|
|
|
b7e076 |
+ return NULL;
|
|
|
b7e076 |
+}
|
|
|
b7e076 |
+/* LCOV_EXCL_STOP */
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+__attribute__((__unused__))
|
|
|
b7e076 |
+static int
|
|
|
b7e076 |
+_Py_hashlib_fips_error(char *name) {
|
|
|
b7e076 |
+ int result = FIPS_mode();
|
|
|
b7e076 |
+ if (result == 0) {
|
|
|
b7e076 |
+ // "If the library was built without support of the FIPS Object Module,
|
|
|
b7e076 |
+ // then the function will return 0 with an error code of
|
|
|
b7e076 |
+ // CRYPTO_R_FIPS_MODE_NOT_SUPPORTED (0x0f06d065)."
|
|
|
b7e076 |
+ // But 0 is also a valid result value.
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+ unsigned long errcode = ERR_peek_last_error();
|
|
|
b7e076 |
+ if (errcode) {
|
|
|
b7e076 |
+ _setException(PyExc_ValueError);
|
|
|
b7e076 |
+ return 1;
|
|
|
b7e076 |
+ }
|
|
|
b7e076 |
+ return 0;
|
|
|
b7e076 |
+ }
|
|
|
b7e076 |
+ PyErr_Format(PyExc_ValueError, "%s is not available in FIPS mode",
|
|
|
b7e076 |
+ name);
|
|
|
b7e076 |
+ return 1;
|
|
|
b7e076 |
+}
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+#define FAIL_RETURN_IN_FIPS_MODE(name) do { \
|
|
|
b7e076 |
+ if (_Py_hashlib_fips_error(name)) return NULL; \
|
|
|
b7e076 |
+} while (0)
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+#endif // !Py_HASHOPENSSL_H
|
|
|
b7e076 |
diff --git a/Modules/_blake2/blake2b_impl.c b/Modules/_blake2/blake2b_impl.c
|
|
|
3d909f |
index 418c018400..341e67a8fc 100644
|
|
|
b7e076 |
--- a/Modules/_blake2/blake2b_impl.c
|
|
|
b7e076 |
+++ b/Modules/_blake2/blake2b_impl.c
|
|
|
b7e076 |
@@ -14,6 +14,7 @@
|
|
|
b7e076 |
*/
|
|
|
b7e076 |
|
|
|
b7e076 |
#include "Python.h"
|
|
|
b7e076 |
+#include "_hashopenssl.h"
|
|
|
b7e076 |
#include "pystrhex.h"
|
|
|
b7e076 |
#ifdef WITH_THREAD
|
|
|
b7e076 |
#include "pythread.h"
|
|
|
b7e076 |
@@ -103,6 +104,8 @@ py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
|
|
|
b7e076 |
unsigned long leaf_size = 0;
|
|
|
b7e076 |
unsigned long long node_offset = 0;
|
|
|
b7e076 |
|
|
|
b7e076 |
+ FAIL_RETURN_IN_FIPS_MODE("_blake2");
|
|
|
b7e076 |
+
|
|
|
b7e076 |
self = new_BLAKE2bObject(type);
|
|
|
b7e076 |
if (self == NULL) {
|
|
|
b7e076 |
goto error;
|
|
|
b7e076 |
@@ -293,6 +296,8 @@ _blake2_blake2b_update(BLAKE2bObject *self, PyObject *data)
|
|
|
b7e076 |
{
|
|
|
b7e076 |
Py_buffer buf;
|
|
|
b7e076 |
|
|
|
b7e076 |
+ FAIL_RETURN_IN_FIPS_MODE("_blake2");
|
|
|
b7e076 |
+
|
|
|
b7e076 |
GET_BUFFER_VIEW_OR_ERROUT(data, &buf;;
|
|
|
b7e076 |
|
|
|
b7e076 |
#ifdef WITH_THREAD
|
|
|
b7e076 |
diff --git a/Modules/_blake2/blake2module.c b/Modules/_blake2/blake2module.c
|
|
|
3d909f |
index e2a3d420d4..817b716568 100644
|
|
|
b7e076 |
--- a/Modules/_blake2/blake2module.c
|
|
|
b7e076 |
+++ b/Modules/_blake2/blake2module.c
|
|
|
b7e076 |
@@ -9,6 +9,7 @@
|
|
|
b7e076 |
*/
|
|
|
b7e076 |
|
|
|
b7e076 |
#include "Python.h"
|
|
|
b7e076 |
+#include "_hashopenssl.h"
|
|
|
b7e076 |
|
|
|
b7e076 |
#include "impl/blake2.h"
|
|
|
b7e076 |
|
|
|
b7e076 |
@@ -57,6 +58,8 @@ PyInit__blake2(void)
|
|
|
b7e076 |
PyObject *m;
|
|
|
b7e076 |
PyObject *d;
|
|
|
b7e076 |
|
|
|
b7e076 |
+ FAIL_RETURN_IN_FIPS_MODE("blake2");
|
|
|
b7e076 |
+
|
|
|
b7e076 |
m = PyModule_Create(&blake2_module);
|
|
|
b7e076 |
if (m == NULL)
|
|
|
b7e076 |
return NULL;
|
|
|
b7e076 |
diff --git a/Modules/_blake2/blake2s_impl.c b/Modules/_blake2/blake2s_impl.c
|
|
|
3d909f |
index 24e529b659..0dfe0586b5 100644
|
|
|
b7e076 |
--- a/Modules/_blake2/blake2s_impl.c
|
|
|
b7e076 |
+++ b/Modules/_blake2/blake2s_impl.c
|
|
|
b7e076 |
@@ -14,6 +14,7 @@
|
|
|
b7e076 |
*/
|
|
|
b7e076 |
|
|
|
b7e076 |
#include "Python.h"
|
|
|
b7e076 |
+#include "_hashopenssl.h"
|
|
|
b7e076 |
#include "pystrhex.h"
|
|
|
b7e076 |
#ifdef WITH_THREAD
|
|
|
b7e076 |
#include "pythread.h"
|
|
|
b7e076 |
@@ -103,6 +104,8 @@ py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
|
|
|
b7e076 |
unsigned long leaf_size = 0;
|
|
|
b7e076 |
unsigned long long node_offset = 0;
|
|
|
b7e076 |
|
|
|
b7e076 |
+ FAIL_RETURN_IN_FIPS_MODE("_blake2");
|
|
|
b7e076 |
+
|
|
|
b7e076 |
self = new_BLAKE2sObject(type);
|
|
|
b7e076 |
if (self == NULL) {
|
|
|
b7e076 |
goto error;
|
|
|
b7e076 |
@@ -293,6 +296,8 @@ _blake2_blake2s_update(BLAKE2sObject *self, PyObject *data)
|
|
|
b7e076 |
{
|
|
|
b7e076 |
Py_buffer buf;
|
|
|
b7e076 |
|
|
|
b7e076 |
+ FAIL_RETURN_IN_FIPS_MODE("_blake2");
|
|
|
b7e076 |
+
|
|
|
b7e076 |
GET_BUFFER_VIEW_OR_ERROUT(data, &buf;;
|
|
|
b7e076 |
|
|
|
b7e076 |
#ifdef WITH_THREAD
|
|
|
b7e076 |
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
|
|
|
3d909f |
index 4876a7f7aa..02cf6087a2 100644
|
|
|
b7e076 |
--- a/Modules/_hashopenssl.c
|
|
|
b7e076 |
+++ b/Modules/_hashopenssl.c
|
|
|
b7e076 |
@@ -17,16 +17,13 @@
|
|
|
b7e076 |
#include "structmember.h"
|
|
|
b7e076 |
#include "hashlib.h"
|
|
|
b7e076 |
#include "pystrhex.h"
|
|
|
b7e076 |
+#include "_hashopenssl.h"
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
/* EVP is the preferred interface to hashing in OpenSSL */
|
|
|
b7e076 |
#include <openssl/evp.h>
|
|
|
b7e076 |
/* We use the object interface to discover what hashes OpenSSL supports. */
|
|
|
b7e076 |
#include <openssl/objects.h>
|
|
|
b7e076 |
-#include "openssl/err.h"
|
|
|
b7e076 |
-
|
|
|
b7e076 |
-/* Expose FIPS_mode */
|
|
|
b7e076 |
-#include <openssl/crypto.h>
|
|
|
b7e076 |
|
|
|
b7e076 |
#include "clinic/_hashopenssl.c.h"
|
|
|
b7e076 |
/*[clinic input]
|
|
|
b7e076 |
@@ -77,37 +74,6 @@ DEFINE_CONSTS_FOR_NEW(sha384)
|
|
|
b7e076 |
DEFINE_CONSTS_FOR_NEW(sha512)
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
-/* LCOV_EXCL_START */
|
|
|
b7e076 |
-static PyObject *
|
|
|
b7e076 |
-_setException(PyObject *exc)
|
|
|
b7e076 |
-{
|
|
|
b7e076 |
- unsigned long errcode;
|
|
|
b7e076 |
- const char *lib, *func, *reason;
|
|
|
b7e076 |
-
|
|
|
b7e076 |
- errcode = ERR_peek_last_error();
|
|
|
b7e076 |
- if (!errcode) {
|
|
|
b7e076 |
- PyErr_SetString(exc, "unknown reasons");
|
|
|
b7e076 |
- return NULL;
|
|
|
b7e076 |
- }
|
|
|
b7e076 |
- ERR_clear_error();
|
|
|
b7e076 |
-
|
|
|
b7e076 |
- lib = ERR_lib_error_string(errcode);
|
|
|
b7e076 |
- func = ERR_func_error_string(errcode);
|
|
|
b7e076 |
- reason = ERR_reason_error_string(errcode);
|
|
|
b7e076 |
-
|
|
|
b7e076 |
- if (lib && func) {
|
|
|
b7e076 |
- PyErr_Format(exc, "[%s: %s] %s", lib, func, reason);
|
|
|
b7e076 |
- }
|
|
|
b7e076 |
- else if (lib) {
|
|
|
b7e076 |
- PyErr_Format(exc, "[%s] %s", lib, reason);
|
|
|
b7e076 |
- }
|
|
|
b7e076 |
- else {
|
|
|
b7e076 |
- PyErr_SetString(exc, reason);
|
|
|
b7e076 |
- }
|
|
|
b7e076 |
- return NULL;
|
|
|
b7e076 |
-}
|
|
|
b7e076 |
-/* LCOV_EXCL_STOP */
|
|
|
b7e076 |
-
|
|
|
b7e076 |
static EVPobject *
|
|
|
b7e076 |
newEVPobject(PyObject *name)
|
|
|
b7e076 |
{
|
|
|
b7e076 |
diff --git a/Modules/_sha3/sha3module.c b/Modules/_sha3/sha3module.c
|
|
|
3d909f |
index 2c2b2dbc5c..624f7f247d 100644
|
|
|
b7e076 |
--- a/Modules/_sha3/sha3module.c
|
|
|
b7e076 |
+++ b/Modules/_sha3/sha3module.c
|
|
|
b7e076 |
@@ -18,6 +18,7 @@
|
|
|
b7e076 |
#include "Python.h"
|
|
|
b7e076 |
#include "pystrhex.h"
|
|
|
b7e076 |
#include "../hashlib.h"
|
|
|
b7e076 |
+#include "_hashopenssl.h"
|
|
|
b7e076 |
|
|
|
b7e076 |
/* **************************************************************************
|
|
|
b7e076 |
* SHA-3 (Keccak) and SHAKE
|
|
|
b7e076 |
@@ -162,6 +163,7 @@ static PyTypeObject SHAKE256type;
|
|
|
b7e076 |
static SHA3object *
|
|
|
b7e076 |
newSHA3object(PyTypeObject *type)
|
|
|
b7e076 |
{
|
|
|
b7e076 |
+ FAIL_RETURN_IN_FIPS_MODE("_sha3");
|
|
|
b7e076 |
SHA3object *newobj;
|
|
|
b7e076 |
newobj = (SHA3object *)PyObject_New(SHA3object, type);
|
|
|
b7e076 |
if (newobj == NULL) {
|
|
|
b7e076 |
@@ -177,6 +179,7 @@ newSHA3object(PyTypeObject *type)
|
|
|
b7e076 |
static PyObject *
|
|
|
b7e076 |
py_sha3_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
|
|
b7e076 |
{
|
|
|
b7e076 |
+ FAIL_RETURN_IN_FIPS_MODE("_sha3");
|
|
|
b7e076 |
SHA3object *self = NULL;
|
|
|
b7e076 |
Py_buffer buf = {NULL, NULL};
|
|
|
b7e076 |
HashReturn res;
|
|
|
b7e076 |
@@ -724,6 +727,8 @@ PyInit__sha3(void)
|
|
|
b7e076 |
{
|
|
|
b7e076 |
PyObject *m = NULL;
|
|
|
b7e076 |
|
|
|
b7e076 |
+ FAIL_RETURN_IN_FIPS_MODE("_sha3");
|
|
|
b7e076 |
+
|
|
|
b7e076 |
if ((m = PyModule_Create(&_SHA3module)) == NULL) {
|
|
|
b7e076 |
return NULL;
|
|
|
b7e076 |
}
|
|
|
b7e076 |
diff --git a/setup.py b/setup.py
|
|
|
3d909f |
index e2c1898253..e2e659ef79 100644
|
|
|
b7e076 |
--- a/setup.py
|
|
|
b7e076 |
+++ b/setup.py
|
|
|
b7e076 |
@@ -901,31 +901,30 @@ class PyBuildExt(build_ext):
|
|
|
b7e076 |
have_usable_openssl = (have_any_openssl and
|
|
|
b7e076 |
openssl_ver >= min_openssl_ver)
|
|
|
b7e076 |
|
|
|
b7e076 |
+ if not have_usable_openssl:
|
|
|
b7e076 |
+ raise ValueError('Cannot build for RHEL without OpenSSL')
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+ ssl_args = {
|
|
|
b7e076 |
+ 'include_dirs': ssl_incs,
|
|
|
b7e076 |
+ 'library_dirs': ssl_libs,
|
|
|
b7e076 |
+ 'libraries': ['ssl', 'crypto'],
|
|
|
b7e076 |
+ }
|
|
|
b7e076 |
+
|
|
|
b7e076 |
if have_any_openssl:
|
|
|
b7e076 |
if have_usable_openssl:
|
|
|
b7e076 |
# The _hashlib module wraps optimized implementations
|
|
|
b7e076 |
# of hash functions from the OpenSSL library.
|
|
|
b7e076 |
exts.append( Extension('_hashlib', ['_hashopenssl.c'],
|
|
|
b7e076 |
depends = ['hashlib.h'],
|
|
|
b7e076 |
- include_dirs = ssl_incs,
|
|
|
b7e076 |
- library_dirs = ssl_libs,
|
|
|
b7e076 |
- libraries = ['ssl', 'crypto']) )
|
|
|
b7e076 |
+ **ssl_args))
|
|
|
b7e076 |
else:
|
|
|
b7e076 |
print("warning: openssl 0x%08x is too old for _hashlib" %
|
|
|
b7e076 |
openssl_ver)
|
|
|
b7e076 |
missing.append('_hashlib')
|
|
|
b7e076 |
|
|
|
b7e076 |
- # We always compile these even when OpenSSL is available (issue #14693).
|
|
|
b7e076 |
- # It's harmless and the object code is tiny (40-50 KB per module,
|
|
|
b7e076 |
- # only loaded when actually used).
|
|
|
b7e076 |
- exts.append( Extension('_sha256', ['sha256module.c'],
|
|
|
b7e076 |
- depends=['hashlib.h']) )
|
|
|
b7e076 |
- exts.append( Extension('_sha512', ['sha512module.c'],
|
|
|
b7e076 |
- depends=['hashlib.h']) )
|
|
|
b7e076 |
- exts.append( Extension('_md5', ['md5module.c'],
|
|
|
b7e076 |
- depends=['hashlib.h']) )
|
|
|
b7e076 |
- exts.append( Extension('_sha1', ['sha1module.c'],
|
|
|
b7e076 |
- depends=['hashlib.h']) )
|
|
|
b7e076 |
+ # RHEL: Always force OpenSSL for md5, sha1, sha256, sha512;
|
|
|
b7e076 |
+ # don't build Python's implementations.
|
|
|
b7e076 |
+ # sha3 and blake2 have extra functionality, so do build those:
|
|
|
b7e076 |
|
|
|
b7e076 |
blake2_deps = glob(os.path.join(os.getcwd(), srcdir,
|
|
|
b7e076 |
'Modules/_blake2/impl/*'))
|
|
|
b7e076 |
@@ -944,6 +943,7 @@ class PyBuildExt(build_ext):
|
|
|
b7e076 |
'_blake2/blake2b_impl.c',
|
|
|
b7e076 |
'_blake2/blake2s_impl.c'],
|
|
|
b7e076 |
define_macros=blake2_macros,
|
|
|
b7e076 |
+ **ssl_args,
|
|
|
b7e076 |
depends=blake2_deps) )
|
|
|
b7e076 |
|
|
|
b7e076 |
sha3_deps = glob(os.path.join(os.getcwd(), srcdir,
|
|
|
b7e076 |
@@ -951,7 +951,8 @@ class PyBuildExt(build_ext):
|
|
|
b7e076 |
sha3_deps.append('hashlib.h')
|
|
|
b7e076 |
exts.append( Extension('_sha3',
|
|
|
b7e076 |
['_sha3/sha3module.c'],
|
|
|
b7e076 |
- depends=sha3_deps))
|
|
|
b7e076 |
+ **ssl_args,
|
|
|
b7e076 |
+ depends=sha3_deps + ['hashlib.h']))
|
|
|
b7e076 |
|
|
|
b7e076 |
# Modules that provide persistent dictionary-like semantics. You will
|
|
|
b7e076 |
# probably want to arrange for at least one of them to be available on
|
|
|
b7e076 |
--
|
|
|
3d909f |
2.25.1
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
From 0f35f480e2134c7d5c4ea3d68d8c0af14f56afa3 Mon Sep 17 00:00:00 2001
|
|
|
b7e076 |
From: Petr Viktorin <pviktori@redhat.com>
|
|
|
b7e076 |
Date: Thu, 25 Jul 2019 17:35:27 +0200
|
|
|
3d909f |
Subject: [PATCH 07/37] Expose all hashes available to OpenSSL, using a list
|
|
|
b7e076 |
|
|
|
b7e076 |
---
|
|
|
b7e076 |
Modules/_hashopenssl.c | 44 ++++++++++++++-----------------------
|
|
|
b7e076 |
Modules/_hashopenssl_list.h | 21 ++++++++++++++++++
|
|
|
b7e076 |
2 files changed, 37 insertions(+), 28 deletions(-)
|
|
|
b7e076 |
create mode 100644 Modules/_hashopenssl_list.h
|
|
|
b7e076 |
|
|
|
b7e076 |
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
|
|
|
3d909f |
index 02cf6087a2..7dfd70822b 100644
|
|
|
b7e076 |
--- a/Modules/_hashopenssl.c
|
|
|
b7e076 |
+++ b/Modules/_hashopenssl.c
|
|
|
b7e076 |
@@ -66,12 +66,9 @@ static PyTypeObject EVPtype;
|
|
|
b7e076 |
static PyObject *CONST_ ## Name ## _name_obj = NULL; \
|
|
|
b7e076 |
static EVP_MD_CTX *CONST_new_ ## Name ## _ctx_p = NULL;
|
|
|
b7e076 |
|
|
|
b7e076 |
-DEFINE_CONSTS_FOR_NEW(md5)
|
|
|
b7e076 |
-DEFINE_CONSTS_FOR_NEW(sha1)
|
|
|
b7e076 |
-DEFINE_CONSTS_FOR_NEW(sha224)
|
|
|
b7e076 |
-DEFINE_CONSTS_FOR_NEW(sha256)
|
|
|
b7e076 |
-DEFINE_CONSTS_FOR_NEW(sha384)
|
|
|
b7e076 |
-DEFINE_CONSTS_FOR_NEW(sha512)
|
|
|
b7e076 |
+#define _HASH(py_name, openssl_name) DEFINE_CONSTS_FOR_NEW(py_name)
|
|
|
b7e076 |
+#include "_hashopenssl_list.h"
|
|
|
b7e076 |
+#undef _HASH
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
static EVPobject *
|
|
|
b7e076 |
@@ -896,7 +893,7 @@ generate_hash_name_list(void)
|
|
|
b7e076 |
* The first call will lazy-initialize, which reports an exception
|
|
|
b7e076 |
* if initialization fails.
|
|
|
b7e076 |
*/
|
|
|
b7e076 |
-#define GEN_CONSTRUCTOR(NAME) \
|
|
|
b7e076 |
+#define GEN_CONSTRUCTOR(NAME, SSL_NAME) \
|
|
|
b7e076 |
static PyObject * \
|
|
|
b7e076 |
EVP_new_ ## NAME (PyObject *self, PyObject *args) \
|
|
|
b7e076 |
{ \
|
|
|
b7e076 |
@@ -910,8 +907,8 @@ generate_hash_name_list(void)
|
|
|
b7e076 |
\
|
|
|
b7e076 |
if (CONST_new_ ## NAME ## _ctx_p == NULL) { \
|
|
|
b7e076 |
EVP_MD_CTX *ctx_p = EVP_MD_CTX_new(); \
|
|
|
b7e076 |
- if (!EVP_get_digestbyname(#NAME) || \
|
|
|
b7e076 |
- !EVP_DigestInit(ctx_p, EVP_get_digestbyname(#NAME))) { \
|
|
|
b7e076 |
+ if (!EVP_get_digestbyname(SSL_NAME) || \
|
|
|
b7e076 |
+ !EVP_DigestInit(ctx_p, EVP_get_digestbyname(SSL_NAME))) { \
|
|
|
b7e076 |
_setException(PyExc_ValueError); \
|
|
|
b7e076 |
EVP_MD_CTX_free(ctx_p); \
|
|
|
b7e076 |
return NULL; \
|
|
|
b7e076 |
@@ -939,7 +936,7 @@ generate_hash_name_list(void)
|
|
|
b7e076 |
{"openssl_" #NAME, (PyCFunction)EVP_new_ ## NAME, METH_VARARGS, \
|
|
|
b7e076 |
PyDoc_STR("Returns a " #NAME \
|
|
|
b7e076 |
" hash object; optionally initialized with a string") \
|
|
|
b7e076 |
- }
|
|
|
b7e076 |
+ },
|
|
|
b7e076 |
|
|
|
b7e076 |
/* used in the init function to setup a constructor: initialize OpenSSL
|
|
|
b7e076 |
constructor constants if they haven't been initialized already. */
|
|
|
b7e076 |
@@ -949,12 +946,9 @@ generate_hash_name_list(void)
|
|
|
b7e076 |
} \
|
|
|
b7e076 |
} while (0);
|
|
|
b7e076 |
|
|
|
b7e076 |
-GEN_CONSTRUCTOR(md5)
|
|
|
b7e076 |
-GEN_CONSTRUCTOR(sha1)
|
|
|
b7e076 |
-GEN_CONSTRUCTOR(sha224)
|
|
|
b7e076 |
-GEN_CONSTRUCTOR(sha256)
|
|
|
b7e076 |
-GEN_CONSTRUCTOR(sha384)
|
|
|
b7e076 |
-GEN_CONSTRUCTOR(sha512)
|
|
|
b7e076 |
+#define _HASH(py_name, openssl_name) GEN_CONSTRUCTOR(py_name, openssl_name)
|
|
|
b7e076 |
+#include "_hashopenssl_list.h"
|
|
|
b7e076 |
+#undef _HASH
|
|
|
b7e076 |
|
|
|
b7e076 |
/*[clinic input]
|
|
|
b7e076 |
_hashlib.get_fips_mode
|
|
|
b7e076 |
@@ -998,12 +992,9 @@ static struct PyMethodDef EVP_functions[] = {
|
|
|
b7e076 |
#endif
|
|
|
b7e076 |
_HASHLIB_SCRYPT_METHODDEF
|
|
|
b7e076 |
_HASHLIB_GET_FIPS_MODE_METHODDEF
|
|
|
b7e076 |
- CONSTRUCTOR_METH_DEF(md5),
|
|
|
b7e076 |
- CONSTRUCTOR_METH_DEF(sha1),
|
|
|
b7e076 |
- CONSTRUCTOR_METH_DEF(sha224),
|
|
|
b7e076 |
- CONSTRUCTOR_METH_DEF(sha256),
|
|
|
b7e076 |
- CONSTRUCTOR_METH_DEF(sha384),
|
|
|
b7e076 |
- CONSTRUCTOR_METH_DEF(sha512),
|
|
|
b7e076 |
+#define _HASH(py_name, openssl_name) CONSTRUCTOR_METH_DEF(py_name)
|
|
|
b7e076 |
+#include "_hashopenssl_list.h"
|
|
|
b7e076 |
+#undef _HASH
|
|
|
b7e076 |
{NULL, NULL} /* Sentinel */
|
|
|
b7e076 |
};
|
|
|
b7e076 |
|
|
|
b7e076 |
@@ -1061,11 +1052,8 @@ PyInit__hashlib(void)
|
|
|
b7e076 |
PyModule_AddObject(m, "HASH", (PyObject *)&EVPtype);
|
|
|
b7e076 |
|
|
|
b7e076 |
/* these constants are used by the convenience constructors */
|
|
|
b7e076 |
- INIT_CONSTRUCTOR_CONSTANTS(md5);
|
|
|
b7e076 |
- INIT_CONSTRUCTOR_CONSTANTS(sha1);
|
|
|
b7e076 |
- INIT_CONSTRUCTOR_CONSTANTS(sha224);
|
|
|
b7e076 |
- INIT_CONSTRUCTOR_CONSTANTS(sha256);
|
|
|
b7e076 |
- INIT_CONSTRUCTOR_CONSTANTS(sha384);
|
|
|
b7e076 |
- INIT_CONSTRUCTOR_CONSTANTS(sha512);
|
|
|
b7e076 |
+#define _HASH(py_name, openssl_name) INIT_CONSTRUCTOR_CONSTANTS(py_name)
|
|
|
b7e076 |
+#include "_hashopenssl_list.h"
|
|
|
b7e076 |
+#undef _HASH
|
|
|
b7e076 |
return m;
|
|
|
b7e076 |
}
|
|
|
b7e076 |
diff --git a/Modules/_hashopenssl_list.h b/Modules/_hashopenssl_list.h
|
|
|
b7e076 |
new file mode 100644
|
|
|
3d909f |
index 0000000000..3c11b2eb6c
|
|
|
b7e076 |
--- /dev/null
|
|
|
b7e076 |
+++ b/Modules/_hashopenssl_list.h
|
|
|
b7e076 |
@@ -0,0 +1,21 @@
|
|
|
b7e076 |
+/* Call the _HASH macro with all the hashes exported by OpenSSL,
|
|
|
b7e076 |
+ * at compile time.
|
|
|
b7e076 |
+ *
|
|
|
b7e076 |
+ * This file is meant to be included multiple times, with different values of
|
|
|
b7e076 |
+ * _HASH.
|
|
|
b7e076 |
+ */
|
|
|
b7e076 |
+
|
|
|
b7e076 |
+_HASH(md5, "md5")
|
|
|
b7e076 |
+_HASH(sha1, "sha1")
|
|
|
b7e076 |
+_HASH(sha224, "sha224")
|
|
|
b7e076 |
+_HASH(sha256, "sha256")
|
|
|
b7e076 |
+_HASH(sha384, "sha384")
|
|
|
b7e076 |
+_HASH(sha512, "sha512")
|
|
|
b7e076 |
+_HASH(blake2b, "blake2b512")
|
|
|
b7e076 |
+_HASH(blake2s, "blake2s256")
|
|
|
b7e076 |
+_HASH(sha3_224, "sha3-224")
|
|
|
b7e076 |
+_HASH(sha3_256, "sha3-256")
|
|
|
b7e076 |
+_HASH(sha3_384, "sha3-384")
|
|
|
b7e076 |
+_HASH(sha3_512, "sha3-512")
|
|
|
b7e076 |
+_HASH(shake_128, "shake128")
|
|
|
b7e076 |
+_HASH(shake_256, "shake256")
|
|
|
b7e076 |
--
|
|
|
3d909f |
2.25.1
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
From 7e5b74b7268e4fb7d473d24cd023493e4e87eb76 Mon Sep 17 00:00:00 2001
|
|
|
b7e076 |
From: Petr Viktorin <pviktori@redhat.com>
|
|
|
b7e076 |
Date: Thu, 25 Jul 2019 18:13:45 +0200
|
|
|
3d909f |
Subject: [PATCH 08/37] Fix tests
|
|
|
b7e076 |
|
|
|
b7e076 |
---
|
|
|
b7e076 |
Lib/hashlib.py | 5 +++-
|
|
|
b7e076 |
Lib/test/test_hashlib.py | 58 +++++++++++++++++++++++++++++++---------
|
|
|
b7e076 |
2 files changed, 49 insertions(+), 14 deletions(-)
|
|
|
b7e076 |
|
|
|
b7e076 |
diff --git a/Lib/hashlib.py b/Lib/hashlib.py
|
|
|
3d909f |
index 7db1e02601..2def0a310c 100644
|
|
|
b7e076 |
--- a/Lib/hashlib.py
|
|
|
b7e076 |
+++ b/Lib/hashlib.py
|
|
|
b7e076 |
@@ -122,7 +122,10 @@ if not get_fips_mode():
|
|
|
b7e076 |
|
|
|
b7e076 |
def __get_openssl_constructor(name):
|
|
|
b7e076 |
if not get_fips_mode():
|
|
|
b7e076 |
- if name in {'blake2b', 'blake2s'}:
|
|
|
b7e076 |
+ if name in {
|
|
|
b7e076 |
+ 'blake2b', 'blake2s', 'shake_256', 'shake_128',
|
|
|
b7e076 |
+ #'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
|
|
|
b7e076 |
+ }:
|
|
|
b7e076 |
# Prefer our blake2 implementation.
|
|
|
b7e076 |
return __get_builtin_constructor(name)
|
|
|
b7e076 |
try:
|
|
|
b7e076 |
diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
|
|
|
3d909f |
index 4e6b5b607a..e57c93b42f 100644
|
|
|
b7e076 |
--- a/Lib/test/test_hashlib.py
|
|
|
b7e076 |
+++ b/Lib/test/test_hashlib.py
|
|
|
b7e076 |
@@ -182,7 +182,9 @@ class HashLibTestCase(unittest.TestCase):
|
|
|
b7e076 |
a = array.array("b", range(10))
|
|
|
b7e076 |
for cons in self.hash_constructors:
|
|
|
b7e076 |
c = cons(a)
|
|
|
b7e076 |
- if c.name in self.shakes:
|
|
|
b7e076 |
+ if (c.name in self.shakes
|
|
|
b7e076 |
+ and not cons.__name__.startswith('openssl_')
|
|
|
b7e076 |
+ ):
|
|
|
b7e076 |
c.hexdigest(16)
|
|
|
b7e076 |
else:
|
|
|
b7e076 |
c.hexdigest()
|
|
|
b7e076 |
@@ -229,7 +231,9 @@ class HashLibTestCase(unittest.TestCase):
|
|
|
b7e076 |
def test_hexdigest(self):
|
|
|
b7e076 |
for cons in self.hash_constructors:
|
|
|
b7e076 |
h = cons()
|
|
|
b7e076 |
- if h.name in self.shakes:
|
|
|
b7e076 |
+ if (h.name in self.shakes
|
|
|
b7e076 |
+ and not cons.__name__.startswith('openssl_')
|
|
|
b7e076 |
+ ):
|
|
|
b7e076 |
self.assertIsInstance(h.digest(16), bytes)
|
|
|
b7e076 |
self.assertEqual(hexstr(h.digest(16)), h.hexdigest(16))
|
|
|
b7e076 |
else:
|
|
|
b7e076 |
@@ -243,6 +247,8 @@ class HashLibTestCase(unittest.TestCase):
|
|
|
b7e076 |
h = cons()
|
|
|
b7e076 |
if h.name not in self.shakes:
|
|
|
b7e076 |
continue
|
|
|
b7e076 |
+ if cons.__name__.startswith('openssl_'):
|
|
|
b7e076 |
+ continue
|
|
|
b7e076 |
for digest in h.digest, h.hexdigest:
|
|
|
b7e076 |
with self.assertRaises((ValueError, OverflowError)):
|
|
|
b7e076 |
digest(-10)
|
|
|
b7e076 |
@@ -272,7 +278,9 @@ class HashLibTestCase(unittest.TestCase):
|
|
|
b7e076 |
m1.update(bees)
|
|
|
b7e076 |
m1.update(cees)
|
|
|
b7e076 |
m1.update(dees)
|
|
|
b7e076 |
- if m1.name in self.shakes:
|
|
|
b7e076 |
+ if (m1.name in self.shakes
|
|
|
b7e076 |
+ and not cons.__name__.startswith('openssl_')
|
|
|
b7e076 |
+ ):
|
|
|
b7e076 |
args = (16,)
|
|
|
b7e076 |
else:
|
|
|
b7e076 |
args = ()
|
|
|
b7e076 |
@@ -299,15 +307,36 @@ class HashLibTestCase(unittest.TestCase):
|
|
|
b7e076 |
# 2 is for hashlib.name(...) and hashlib.new(name, ...)
|
|
|
b7e076 |
self.assertGreaterEqual(len(constructors), 2)
|
|
|
b7e076 |
for hash_object_constructor in constructors:
|
|
|
b7e076 |
+ if (
|
|
|
b7e076 |
+ kwargs
|
|
|
b7e076 |
+ and hash_object_constructor.__name__.startswith('openssl_')
|
|
|
b7e076 |
+ ):
|
|
|
b7e076 |
+ return
|
|
|
b7e076 |
m = hash_object_constructor(data, **kwargs)
|
|
|
b7e076 |
- computed = m.hexdigest() if not shake else m.hexdigest(length)
|
|
|
b7e076 |
+ if shake:
|
|
|
b7e076 |
+ if hash_object_constructor.__name__.startswith('openssl_'):
|
|
|
b7e076 |
+ if length > m.digest_size:
|
|
|
b7e076 |
+ # OpenSSL doesn't give long digests
|
|
|
b7e076 |
+ return
|
|
|
b7e076 |
+ computed = m.hexdigest()[:length*2]
|
|
|
b7e076 |
+ hexdigest = hexdigest[:length*2]
|
|
|
b7e076 |
+ else:
|
|
|
b7e076 |
+ computed = m.hexdigest(length)
|
|
|
b7e076 |
+ else:
|
|
|
b7e076 |
+ computed = m.hexdigest()
|
|
|
b7e076 |
self.assertEqual(
|
|
|
b7e076 |
computed, hexdigest,
|
|
|
b7e076 |
"Hash algorithm %s constructed using %s returned hexdigest"
|
|
|
b7e076 |
" %r for %d byte input data that should have hashed to %r."
|
|
|
b7e076 |
% (name, hash_object_constructor,
|
|
|
b7e076 |
computed, len(data), hexdigest))
|
|
|
b7e076 |
- computed = m.digest() if not shake else m.digest(length)
|
|
|
b7e076 |
+ if shake:
|
|
|
b7e076 |
+ if hash_object_constructor.__name__.startswith('openssl_'):
|
|
|
b7e076 |
+ computed = m.digest()[:length]
|
|
|
b7e076 |
+ else:
|
|
|
b7e076 |
+ computed = m.digest(length)
|
|
|
b7e076 |
+ else:
|
|
|
b7e076 |
+ computed = m.digest()
|
|
|
b7e076 |
digest = bytes.fromhex(hexdigest)
|
|
|
b7e076 |
self.assertEqual(computed, digest)
|
|
|
b7e076 |
if not shake:
|
|
|
b7e076 |
@@ -347,12 +376,14 @@ class HashLibTestCase(unittest.TestCase):
|
|
|
b7e076 |
for hash_object_constructor in constructors:
|
|
|
b7e076 |
m = hash_object_constructor()
|
|
|
b7e076 |
self.assertEqual(m.block_size, block_size)
|
|
|
b7e076 |
- self.assertEqual(m.digest_size, digest_size)
|
|
|
b7e076 |
+ if not hash_object_constructor.__name__.startswith('openssl_'):
|
|
|
b7e076 |
+ self.assertEqual(m.digest_size, digest_size)
|
|
|
b7e076 |
if digest_length:
|
|
|
b7e076 |
- self.assertEqual(len(m.digest(digest_length)),
|
|
|
b7e076 |
- digest_length)
|
|
|
b7e076 |
- self.assertEqual(len(m.hexdigest(digest_length)),
|
|
|
b7e076 |
- 2*digest_length)
|
|
|
b7e076 |
+ if not hash_object_constructor.__name__.startswith('openssl_'):
|
|
|
b7e076 |
+ self.assertEqual(len(m.digest(digest_length)),
|
|
|
b7e076 |
+ digest_length)
|
|
|
b7e076 |
+ self.assertEqual(len(m.hexdigest(digest_length)),
|
|
|
b7e076 |
+ 2*digest_length)
|
|
|
b7e076 |
else:
|
|
|
b7e076 |
self.assertEqual(len(m.digest()), digest_size)
|
|
|
b7e076 |
self.assertEqual(len(m.hexdigest()), 2*digest_size)
|
|
|
b7e076 |
@@ -382,9 +413,10 @@ class HashLibTestCase(unittest.TestCase):
|
|
|
b7e076 |
for hash_object_constructor in constructors:
|
|
|
b7e076 |
m = hash_object_constructor()
|
|
|
b7e076 |
self.assertEqual(capacity + rate, 1600)
|
|
|
b7e076 |
- self.assertEqual(m._capacity_bits, capacity)
|
|
|
b7e076 |
- self.assertEqual(m._rate_bits, rate)
|
|
|
b7e076 |
- self.assertEqual(m._suffix, suffix)
|
|
|
b7e076 |
+ if not hash_object_constructor.__name__.startswith('openssl_'):
|
|
|
b7e076 |
+ self.assertEqual(m._capacity_bits, capacity)
|
|
|
b7e076 |
+ self.assertEqual(m._rate_bits, rate)
|
|
|
b7e076 |
+ self.assertEqual(m._suffix, suffix)
|
|
|
b7e076 |
|
|
|
b7e076 |
@requires_sha3
|
|
|
b7e076 |
def test_extra_sha3(self):
|
|
|
b7e076 |
--
|
|
|
3d909f |
2.25.1
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
From d6618795dd079acd8585f830b129d7f2fc9a6c52 Mon Sep 17 00:00:00 2001
|
|
|
b7e076 |
From: Petr Viktorin <pviktori@redhat.com>
|
|
|
b7e076 |
Date: Fri, 26 Jul 2019 11:27:57 +0200
|
|
|
3d909f |
Subject: [PATCH 09/37] Change FIPS exceptions from _blake2, _sha3 module init
|
|
|
b7e076 |
to ImportError
|
|
|
b7e076 |
|
|
|
b7e076 |
---
|
|
|
b7e076 |
Include/_hashopenssl.h | 11 +++++------
|
|
|
b7e076 |
Modules/_blake2/blake2b_impl.c | 4 ++--
|
|
|
b7e076 |
Modules/_blake2/blake2module.c | 2 +-
|
|
|
b7e076 |
Modules/_blake2/blake2s_impl.c | 4 ++--
|
|
|
b7e076 |
Modules/_sha3/sha3module.c | 6 +++---
|
|
|
b7e076 |
5 files changed, 13 insertions(+), 14 deletions(-)
|
|
|
b7e076 |
|
|
|
b7e076 |
diff --git a/Include/_hashopenssl.h b/Include/_hashopenssl.h
|
|
|
3d909f |
index a726c0d3fb..47ed003042 100644
|
|
|
b7e076 |
--- a/Include/_hashopenssl.h
|
|
|
b7e076 |
+++ b/Include/_hashopenssl.h
|
|
|
b7e076 |
@@ -39,7 +39,7 @@ _setException(PyObject *exc)
|
|
|
b7e076 |
|
|
|
b7e076 |
__attribute__((__unused__))
|
|
|
b7e076 |
static int
|
|
|
b7e076 |
-_Py_hashlib_fips_error(char *name) {
|
|
|
b7e076 |
+_Py_hashlib_fips_error(PyObject *exc, char *name) {
|
|
|
b7e076 |
int result = FIPS_mode();
|
|
|
b7e076 |
if (result == 0) {
|
|
|
b7e076 |
// "If the library was built without support of the FIPS Object Module,
|
|
|
b7e076 |
@@ -49,18 +49,17 @@ _Py_hashlib_fips_error(char *name) {
|
|
|
b7e076 |
|
|
|
b7e076 |
unsigned long errcode = ERR_peek_last_error();
|
|
|
b7e076 |
if (errcode) {
|
|
|
b7e076 |
- _setException(PyExc_ValueError);
|
|
|
b7e076 |
+ _setException(exc);
|
|
|
b7e076 |
return 1;
|
|
|
b7e076 |
}
|
|
|
b7e076 |
return 0;
|
|
|
b7e076 |
}
|
|
|
b7e076 |
- PyErr_Format(PyExc_ValueError, "%s is not available in FIPS mode",
|
|
|
b7e076 |
- name);
|
|
|
b7e076 |
+ PyErr_Format(exc, "%s is not available in FIPS mode", name);
|
|
|
b7e076 |
return 1;
|
|
|
b7e076 |
}
|
|
|
b7e076 |
|
|
|
b7e076 |
-#define FAIL_RETURN_IN_FIPS_MODE(name) do { \
|
|
|
b7e076 |
- if (_Py_hashlib_fips_error(name)) return NULL; \
|
|
|
b7e076 |
+#define FAIL_RETURN_IN_FIPS_MODE(exc, name) do { \
|
|
|
b7e076 |
+ if (_Py_hashlib_fips_error(exc, name)) return NULL; \
|
|
|
b7e076 |
} while (0)
|
|
|
b7e076 |
|
|
|
b7e076 |
#endif // !Py_HASHOPENSSL_H
|
|
|
b7e076 |
diff --git a/Modules/_blake2/blake2b_impl.c b/Modules/_blake2/blake2b_impl.c
|
|
|
3d909f |
index 341e67a8fc..f6bfce823b 100644
|
|
|
b7e076 |
--- a/Modules/_blake2/blake2b_impl.c
|
|
|
b7e076 |
+++ b/Modules/_blake2/blake2b_impl.c
|
|
|
b7e076 |
@@ -104,7 +104,7 @@ py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
|
|
|
b7e076 |
unsigned long leaf_size = 0;
|
|
|
b7e076 |
unsigned long long node_offset = 0;
|
|
|
b7e076 |
|
|
|
b7e076 |
- FAIL_RETURN_IN_FIPS_MODE("_blake2");
|
|
|
b7e076 |
+ FAIL_RETURN_IN_FIPS_MODE(PyExc_ValueError, "_blake2");
|
|
|
b7e076 |
|
|
|
b7e076 |
self = new_BLAKE2bObject(type);
|
|
|
b7e076 |
if (self == NULL) {
|
|
|
b7e076 |
@@ -296,7 +296,7 @@ _blake2_blake2b_update(BLAKE2bObject *self, PyObject *data)
|
|
|
b7e076 |
{
|
|
|
b7e076 |
Py_buffer buf;
|
|
|
b7e076 |
|
|
|
b7e076 |
- FAIL_RETURN_IN_FIPS_MODE("_blake2");
|
|
|
b7e076 |
+ FAIL_RETURN_IN_FIPS_MODE(PyExc_ValueError, "_blake2");
|
|
|
b7e076 |
|
|
|
b7e076 |
GET_BUFFER_VIEW_OR_ERROUT(data, &buf;;
|
|
|
b7e076 |
|
|
|
b7e076 |
diff --git a/Modules/_blake2/blake2module.c b/Modules/_blake2/blake2module.c
|
|
|
3d909f |
index 817b716568..a9c7cbc7eb 100644
|
|
|
b7e076 |
--- a/Modules/_blake2/blake2module.c
|
|
|
b7e076 |
+++ b/Modules/_blake2/blake2module.c
|
|
|
b7e076 |
@@ -58,7 +58,7 @@ PyInit__blake2(void)
|
|
|
b7e076 |
PyObject *m;
|
|
|
b7e076 |
PyObject *d;
|
|
|
b7e076 |
|
|
|
b7e076 |
- FAIL_RETURN_IN_FIPS_MODE("blake2");
|
|
|
b7e076 |
+ FAIL_RETURN_IN_FIPS_MODE(PyExc_ImportError, "blake2");
|
|
|
b7e076 |
|
|
|
b7e076 |
m = PyModule_Create(&blake2_module);
|
|
|
b7e076 |
if (m == NULL)
|
|
|
b7e076 |
diff --git a/Modules/_blake2/blake2s_impl.c b/Modules/_blake2/blake2s_impl.c
|
|
|
3d909f |
index 0dfe0586b5..28ae5b6510 100644
|
|
|
b7e076 |
--- a/Modules/_blake2/blake2s_impl.c
|
|
|
b7e076 |
+++ b/Modules/_blake2/blake2s_impl.c
|
|
|
b7e076 |
@@ -104,7 +104,7 @@ py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
|
|
|
b7e076 |
unsigned long leaf_size = 0;
|
|
|
b7e076 |
unsigned long long node_offset = 0;
|
|
|
b7e076 |
|
|
|
b7e076 |
- FAIL_RETURN_IN_FIPS_MODE("_blake2");
|
|
|
b7e076 |
+ FAIL_RETURN_IN_FIPS_MODE(PyExc_ValueError, "_blake2");
|
|
|
b7e076 |
|
|
|
b7e076 |
self = new_BLAKE2sObject(type);
|
|
|
b7e076 |
if (self == NULL) {
|
|
|
b7e076 |
@@ -296,7 +296,7 @@ _blake2_blake2s_update(BLAKE2sObject *self, PyObject *data)
|
|
|
b7e076 |
{
|
|
|
b7e076 |
Py_buffer buf;
|
|
|
b7e076 |
|
|
|
b7e076 |
- FAIL_RETURN_IN_FIPS_MODE("_blake2");
|
|
|
b7e076 |
+ FAIL_RETURN_IN_FIPS_MODE(PyExc_ValueError, "_blake2");
|
|
|
b7e076 |
|
|
|
b7e076 |
GET_BUFFER_VIEW_OR_ERROUT(data, &buf;;
|
|
|
b7e076 |
|
|
|
b7e076 |
diff --git a/Modules/_sha3/sha3module.c b/Modules/_sha3/sha3module.c
|
|
|
3d909f |
index 624f7f247d..2783a75644 100644
|
|
|
b7e076 |
--- a/Modules/_sha3/sha3module.c
|
|
|
b7e076 |
+++ b/Modules/_sha3/sha3module.c
|
|
|
b7e076 |
@@ -163,7 +163,7 @@ static PyTypeObject SHAKE256type;
|
|
|
b7e076 |
static SHA3object *
|
|
|
b7e076 |
newSHA3object(PyTypeObject *type)
|
|
|
b7e076 |
{
|
|
|
b7e076 |
- FAIL_RETURN_IN_FIPS_MODE("_sha3");
|
|
|
b7e076 |
+ FAIL_RETURN_IN_FIPS_MODE(PyExc_ValueError, "_sha3");
|
|
|
b7e076 |
SHA3object *newobj;
|
|
|
b7e076 |
newobj = (SHA3object *)PyObject_New(SHA3object, type);
|
|
|
b7e076 |
if (newobj == NULL) {
|
|
|
b7e076 |
@@ -179,7 +179,7 @@ newSHA3object(PyTypeObject *type)
|
|
|
b7e076 |
static PyObject *
|
|
|
b7e076 |
py_sha3_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
|
|
b7e076 |
{
|
|
|
b7e076 |
- FAIL_RETURN_IN_FIPS_MODE("_sha3");
|
|
|
b7e076 |
+ FAIL_RETURN_IN_FIPS_MODE(PyExc_ValueError, "_sha3");
|
|
|
b7e076 |
SHA3object *self = NULL;
|
|
|
b7e076 |
Py_buffer buf = {NULL, NULL};
|
|
|
b7e076 |
HashReturn res;
|
|
|
b7e076 |
@@ -727,7 +727,7 @@ PyInit__sha3(void)
|
|
|
b7e076 |
{
|
|
|
b7e076 |
PyObject *m = NULL;
|
|
|
b7e076 |
|
|
|
b7e076 |
- FAIL_RETURN_IN_FIPS_MODE("_sha3");
|
|
|
b7e076 |
+ FAIL_RETURN_IN_FIPS_MODE(PyExc_ImportError, "_sha3");
|
|
|
b7e076 |
|
|
|
b7e076 |
if ((m = PyModule_Create(&_SHA3module)) == NULL) {
|
|
|
b7e076 |
return NULL;
|
|
|
b7e076 |
--
|
|
|
3d909f |
2.25.1
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
From eb78e4b4179842185f53edba2073ab7644db7ad3 Mon Sep 17 00:00:00 2001
|
|
|
b7e076 |
From: Petr Viktorin <pviktori@redhat.com>
|
|
|
b7e076 |
Date: Fri, 26 Jul 2019 11:24:09 +0200
|
|
|
3d909f |
Subject: [PATCH 10/37] Make hashlib importable under FIPS mode
|
|
|
b7e076 |
|
|
|
b7e076 |
---
|
|
|
b7e076 |
Lib/hashlib.py | 8 +++++---
|
|
|
b7e076 |
1 file changed, 5 insertions(+), 3 deletions(-)
|
|
|
b7e076 |
|
|
|
b7e076 |
diff --git a/Lib/hashlib.py b/Lib/hashlib.py
|
|
|
3d909f |
index 2def0a310c..ca1dd20225 100644
|
|
|
b7e076 |
--- a/Lib/hashlib.py
|
|
|
b7e076 |
+++ b/Lib/hashlib.py
|
|
|
b7e076 |
@@ -132,12 +132,14 @@ def __get_openssl_constructor(name):
|
|
|
b7e076 |
f = getattr(_hashlib, 'openssl_' + name)
|
|
|
b7e076 |
# Allow the C module to raise ValueError. The function will be
|
|
|
b7e076 |
# defined but the hash not actually available thanks to OpenSSL.
|
|
|
b7e076 |
- f()
|
|
|
b7e076 |
+ if not get_fips_mode():
|
|
|
b7e076 |
+ # N.B. In "FIPS mode", there is no fallback.
|
|
|
b7e076 |
+ # If this test fails, we want to export the broken hash
|
|
|
b7e076 |
+ # constructor anyway.
|
|
|
b7e076 |
+ f()
|
|
|
b7e076 |
# Use the C function directly (very fast)
|
|
|
b7e076 |
return f
|
|
|
b7e076 |
except (AttributeError, ValueError):
|
|
|
b7e076 |
- if get_fips_mode():
|
|
|
b7e076 |
- raise
|
|
|
b7e076 |
return __get_builtin_constructor(name)
|
|
|
b7e076 |
|
|
|
b7e076 |
if not get_fips_mode():
|
|
|
b7e076 |
--
|
|
|
3d909f |
2.25.1
|
|
|
b7e076 |
|
|
|
b7e076 |
|
|
|
b7e076 |
From 0f313f65457f1e7d0e7238a71935f5d4e0d197ee Mon Sep 17 00:00:00 2001
|
|
|
b7e076 |
From: Petr Viktorin <pviktori@redhat.com>
|
|
|
b7e076 |
Date: Fri, 26 Jul 2019 15:41:10 +0200
|
|
|
3d909f |
Subject: [PATCH 11/37] Implement hmac.new using new built-in module,
|
|
|
b7e076 |
_hmacopenssl
|
|
|
b7e076 |
|
|
|
b7e076 |
---
|
|
|
b7e076 |
Lib/hmac.py | 33 ++-
|
|
|
b7e076 |
Modules/_hmacopenssl.c | 396 ++++++++++++++++++++++++++++++++
|
|
|
b7e076 |
Modules/clinic/_hmacopenssl.c.h | 133 +++++++++++
|
|
|
b7e076 |
setup.py | 4 +
|
|
|
b7e076 |
4 files changed, 565 insertions(+), 1 deletion(-)
|
|
|
b7e076 |
create mode 100644 Modules/_hmacopenssl.c
|
|
|
b7e076 |
create mode 100644 Modules/clinic/_hmacopenssl.c.h
|
|
|
b7e076 |
|
|
|