From 08ad15e6fb0f00ae55abe741fadf3a5654da07a8 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 28 Apr 2020 05:33:44 -0400 Subject: [PATCH] import python3-3.6.8-23.el8 --- ...00316-mark-bdist_wininst-unsupported.patch | 14 + SOURCES/00318-fixes-for-tls-13.patch | 949 +++++++ SOURCES/00318-test-ssl-fix-for-tls-13.patch | 44 - SOURCES/00329-fips.patch | 2410 +++++++++++------ SOURCES/00330-CVE-2018-20852.patch | 93 + SOURCES/00332-CVE-2019-16056.patch | 95 + SOURCES/00333-reduce-pgo-tests.patch | 296 ++ SPECS/python3.spec | 135 +- 8 files changed, 3088 insertions(+), 948 deletions(-) create mode 100644 SOURCES/00316-mark-bdist_wininst-unsupported.patch create mode 100644 SOURCES/00318-fixes-for-tls-13.patch delete mode 100644 SOURCES/00318-test-ssl-fix-for-tls-13.patch create mode 100644 SOURCES/00330-CVE-2018-20852.patch create mode 100644 SOURCES/00332-CVE-2019-16056.patch create mode 100644 SOURCES/00333-reduce-pgo-tests.patch diff --git a/SOURCES/00316-mark-bdist_wininst-unsupported.patch b/SOURCES/00316-mark-bdist_wininst-unsupported.patch new file mode 100644 index 0000000..c091be0 --- /dev/null +++ b/SOURCES/00316-mark-bdist_wininst-unsupported.patch @@ -0,0 +1,14 @@ +diff --git a/Lib/distutils/command/bdist_wininst.py b/Lib/distutils/command/bdist_wininst.py +index fde5675..15434c3 100644 +--- a/Lib/distutils/command/bdist_wininst.py ++++ b/Lib/distutils/command/bdist_wininst.py +@@ -55,6 +55,9 @@ class bdist_wininst(Command): + boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize', + 'skip-build'] + ++ # bpo-10945: bdist_wininst requires mbcs encoding only available on Windows ++ _unsupported = (sys.platform != "win32") ++ + def initialize_options(self): + self.bdist_dir = None + self.plat_name = None diff --git a/SOURCES/00318-fixes-for-tls-13.patch b/SOURCES/00318-fixes-for-tls-13.patch new file mode 100644 index 0000000..8f4a1b0 --- /dev/null +++ b/SOURCES/00318-fixes-for-tls-13.patch @@ -0,0 +1,949 @@ +From 412ccf4c6f8c417006c0a93392a8274a425074c0 Mon Sep 17 00:00:00 2001 +From: Victor Stinner +Date: Wed, 29 May 2019 04:04:54 +0200 +Subject: [PATCH 1/5] bpo-32947: test_ssl fixes for TLS 1.3 and OpenSSL 1.1.1 + (GH-11612) + +Backport partially commit 529525fb5a8fd9b96ab4021311a598c77588b918: +complete the previous partial backport (commit +2a4ee8aa01d61b6a9c8e9c65c211e61bdb471826. + +Co-Authored-By: Christian Heimes +--- + Lib/test/test_ssl.py | 15 +++++++++++++++ + .../2019-01-18-17-46-10.bpo-32947.Hk0KnM.rst | 1 + + 2 files changed, 16 insertions(+) + create mode 100644 Misc/NEWS.d/next/Tests/2019-01-18-17-46-10.bpo-32947.Hk0KnM.rst + +diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py +index cb0acda..639109f 100644 +--- a/Lib/test/test_ssl.py ++++ b/Lib/test/test_ssl.py +@@ -2043,6 +2043,16 @@ if _have_threads: + sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n" + % (msg, ctype, msg.lower(), ctype)) + self.write(msg.lower()) ++ except ConnectionResetError: ++ # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError ++ # when connection is not shut down gracefully. ++ if self.server.chatty and support.verbose: ++ sys.stdout.write( ++ " Connection reset by peer: {}\n".format( ++ self.addr) ++ ) ++ self.close() ++ self.running = False + except OSError: + if self.server.chatty: + handle_error("Test server failure:\n") +@@ -2122,6 +2132,11 @@ if _have_threads: + pass + except KeyboardInterrupt: + self.stop() ++ except BaseException as e: ++ if support.verbose and self.chatty: ++ sys.stdout.write( ++ ' connection handling failed: ' + repr(e) + '\n') ++ + self.sock.close() + + def stop(self): +diff --git a/Misc/NEWS.d/next/Tests/2019-01-18-17-46-10.bpo-32947.Hk0KnM.rst b/Misc/NEWS.d/next/Tests/2019-01-18-17-46-10.bpo-32947.Hk0KnM.rst +new file mode 100644 +index 0000000..f508504 +--- /dev/null ++++ b/Misc/NEWS.d/next/Tests/2019-01-18-17-46-10.bpo-32947.Hk0KnM.rst +@@ -0,0 +1 @@ ++test_ssl fixes for TLS 1.3 and OpenSSL 1.1.1. +-- +2.21.0 + + +From 6b728ec778067849dd1f0d9b73cf1ac47dafa270 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Wed, 25 Sep 2019 09:12:59 -0700 +Subject: [PATCH 2/5] bpo-38271: encrypt private key test files with AES256 + (GH-16385) + +The private keys for test_ssl were encrypted with 3DES in traditional +PKCSGH-5 format. 3DES and the digest algorithm of PKCSGH-5 are blocked by +some strict crypto policies. Use PKCSGH-8 format with AES256 encryption +instead. + +Signed-off-by: Christian Heimes + +https://bugs.python.org/issue38271 + +Automerge-Triggered-By: @tiran +(cherry picked from commit bfd0c963d88f3df69489ee250655e2b8f3d235bd) + +Co-authored-by: Christian Heimes +--- + Lib/test/keycert.passwd.pem | 85 ++++++++++--------- + Lib/test/make_ssl_certs.py | 4 +- + Lib/test/ssl_key.passwd.pem | 84 +++++++++--------- + .../2019-09-25-13-11-29.bpo-38271.iHXNIg.rst | 4 + + 4 files changed, 91 insertions(+), 86 deletions(-) + create mode 100644 Misc/NEWS.d/next/Tests/2019-09-25-13-11-29.bpo-38271.iHXNIg.rst + +diff --git a/Lib/test/keycert.passwd.pem b/Lib/test/keycert.passwd.pem +index cbb3c3b..c330c36 100644 +--- a/Lib/test/keycert.passwd.pem ++++ b/Lib/test/keycert.passwd.pem +@@ -1,45 +1,45 @@ +------BEGIN RSA PRIVATE KEY----- +-Proc-Type: 4,ENCRYPTED +-DEK-Info: DES-EDE3-CBC,D134E931C96D9DEC +- +-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 +------END RSA PRIVATE KEY----- ++-----BEGIN ENCRYPTED PRIVATE KEY----- ++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 ++-----END ENCRYPTED PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIEWTCCAsGgAwIBAgIJAJinz4jHSjLtMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV + BAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9u +@@ -66,3 +66,4 @@ jMqTFlmO7kpf/jpCSmamp3/JSEE1BJKHwQ6Ql4nzRA2N1mnvWH7Zxcv043gkHeAu + 9Wc2uXpw9xF8itV4Uvcdr3dwqByvIqn7iI/gB+4l41e0u8OmH2MKOx4Nxlly5TNW + HcVKQHyOeyvnINuBAQ== + -----END CERTIFICATE----- ++ +diff --git a/Lib/test/make_ssl_certs.py b/Lib/test/make_ssl_certs.py +index 3622765..41b5f46 100644 +--- a/Lib/test/make_ssl_certs.py ++++ b/Lib/test/make_ssl_certs.py +@@ -206,8 +206,8 @@ if __name__ == '__main__': + with open('ssl_key.pem', 'w') as f: + f.write(key) + print("password protecting ssl_key.pem in ssl_key.passwd.pem") +- check_call(['openssl','rsa','-in','ssl_key.pem','-out','ssl_key.passwd.pem','-des3','-passout','pass:somepass']) +- check_call(['openssl','rsa','-in','ssl_key.pem','-out','keycert.passwd.pem','-des3','-passout','pass:somepass']) ++ check_call(['openssl','pkey','-in','ssl_key.pem','-out','ssl_key.passwd.pem','-aes256','-passout','pass:somepass']) ++ check_call(['openssl','pkey','-in','ssl_key.pem','-out','keycert.passwd.pem','-aes256','-passout','pass:somepass']) + + with open('keycert.pem', 'w') as f: + f.write(key) +diff --git a/Lib/test/ssl_key.passwd.pem b/Lib/test/ssl_key.passwd.pem +index e4f1370..46de61a 100644 +--- a/Lib/test/ssl_key.passwd.pem ++++ b/Lib/test/ssl_key.passwd.pem +@@ -1,42 +1,42 @@ +------BEGIN RSA PRIVATE KEY----- +-Proc-Type: 4,ENCRYPTED +-DEK-Info: DES-EDE3-CBC,8064BE1494B24B13 +- +-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 +------END RSA PRIVATE KEY----- ++-----BEGIN ENCRYPTED PRIVATE KEY----- ++MIIHbTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQI072N7W+PDDMCAggA ++MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBA/AuaRNi4vE4KGqI4In+70BIIH ++ENGS5Vex5NID873frmd1UZEHZ+O/Bd0wDb+NUpIqesHkRYf7kKi6Gnr+nKQ/oVVn ++Lm3JjE7c8ECP0OkOOXmiXuWL1SkzBBWqCI4stSGUPvBiHsGwNnvJAaGjUffgMlcC ++aJOA2+dnejLkzblq4CB2LQdm06N3Xoe9tyqtQaUHxfzJAf5Ydd8uj7vpKN2MMhY7 ++icIPJwSyh0N7S6XWVtHEokr9Kp4y2hS5a+BgCWV1/1z0aF7agnSVndmT1VR+nWmc ++lM14k+lethmHMB+fsNSjnqeJ7XOPlOTHqhiZ9bBSTgF/xr5Bck/NiKRzHjdovBox ++TKg+xchaBhpRh7wBPBIlNJeHmIjv+8obOKjKU98Ig/7R9+IryZaNcKAH0PuOT+Sw ++QHXiCGQbOiYHB9UyhDTWiB7YVjd8KHefOFxfHzOQb/iBhbv1x3bTl3DgepvRN6VO ++dIsPLoIZe42sdf9GeMsk8mGJyZUQ6AzsfhWk3grb/XscizPSvrNsJ2VL1R7YTyT3 ++3WA4ZXR1EqvXnWL7N/raemQjy62iOG6t7fcF5IdP9CMbWP+Plpsz4cQW7FtesCTq ++a5ZXraochQz361ODFNIeBEGU+0qqXUtZDlmos/EySkZykSeU/L0bImS62VGE3afo ++YXBmznTTT9kkFkqv7H0MerfJsrE/wF8puP3GM01DW2JRgXRpSWlvbPV/2LnMtRuD ++II7iH4rWDtTjCN6BWKAgDOnPkc9sZ4XulqT32lcUeV6LTdMBfq8kMEc8eDij1vUT ++maVCRpuwaq8EIT3lVgNLufHiG96ojlyYtj3orzw22IjkgC/9ee8UDik9CqbMVmFf ++fVHhsw8LNSg8Q4bmwm5Eg2w2it2gtI68+mwr75oCxuJ/8OMjW21Prj8XDh5reie2 ++c0lDKQOFZ9UnLU1bXR/6qUM+JFKR4DMq+fOCuoQSVoyVUEOsJpvBOYnYZN9cxsZm ++vh9dKafMEcKZ8flsbr+gOmOw7+Py2ifSlf25E/Frb1W4gtbTb0LQVHb6+drutrZj ++8HEu4CnHYFCD4ZnOJb26XlZCb8GFBddW86yJYyUqMMV6Q1aJfAOAglsTo1LjIMOZ ++byo0BTAmwUevU/iuOXQ4qRBXXcoidDcTCrxfUSPG9wdt9l+m5SdQpWqfQ+fx5O7m ++SLlrHyZCiPSFMtC9DxqjIklHjf5W3wslGLgaD30YXa4VDYkRihf3CNsxGQ+tVvef ++l0ZjoAitF7Gaua06IESmKnpHe23dkr1cjYq+u2IV+xGH8LeExdwsQ9kpuTeXPnQs ++JOA99SsFx1ct32RrwjxnDDsiNkaViTKo9GDkV3jQTfoFgAVqfSgg9wGXpqUqhNG7 ++TiSIHCowllLny2zn4XrXCy2niD3VDt0skb3l/PaegHE2z7S5YY85nQtYwpLiwB9M ++SQ08DYKxPBZYKtS2iZ/fsA1gjSRQDPg/SIxMhUC3M3qH8iWny1Lzl25F2Uq7VVEX ++LdTUtaby49jRTT3CQGr5n6z7bMbUegiY7h8WmOekuThGDH+4xZp6+rDP4GFk4FeK ++JcF70vMQYIjQZhadic6olv+9VtUP42ltGG/yP9a3eWRkzfAf2eCh6B1rYdgEWwE8 ++rlcZzwM+y6eUmeNF2FVWB8iWtTMQHy+dYNPM+Jtus1KQKxiiq/yCRs7nWvzWRFWA ++HRyqV0J6/lqgm4FvfktFt1T0W+mDoLJOR2/zIwMy2lgL5zeHuR3SaMJnCikJbqKS ++HB3UvrhAWUcZqdH29+FhVWeM7ybyF1Wccmf+IIC/ePLa6gjtqPV8lG/5kbpcpnB6 ++UQY8WWaKMxyr3jJ9bAX5QKshchp04cDecOLZrpFGNNQngR8RxSEkiIgAqNxWunIu ++KrdBDrupv/XAgEOclmgToY3iywLJSV5gHAyHWDUhRH4cFCLiGPl4XIcnXOuTze3H ++3j+EYSiS3v3DhHjp33YU2pXlJDjiYsKzAXejEh66++Y8qaQdCAad3ruWRCzW3kgk ++Md0A1VGzntTnQsewvExQEMZH2LtYIsPv3KCYGeSAuLabX4tbGk79PswjnjLLEOr0 ++Ghf6RF6qf5/iFyJoG4vrbKT8kx6ywh0InILCdjUunuDskIBxX6tEcr9XwajoIvb2 ++kcmGdjam5kKLS7QOWQTl8/r/cuFes0dj34cX5Qpq+Gd7tRq/D+b0207926Cxvftv ++qQ1cVn8HiLxKkZzd3tpf2xnoV1zkTL0oHrNg+qzxoxXUTUcwtIf1d/HRbYEAhi/d ++bBBoFeftEHWNq+sJgS9bH+XNzo/yK4u04B5miOq8v4CSkJdzu+ZdF22d4cjiGmtQ ++8BTmcn0Unzm+u5H0+QSZe54QBHJGNXXOIKMTkgnOdW27g4DbI1y7fCqJiSMbRW6L ++oHmMfbdB3GWqGbsUkhY8i6h9op0MU6WOX7ea2Rxyt4t6 ++-----END ENCRYPTED PRIVATE KEY----- +diff --git a/Misc/NEWS.d/next/Tests/2019-09-25-13-11-29.bpo-38271.iHXNIg.rst b/Misc/NEWS.d/next/Tests/2019-09-25-13-11-29.bpo-38271.iHXNIg.rst +new file mode 100644 +index 0000000..8f43d32 +--- /dev/null ++++ b/Misc/NEWS.d/next/Tests/2019-09-25-13-11-29.bpo-38271.iHXNIg.rst +@@ -0,0 +1,4 @@ ++The private keys for test_ssl were encrypted with 3DES in traditional ++PKCS#5 format. 3DES and the digest algorithm of PKCS#5 are blocked by ++some strict crypto policies. Use PKCS#8 format with AES256 encryption ++instead. +-- +2.21.0 + + +From d8584f9bb3fb841a1b21ed25abc2237ea8bbc206 Mon Sep 17 00:00:00 2001 +From: Charalampos Stratakis +Date: Tue, 26 Nov 2019 23:57:21 +0100 +Subject: [PATCH 3/5] Use PROTOCOL_TLS_CLIENT/SERVER + +Replaces PROTOCOL_TLSv* and PROTOCOL_SSLv23 with PROTOCOL_TLS_CLIENT and +PROTOCOL_TLS_SERVER. + +Partially backports a170fa162dc03f0a014373349e548954fff2e567 +--- + Lib/ssl.py | 7 +- + Lib/test/test_logging.py | 2 +- + Lib/test/test_ssl.py | 169 +++++++++++++++++++-------------------- + 3 files changed, 87 insertions(+), 91 deletions(-) + +diff --git a/Lib/ssl.py b/Lib/ssl.py +index 0114387..c5c5529 100644 +--- a/Lib/ssl.py ++++ b/Lib/ssl.py +@@ -473,7 +473,7 @@ def create_default_context(purpose=Purpose.SERVER_AUTH, *, cafile=None, + context.load_default_certs(purpose) + return context + +-def _create_unverified_context(protocol=PROTOCOL_TLS, *, cert_reqs=None, ++def _create_unverified_context(protocol=PROTOCOL_TLS, *, cert_reqs=CERT_NONE, + check_hostname=False, purpose=Purpose.SERVER_AUTH, + certfile=None, keyfile=None, + cafile=None, capath=None, cadata=None): +@@ -492,9 +492,12 @@ def _create_unverified_context(protocol=PROTOCOL_TLS, *, cert_reqs=None, + # by default. + context = SSLContext(protocol) + ++ if not check_hostname: ++ context.check_hostname = False + if cert_reqs is not None: + context.verify_mode = cert_reqs +- context.check_hostname = check_hostname ++ if check_hostname: ++ context.check_hostname = True + + if keyfile and not certfile: + raise ValueError("certfile must be specified") +diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py +index 763a5d1..d5c63b4 100644 +--- a/Lib/test/test_logging.py ++++ b/Lib/test/test_logging.py +@@ -1830,7 +1830,7 @@ class HTTPHandlerTest(BaseTest): + else: + here = os.path.dirname(__file__) + localhost_cert = os.path.join(here, "keycert.pem") +- sslctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) ++ sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + sslctx.load_cert_chain(localhost_cert) + + context = ssl.create_default_context(cafile=localhost_cert) +diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py +index 639109f..a7bf2f7 100644 +--- a/Lib/test/test_ssl.py ++++ b/Lib/test/test_ssl.py +@@ -155,6 +155,8 @@ def test_wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLS, *, + **kwargs): + context = ssl.SSLContext(ssl_version) + if cert_reqs is not None: ++ if cert_reqs == ssl.CERT_NONE: ++ context.check_hostname = False + context.verify_mode = cert_reqs + if ca_certs is not None: + context.load_verify_locations(ca_certs) +@@ -1377,7 +1379,7 @@ class ContextTests(unittest.TestCase): + self._assert_context_options(ctx) + + def test_check_hostname(self): +- ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) ++ ctx = ssl.SSLContext(ssl.PROTOCOL_TLS) + self.assertFalse(ctx.check_hostname) + + # Requires CERT_REQUIRED or CERT_OPTIONAL +@@ -2386,17 +2388,13 @@ if _have_threads: + server_params_test(context, context, + chatty=True, connectionchatty=True) + +- client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) +- client_context.load_verify_locations(SIGNING_CA) +- server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) +- # server_context.load_verify_locations(SIGNING_CA) +- server_context.load_cert_chain(SIGNED_CERTFILE2) ++ client_context, server_context, hostname = testing_context() + + with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER): + server_params_test(client_context=client_context, + server_context=server_context, + chatty=True, connectionchatty=True, +- sni_name='fakehostname') ++ sni_name='localhost') + + client_context.check_hostname = False + with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT): +@@ -2404,7 +2402,7 @@ if _have_threads: + server_params_test(client_context=server_context, + server_context=client_context, + chatty=True, connectionchatty=True, +- sni_name='fakehostname') ++ sni_name='localhost') + self.assertIn('called a function you should not call', + str(e.exception)) + +@@ -2469,39 +2467,38 @@ if _have_threads: + if support.verbose: + sys.stdout.write("\n") + +- server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- server_context.load_cert_chain(SIGNED_CERTFILE) ++ client_context, server_context, hostname = testing_context() + +- context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- context.verify_mode = ssl.CERT_REQUIRED +- context.load_verify_locations(SIGNING_CA) + tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0) +- self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT | tf) ++ self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf) + + # VERIFY_DEFAULT should pass + server = ThreadedEchoServer(context=server_context, chatty=True) + with server: +- with context.wrap_socket(socket.socket()) as s: ++ with client_context.wrap_socket(socket.socket(), ++ server_hostname=hostname) as s: + s.connect((HOST, server.port)) + cert = s.getpeercert() + self.assertTrue(cert, "Can't get peer certificate.") + + # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails +- context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF ++ client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF + + server = ThreadedEchoServer(context=server_context, chatty=True) + with server: +- with context.wrap_socket(socket.socket()) as s: ++ with client_context.wrap_socket(socket.socket(), ++ server_hostname=hostname) as s: + with self.assertRaisesRegex(ssl.SSLError, + "certificate verify failed"): + s.connect((HOST, server.port)) + + # now load a CRL file. The CRL file is signed by the CA. +- context.load_verify_locations(CRLFILE) ++ client_context.load_verify_locations(CRLFILE) + + server = ThreadedEchoServer(context=server_context, chatty=True) + with server: +- with context.wrap_socket(socket.socket()) as s: ++ with client_context.wrap_socket(socket.socket(), ++ server_hostname=hostname) as s: + s.connect((HOST, server.port)) + cert = s.getpeercert() + self.assertTrue(cert, "Can't get peer certificate.") +@@ -2510,19 +2507,13 @@ if _have_threads: + if support.verbose: + sys.stdout.write("\n") + +- server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- server_context.load_cert_chain(SIGNED_CERTFILE) +- +- context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- context.verify_mode = ssl.CERT_REQUIRED +- context.check_hostname = True +- context.load_verify_locations(SIGNING_CA) ++ client_context, server_context, hostname = testing_context() + + # correct hostname should verify + server = ThreadedEchoServer(context=server_context, chatty=True) + with server: +- with context.wrap_socket(socket.socket(), +- server_hostname="localhost") as s: ++ with client_context.wrap_socket(socket.socket(), ++ server_hostname=hostname) as s: + s.connect((HOST, server.port)) + cert = s.getpeercert() + self.assertTrue(cert, "Can't get peer certificate.") +@@ -2530,7 +2521,7 @@ if _have_threads: + # incorrect hostname should raise an exception + server = ThreadedEchoServer(context=server_context, chatty=True) + with server: +- with context.wrap_socket(socket.socket(), ++ with client_context.wrap_socket(socket.socket(), + server_hostname="invalid") as s: + with self.assertRaisesRegex(ssl.CertificateError, + "hostname 'invalid' doesn't match 'localhost'"): +@@ -2542,7 +2533,7 @@ if _have_threads: + with socket.socket() as s: + with self.assertRaisesRegex(ValueError, + "check_hostname requires server_hostname"): +- context.wrap_socket(s) ++ client_context.wrap_socket(s) + + def test_wrong_cert(self): + """Connecting when the server rejects the client's certificate +@@ -2767,7 +2758,6 @@ if _have_threads: + msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6") + + server = ThreadedEchoServer(CERTFILE, +- ssl_version=ssl.PROTOCOL_TLSv1, + starttls_server=True, + chatty=True, + connectionchatty=True) +@@ -2795,7 +2785,7 @@ if _have_threads: + sys.stdout.write( + " client: read %r from server, starting TLS...\n" + % msg) +- conn = test_wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1) ++ conn = test_wrap_socket(s) + wrapped = True + elif indata == b"ENDTLS" and msg.startswith(b"ok"): + # ENDTLS ok, switch back to clear text +@@ -2882,7 +2872,7 @@ if _have_threads: + + server = ThreadedEchoServer(CERTFILE, + certreqs=ssl.CERT_NONE, +- ssl_version=ssl.PROTOCOL_TLSv1, ++ ssl_version=ssl.PROTOCOL_TLS_SERVER, + cacerts=CERTFILE, + chatty=True, + connectionchatty=False) +@@ -2892,7 +2882,7 @@ if _have_threads: + certfile=CERTFILE, + ca_certs=CERTFILE, + cert_reqs=ssl.CERT_NONE, +- ssl_version=ssl.PROTOCOL_TLSv1) ++ ssl_version=ssl.PROTOCOL_TLS_CLIENT) + s.connect((HOST, server.port)) + # helper methods for standardising recv* method signatures + def _recv_into(): +@@ -3034,7 +3024,7 @@ if _have_threads: + def test_nonblocking_send(self): + server = ThreadedEchoServer(CERTFILE, + certreqs=ssl.CERT_NONE, +- ssl_version=ssl.PROTOCOL_TLSv1, ++ ssl_version=ssl.PROTOCOL_TLS_SERVER, + cacerts=CERTFILE, + chatty=True, + connectionchatty=False) +@@ -3044,7 +3034,7 @@ if _have_threads: + certfile=CERTFILE, + ca_certs=CERTFILE, + cert_reqs=ssl.CERT_NONE, +- ssl_version=ssl.PROTOCOL_TLSv1) ++ ssl_version=ssl.PROTOCOL_TLS_CLIENT) + s.connect((HOST, server.port)) + s.setblocking(False) + +@@ -3190,9 +3180,11 @@ if _have_threads: + Basic tests for SSLSocket.version(). + More tests are done in the test_protocol_*() methods. + """ +- context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) ++ context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) ++ context.check_hostname = False ++ context.verify_mode = ssl.CERT_NONE + with ThreadedEchoServer(CERTFILE, +- ssl_version=ssl.PROTOCOL_TLSv1, ++ ssl_version=ssl.PROTOCOL_TLS_SERVER, + chatty=False) as server: + with context.wrap_socket(socket.socket()) as s: + self.assertIs(s.version(), None) +@@ -3247,7 +3239,7 @@ if _have_threads: + + server = ThreadedEchoServer(CERTFILE, + certreqs=ssl.CERT_NONE, +- ssl_version=ssl.PROTOCOL_TLSv1, ++ ssl_version=ssl.PROTOCOL_TLS_SERVER, + cacerts=CERTFILE, + chatty=True, + connectionchatty=False) +@@ -3257,7 +3249,7 @@ if _have_threads: + certfile=CERTFILE, + ca_certs=CERTFILE, + cert_reqs=ssl.CERT_NONE, +- ssl_version=ssl.PROTOCOL_TLSv1) ++ ssl_version=ssl.PROTOCOL_TLS_CLIENT) + s.connect((HOST, server.port)) + # get the data + cb_data = s.get_channel_binding("tls-unique") +@@ -3282,7 +3274,7 @@ if _have_threads: + certfile=CERTFILE, + ca_certs=CERTFILE, + cert_reqs=ssl.CERT_NONE, +- ssl_version=ssl.PROTOCOL_TLSv1) ++ ssl_version=ssl.PROTOCOL_TLS_CLIENT) + s.connect((HOST, server.port)) + new_cb_data = s.get_channel_binding("tls-unique") + if support.verbose: +@@ -3299,32 +3291,35 @@ if _have_threads: + s.close() + + def test_compression(self): +- context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- context.load_cert_chain(CERTFILE) +- stats = server_params_test(context, context, +- chatty=True, connectionchatty=True) ++ client_context, server_context, hostname = testing_context() ++ stats = server_params_test(client_context, server_context, ++ chatty=True, connectionchatty=True, ++ sni_name=hostname) + if support.verbose: + sys.stdout.write(" got compression: {!r}\n".format(stats['compression'])) + self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' }) + ++ + @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'), + "ssl.OP_NO_COMPRESSION needed for this test") + def test_compression_disabled(self): +- context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- context.load_cert_chain(CERTFILE) +- context.options |= ssl.OP_NO_COMPRESSION +- stats = server_params_test(context, context, +- chatty=True, connectionchatty=True) ++ client_context, server_context, hostname = testing_context() ++ client_context.options |= ssl.OP_NO_COMPRESSION ++ server_context.options |= ssl.OP_NO_COMPRESSION ++ stats = server_params_test(client_context, server_context, ++ chatty=True, connectionchatty=True, ++ sni_name=hostname) + self.assertIs(stats['compression'], None) + + def test_dh_params(self): + # Check we can get a connection with ephemeral Diffie-Hellman +- context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- context.load_cert_chain(CERTFILE) +- context.load_dh_params(DHFILE) +- context.set_ciphers("kEDH") +- stats = server_params_test(context, context, +- chatty=True, connectionchatty=True) ++ client_context, server_context, hostname = testing_context() ++ server_context.load_dh_params(DHFILE) ++ server_context.set_ciphers("kEDH") ++ server_context.options |= ssl.OP_NO_TLSv1_3 ++ stats = server_params_test(client_context, server_context, ++ chatty=True, connectionchatty=True, ++ sni_name=hostname) + cipher = stats["cipher"][0] + parts = cipher.split("-") + if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts: +@@ -3332,22 +3327,20 @@ if _have_threads: + + def test_selected_alpn_protocol(self): + # selected_alpn_protocol() is None unless ALPN is used. +- context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- context.load_cert_chain(CERTFILE) +- stats = server_params_test(context, context, +- chatty=True, connectionchatty=True) ++ client_context, server_context, hostname = testing_context() ++ stats = server_params_test(client_context, server_context, ++ chatty=True, connectionchatty=True, ++ sni_name=hostname) + self.assertIs(stats['client_alpn_protocol'], None) + + @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required") + def test_selected_alpn_protocol_if_server_uses_alpn(self): + # selected_alpn_protocol() is None unless ALPN is used by the client. +- client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- client_context.load_verify_locations(CERTFILE) +- server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- server_context.load_cert_chain(CERTFILE) ++ client_context, server_context, hostname = testing_context() + server_context.set_alpn_protocols(['foo', 'bar']) + stats = server_params_test(client_context, server_context, +- chatty=True, connectionchatty=True) ++ chatty=True, connectionchatty=True, ++ sni_name=hostname) + self.assertIs(stats['client_alpn_protocol'], None) + + @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test") +@@ -3394,10 +3387,10 @@ if _have_threads: + + def test_selected_npn_protocol(self): + # selected_npn_protocol() is None unless NPN is used +- context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- context.load_cert_chain(CERTFILE) +- stats = server_params_test(context, context, +- chatty=True, connectionchatty=True) ++ client_context, server_context, hostname = testing_context() ++ stats = server_params_test(client_context, server_context, ++ chatty=True, connectionchatty=True, ++ sni_name=hostname) + self.assertIs(stats['client_npn_protocol'], None) + + @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test") +@@ -3430,12 +3423,11 @@ if _have_threads: + self.assertEqual(server_result, expected, msg % (server_result, "server")) + + def sni_contexts(self): +- server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) ++ server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + server_context.load_cert_chain(SIGNED_CERTFILE) +- other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) ++ other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + other_context.load_cert_chain(SIGNED_CERTFILE2) +- client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- client_context.verify_mode = ssl.CERT_REQUIRED ++ client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + client_context.load_verify_locations(SIGNING_CA) + return server_context, other_context, client_context + +@@ -3448,6 +3440,8 @@ if _have_threads: + calls = [] + server_context, other_context, client_context = self.sni_contexts() + ++ client_context.check_hostname = False ++ + def servername_cb(ssl_sock, server_name, initial_context): + calls.append((server_name, initial_context)) + if server_name is not None: +@@ -3533,11 +3527,7 @@ if _have_threads: + self.assertIn("TypeError", stderr.getvalue()) + + def test_shared_ciphers(self): +- server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- server_context.load_cert_chain(SIGNED_CERTFILE) +- client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- client_context.verify_mode = ssl.CERT_REQUIRED +- client_context.load_verify_locations(SIGNING_CA) ++ client_context, server_context, hostname = testing_context() + if ssl.OPENSSL_VERSION_INFO >= (1, 0, 2): + client_context.set_ciphers("AES128:AES256") + server_context.set_ciphers("AES256") +@@ -3555,7 +3545,8 @@ if _have_threads: + # TLS 1.3 ciphers are always enabled + expected_algs.extend(["TLS_CHACHA20", "TLS_AES"]) + +- stats = server_params_test(client_context, server_context) ++ stats = server_params_test(client_context, server_context, ++ sni_name=hostname) + ciphers = stats['server_shared_ciphers'][0] + self.assertGreater(len(ciphers), 0) + for name, tls_version, bits in ciphers: +@@ -3595,14 +3586,13 @@ if _have_threads: + self.assertEqual(s.recv(1024), TEST_DATA) + + def test_session(self): +- server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- server_context.load_cert_chain(SIGNED_CERTFILE) +- client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- client_context.verify_mode = ssl.CERT_REQUIRED +- client_context.load_verify_locations(SIGNING_CA) ++ client_context, server_context, hostname = testing_context() ++ # TODO: sessions aren't compatible with TLSv1.3 yet ++ client_context.options |= ssl.OP_NO_TLSv1_3 + + # first connection without session +- stats = server_params_test(client_context, server_context) ++ stats = server_params_test(client_context, server_context, ++ sni_name=hostname) + session = stats['session'] + self.assertTrue(session.id) + self.assertGreater(session.time, 0) +@@ -3616,7 +3606,8 @@ if _have_threads: + self.assertEqual(sess_stat['hits'], 0) + + # reuse session +- stats = server_params_test(client_context, server_context, session=session) ++ stats = server_params_test(client_context, server_context, ++ session=session, sni_name=hostname) + sess_stat = server_context.session_stats() + self.assertEqual(sess_stat['accept'], 2) + self.assertEqual(sess_stat['hits'], 1) +@@ -3629,7 +3620,8 @@ if _have_threads: + self.assertGreaterEqual(session2.timeout, session.timeout) + + # another one without session +- stats = server_params_test(client_context, server_context) ++ stats = server_params_test(client_context, server_context, ++ sni_name=hostname) + self.assertFalse(stats['session_reused']) + session3 = stats['session'] + self.assertNotEqual(session3.id, session.id) +@@ -3639,7 +3631,8 @@ if _have_threads: + self.assertEqual(sess_stat['hits'], 1) + + # reuse session again +- stats = server_params_test(client_context, server_context, session=session) ++ stats = server_params_test(client_context, server_context, ++ session=session, sni_name=hostname) + self.assertTrue(stats['session_reused']) + session4 = stats['session'] + self.assertEqual(session4.id, session.id) +-- +2.21.0 + + +From 743c3e09b485092b51a982ab9859ffc79cbb7791 Mon Sep 17 00:00:00 2001 +From: Charalampos Stratakis +Date: Wed, 27 Nov 2019 00:01:17 +0100 +Subject: [PATCH 4/5] Adjust some tests for TLS 1.3 compatibility + +Partially backports some changes from 529525fb5a8fd9b96ab4021311a598c77588b918 +and 2614ed4c6e4b32eafb683f2378ed20e87d42976d +--- + Lib/test/test_ssl.py | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py +index a7bf2f7..43c2dbc 100644 +--- a/Lib/test/test_ssl.py ++++ b/Lib/test/test_ssl.py +@@ -3189,7 +3189,12 @@ if _have_threads: + with context.wrap_socket(socket.socket()) as s: + self.assertIs(s.version(), None) + s.connect((HOST, server.port)) +- self.assertEqual(s.version(), 'TLSv1') ++ if IS_OPENSSL_1_1: ++ self.assertEqual(s.version(), 'TLSv1.3') ++ elif ssl.OPENSSL_VERSION_INFO >= (1, 0, 2): ++ self.assertEqual(s.version(), 'TLSv1.2') ++ else: # 0.9.8 to 1.0.1 ++ self.assertIn(s.version(), ('TLSv1', 'TLSv1.2')) + self.assertIs(s.version(), None) + + @unittest.skipUnless(ssl.HAS_TLSv1_3, +@@ -3259,7 +3264,10 @@ if _have_threads: + + # check if it is sane + self.assertIsNotNone(cb_data) +- self.assertEqual(len(cb_data), 12) # True for TLSv1 ++ if s.version() == 'TLSv1.3': ++ self.assertEqual(len(cb_data), 48) ++ else: ++ self.assertEqual(len(cb_data), 12) # True for TLSv1 + + # and compare with the peers version + s.write(b"CB tls-unique\n") +@@ -3283,7 +3291,10 @@ if _have_threads: + # is it really unique + self.assertNotEqual(cb_data, new_cb_data) + self.assertIsNotNone(cb_data) +- self.assertEqual(len(cb_data), 12) # True for TLSv1 ++ if s.version() == 'TLSv1.3': ++ self.assertEqual(len(cb_data), 48) ++ else: ++ self.assertEqual(len(cb_data), 12) # True for TLSv1 + s.write(b"CB tls-unique\n") + peer_data_repr = s.read().strip() + self.assertEqual(peer_data_repr, +-- +2.21.0 + + +From cd250c8a782f36c7a6f5ffabc922cb75744fa9c0 Mon Sep 17 00:00:00 2001 +From: Charalampos Stratakis +Date: Tue, 26 Nov 2019 23:18:10 +0100 +Subject: [PATCH 5/5] Skip the ssl tests that rely on TLSv1 and TLSv1.1 + availability + +--- + Lib/test/test_ssl.py | 32 +++++++++++++++++++++++--------- + 1 file changed, 23 insertions(+), 9 deletions(-) + +diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py +index 43c2dbc..b35db25 100644 +--- a/Lib/test/test_ssl.py ++++ b/Lib/test/test_ssl.py +@@ -39,6 +39,13 @@ IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL') + IS_OPENSSL_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0) + PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS') + ++# On RHEL8 openssl disables TLSv1 and TLSv1.1 on runtime. ++# Since we don't have a good way to detect runtime changes ++# on the allowed protocols, we hardcode the default config ++# with those flags. ++TLSv1_enabled = False ++TLSv1_1_enabled = False ++ + def data_file(*name): + return os.path.join(os.path.dirname(__file__), *name) + +@@ -2380,7 +2387,8 @@ if _have_threads: + if support.verbose: + sys.stdout.write("\n") + for protocol in PROTOCOLS: +- if protocol in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}: ++ if protocol in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER, ++ ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1}: + continue + with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]): + context = ssl.SSLContext(protocol) +@@ -2650,17 +2658,20 @@ if _have_threads: + if hasattr(ssl, 'PROTOCOL_SSLv3'): + try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False) + try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True) +- try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1') ++ if TLSv1_enabled: ++ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1') + + if hasattr(ssl, 'PROTOCOL_SSLv3'): + try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL) + try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL) +- try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL) ++ if TLSv1_enabled: ++ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL) + + if hasattr(ssl, 'PROTOCOL_SSLv3'): + try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED) + try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED) +- try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED) ++ if TLSv1_enabled: ++ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED) + + # Server with specific SSL options + if hasattr(ssl, 'PROTOCOL_SSLv3'): +@@ -2698,9 +2709,10 @@ if _have_threads: + """Connecting to a TLSv1 server with various client options""" + if support.verbose: + sys.stdout.write("\n") +- try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1') +- try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL) +- try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED) ++ if TLSv1_enabled: ++ try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1') ++ try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL) ++ try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED) + if hasattr(ssl, 'PROTOCOL_SSLv2'): + try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False) + if hasattr(ssl, 'PROTOCOL_SSLv3'): +@@ -2716,7 +2728,8 @@ if _have_threads: + Testing against older TLS versions.""" + if support.verbose: + sys.stdout.write("\n") +- try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1') ++ if TLSv1_1_enabled: ++ try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1') + if hasattr(ssl, 'PROTOCOL_SSLv2'): + try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False) + if hasattr(ssl, 'PROTOCOL_SSLv3'): +@@ -2724,7 +2737,8 @@ if _have_threads: + try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False, + client_options=ssl.OP_NO_TLSv1_1) + +- try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1') ++ if TLSv1_1_enabled: ++ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1') + try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False) + try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False) + +-- +2.21.0 + diff --git a/SOURCES/00318-test-ssl-fix-for-tls-13.patch b/SOURCES/00318-test-ssl-fix-for-tls-13.patch deleted file mode 100644 index 7b00d75..0000000 --- a/SOURCES/00318-test-ssl-fix-for-tls-13.patch +++ /dev/null @@ -1,44 +0,0 @@ -bpo-32947: test_ssl fixes for TLS 1.3 and OpenSSL 1.1.1 - -Backport partially commit 529525fb5a8fd9b96ab4021311a598c77588b918: -complete the previous partial backport (commit -2a4ee8aa01d61b6a9c8e9c65c211e61bdb471826. - -Reported upstream: - -* https://bugs.python.org/issue32947#msg333990 -* https://github.com/python/cpython/pull/11612 - -diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py -index 7f8f636..05c09a6 100644 ---- a/Lib/test/test_ssl.py -+++ b/Lib/test/test_ssl.py -@@ -2021,6 +2021,16 @@ if _have_threads: - sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n" - % (msg, ctype, msg.lower(), ctype)) - self.write(msg.lower()) -+ except ConnectionResetError: -+ # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError -+ # when connection is not shut down gracefully. -+ if self.server.chatty and support.verbose: -+ sys.stdout.write( -+ " Connection reset by peer: {}\n".format( -+ self.addr) -+ ) -+ self.close() -+ self.running = False - except OSError: - if self.server.chatty: - handle_error("Test server failure:\n") -@@ -2100,6 +2110,11 @@ if _have_threads: - pass - except KeyboardInterrupt: - self.stop() -+ except BaseException as e: -+ if support.verbose and self.chatty: -+ sys.stdout.write( -+ ' connection handling failed: ' + repr(e) + '\n') -+ - self.sock.close() - - def stop(self): diff --git a/SOURCES/00329-fips.patch b/SOURCES/00329-fips.patch index b1ec9f8..e250caa 100644 --- a/SOURCES/00329-fips.patch +++ b/SOURCES/00329-fips.patch @@ -1,7 +1,783 @@ -From f85cd78683a7f4216f85439ff12bde07c8118597 Mon Sep 17 00:00:00 2001 +From 53d108c5103c99079f1f231b0e731f3f47a142fc Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Wed, 25 Sep 2019 08:50:31 -0700 +Subject: [PATCH 01/36] [3.8] bpo-38270: Check for hash digest algorithms and + avoid MD5 (GH-16382) (GH-16393) + +Make it easier to run and test Python on systems with restrict crypto policies: + +* add requires_hashdigest to test.support to check if a hash digest algorithm is available and working +* avoid MD5 in test_hmac +* replace MD5 with SHA256 in test_tarfile +* mark network tests that require MD5 for MD5-based digest auth or CRAM-MD5 + +https://bugs.python.org/issue38270 +(cherry picked from commit c64a1a61e6fc542cada40eb069a239317e1af36e) + +Co-authored-by: Christian Heimes + +https://bugs.python.org/issue38270 + +Automerge-Triggered-By: @tiran +--- + Lib/test/support/__init__.py | 22 ++++++++++ + Lib/test/test_hmac.py | 67 +++++++++++++++++++------------ + Lib/test/test_imaplib.py | 6 ++- + Lib/test/test_poplib.py | 2 + + Lib/test/test_smtplib.py | 11 ++++- + Lib/test/test_tarfile.py | 56 ++++++++++++++------------ + Lib/test/test_urllib2_localnet.py | 1 + + 7 files changed, 112 insertions(+), 53 deletions(-) + +diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py +index 66c0fed8411..a43819904e0 100644 +--- a/Lib/test/support/__init__.py ++++ b/Lib/test/support/__init__.py +@@ -11,6 +11,7 @@ import faulthandler + import fnmatch + import functools + import gc ++import hashlib + import importlib + import importlib.util + import io +@@ -627,6 +628,27 @@ def requires_mac_ver(*min_version): + return wrapper + return decorator + ++def requires_hashdigest(digestname): ++ """Decorator raising SkipTest if a hashing algorithm is not available ++ ++ The hashing algorithm could be missing or blocked by a strict crypto ++ policy. ++ ++ ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS ++ ValueError: unsupported hash type md4 ++ """ ++ def decorator(func): ++ @functools.wraps(func) ++ def wrapper(*args, **kwargs): ++ try: ++ hashlib.new(digestname) ++ except ValueError: ++ raise unittest.SkipTest( ++ f"hash digest '{digestname}' is not available." ++ ) ++ return func(*args, **kwargs) ++ return wrapper ++ return decorator + + # Don't use "localhost", since resolving it uses the DNS under recent + # Windows versions (see issue #18792). +diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py +index 067e13f1079..81c3485f761 100644 +--- a/Lib/test/test_hmac.py ++++ b/Lib/test/test_hmac.py +@@ -4,6 +4,8 @@ import hashlib + import unittest + import warnings + ++from test.support import requires_hashdigest ++ + + def ignore_warning(func): + @functools.wraps(func) +@@ -17,6 +19,7 @@ def ignore_warning(func): + + class TestVectorsTestCase(unittest.TestCase): + ++ @requires_hashdigest('md5') + def test_md5_vectors(self): + # Test the HMAC module against test vectors from the RFC. + +@@ -63,6 +66,7 @@ class TestVectorsTestCase(unittest.TestCase): + b"and Larger Than One Block-Size Data"), + "6f630fad67cda0ee1fb1f562db3aa53e") + ++ @requires_hashdigest('sha1') + def test_sha_vectors(self): + def shatest(key, data, digest): + h = hmac.HMAC(key, data, digestmod=hashlib.sha1) +@@ -230,23 +234,28 @@ class TestVectorsTestCase(unittest.TestCase): + '134676fb6de0446065c97440fa8c6a58', + }) + ++ @requires_hashdigest('sha224') + def test_sha224_rfc4231(self): + self._rfc4231_test_cases(hashlib.sha224, 'sha224', 28, 64) + ++ @requires_hashdigest('sha256') + def test_sha256_rfc4231(self): + self._rfc4231_test_cases(hashlib.sha256, 'sha256', 32, 64) + ++ @requires_hashdigest('sha384') + def test_sha384_rfc4231(self): + self._rfc4231_test_cases(hashlib.sha384, 'sha384', 48, 128) + ++ @requires_hashdigest('sha512') + def test_sha512_rfc4231(self): + self._rfc4231_test_cases(hashlib.sha512, 'sha512', 64, 128) + ++ @requires_hashdigest('sha256') + def test_legacy_block_size_warnings(self): + class MockCrazyHash(object): + """Ain't no block_size attribute here.""" + def __init__(self, *args): +- self._x = hashlib.sha1(*args) ++ self._x = hashlib.sha256(*args) + self.digest_size = self._x.digest_size + def update(self, v): + self._x.update(v) +@@ -273,76 +282,80 @@ class TestVectorsTestCase(unittest.TestCase): + self.assertEqual(h.hexdigest().upper(), digest) + + ++ + class ConstructorTestCase(unittest.TestCase): + ++ expected = ( ++ "6c845b47f52b3b47f6590c502db7825aad757bf4fadc8fa972f7cd2e76a5bdeb" ++ ) + @ignore_warning ++ @requires_hashdigest('sha256') + def test_normal(self): + # Standard constructor call. +- failed = 0 + try: +- h = hmac.HMAC(b"key") ++ hmac.HMAC(b"key", digestmod='sha256') + except Exception: + self.fail("Standard constructor call raised exception.") + + @ignore_warning ++ @requires_hashdigest('sha256') + def test_with_str_key(self): + # Pass a key of type str, which is an error, because it expects a key + # of type bytes + with self.assertRaises(TypeError): +- h = hmac.HMAC("key") ++ h = hmac.HMAC("key", digestmod='sha256') + +- @ignore_warning ++ @requires_hashdigest('sha256') + def test_dot_new_with_str_key(self): + # Pass a key of type str, which is an error, because it expects a key + # of type bytes + with self.assertRaises(TypeError): +- h = hmac.new("key") ++ h = hmac.HMAC("key", digestmod='sha256') + + @ignore_warning ++ @requires_hashdigest('sha256') + def test_withtext(self): + # Constructor call with text. + try: +- h = hmac.HMAC(b"key", b"hash this!") ++ h = hmac.HMAC(b"key", b"hash this!", digestmod='sha256') + except Exception: + self.fail("Constructor call with text argument raised exception.") +- self.assertEqual(h.hexdigest(), '34325b639da4cfd95735b381e28cb864') ++ self.assertEqual(h.hexdigest(), self.expected) + ++ @requires_hashdigest('sha256') + def test_with_bytearray(self): + try: + h = hmac.HMAC(bytearray(b"key"), bytearray(b"hash this!"), +- digestmod="md5") ++ digestmod="sha256") + except Exception: + self.fail("Constructor call with bytearray arguments raised exception.") +- self.assertEqual(h.hexdigest(), '34325b639da4cfd95735b381e28cb864') ++ self.assertEqual(h.hexdigest(), self.expected) + ++ @requires_hashdigest('sha256') + def test_with_memoryview_msg(self): + try: +- h = hmac.HMAC(b"key", memoryview(b"hash this!"), digestmod="md5") ++ h = hmac.HMAC(b"key", memoryview(b"hash this!"), digestmod="sha256") + except Exception: + self.fail("Constructor call with memoryview msg raised exception.") +- self.assertEqual(h.hexdigest(), '34325b639da4cfd95735b381e28cb864') ++ self.assertEqual(h.hexdigest(), self.expected) + ++ @requires_hashdigest('sha256') + def test_withmodule(self): + # Constructor call with text and digest module. + try: +- h = hmac.HMAC(b"key", b"", hashlib.sha1) ++ h = hmac.HMAC(b"key", b"", hashlib.sha256) + except Exception: +- self.fail("Constructor call with hashlib.sha1 raised exception.") ++ self.fail("Constructor call with hashlib.sha256 raised exception.") + +-class SanityTestCase(unittest.TestCase): + +- @ignore_warning +- def test_default_is_md5(self): +- # Testing if HMAC defaults to MD5 algorithm. +- # NOTE: this whitebox test depends on the hmac class internals +- h = hmac.HMAC(b"key") +- self.assertEqual(h.digest_cons, hashlib.md5) ++class SanityTestCase(unittest.TestCase): + ++ @requires_hashdigest('sha256') + def test_exercise_all_methods(self): + # Exercising all methods once. + # This must not raise any exceptions + try: +- h = hmac.HMAC(b"my secret key", digestmod="md5") ++ h = hmac.HMAC(b"my secret key", digestmod="sha256") + h.update(b"compute the hash of this text!") + dig = h.digest() + dig = h.hexdigest() +@@ -350,11 +363,13 @@ class SanityTestCase(unittest.TestCase): + except Exception: + self.fail("Exception raised during normal usage of HMAC class.") + ++ + class CopyTestCase(unittest.TestCase): + ++ @requires_hashdigest('sha256') + def test_attributes(self): + # Testing if attributes are of same type. +- h1 = hmac.HMAC(b"key", digestmod="md5") ++ h1 = hmac.HMAC(b"key", digestmod="sha256") + h2 = h1.copy() + self.assertTrue(h1.digest_cons == h2.digest_cons, + "digest constructors don't match.") +@@ -363,9 +378,10 @@ class CopyTestCase(unittest.TestCase): + self.assertEqual(type(h1.outer), type(h2.outer), + "Types of outer don't match.") + ++ @requires_hashdigest('sha256') + def test_realcopy(self): + # Testing if the copy method created a real copy. +- h1 = hmac.HMAC(b"key", digestmod="md5") ++ h1 = hmac.HMAC(b"key", digestmod="sha256") + h2 = h1.copy() + # Using id() in case somebody has overridden __eq__/__ne__. + self.assertTrue(id(h1) != id(h2), "No real copy of the HMAC instance.") +@@ -374,9 +390,10 @@ class CopyTestCase(unittest.TestCase): + self.assertTrue(id(h1.outer) != id(h2.outer), + "No real copy of the attribute 'outer'.") + ++ @requires_hashdigest('sha256') + def test_equality(self): + # Testing if the copy has the same digests. +- h1 = hmac.HMAC(b"key", digestmod="md5") ++ h1 = hmac.HMAC(b"key", digestmod="sha256") + h1.update(b"some random text") + h2 = h1.copy() + self.assertEqual(h1.digest(), h2.digest(), +diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py +index 0593a3756b0..086cc0ac4e0 100644 +--- a/Lib/test/test_imaplib.py ++++ b/Lib/test/test_imaplib.py +@@ -14,7 +14,8 @@ import calendar + import inspect + + from test.support import (reap_threads, verbose, transient_internet, +- run_with_tz, run_with_locale, cpython_only) ++ run_with_tz, run_with_locale, cpython_only, ++ requires_hashdigest) + import unittest + from unittest import mock + from datetime import datetime, timezone, timedelta +@@ -369,6 +370,7 @@ class NewIMAPTestsMixin(): + self.assertEqual(code, 'OK') + self.assertEqual(server.response, b'ZmFrZQ==\r\n') # b64 encoded 'fake' + ++ @requires_hashdigest('md5') + def test_login_cram_md5_bytes(self): + class AuthHandler(SimpleIMAPHandler): + capabilities = 'LOGINDISABLED AUTH=CRAM-MD5' +@@ -386,6 +388,7 @@ class NewIMAPTestsMixin(): + ret, _ = client.login_cram_md5("tim", b"tanstaaftanstaaf") + self.assertEqual(ret, "OK") + ++ @requires_hashdigest('md5') + def test_login_cram_md5_plain_text(self): + class AuthHandler(SimpleIMAPHandler): + capabilities = 'LOGINDISABLED AUTH=CRAM-MD5' +@@ -797,6 +800,7 @@ class ThreadedNetworkedTests(unittest.TestCase): + b'ZmFrZQ==\r\n') # b64 encoded 'fake' + + @reap_threads ++ @requires_hashdigest('md5') + def test_login_cram_md5(self): + + class AuthHandler(SimpleIMAPHandler): +diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py +index 234c855545c..b8146be3a8c 100644 +--- a/Lib/test/test_poplib.py ++++ b/Lib/test/test_poplib.py +@@ -304,9 +304,11 @@ class TestPOP3Class(TestCase): + def test_rpop(self): + self.assertOK(self.client.rpop('foo')) + ++ @test_support.requires_hashdigest('md5') + def test_apop_normal(self): + self.assertOK(self.client.apop('foo', 'dummypassword')) + ++ @test_support.requires_hashdigest('md5') + def test_apop_REDOS(self): + # Replace welcome with very long evil welcome. + # NB The upper bound on welcome length is currently 2048. +diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py +index 87047514e7a..64b3201254a 100644 +--- a/Lib/test/test_smtplib.py ++++ b/Lib/test/test_smtplib.py +@@ -4,6 +4,7 @@ import email.mime.text + from email.message import EmailMessage + from email.base64mime import body_encode as encode_base64 + import email.utils ++import hashlib + import hmac + import socket + import smtpd +@@ -18,6 +19,7 @@ import textwrap + + import unittest + from test import support, mock_socket ++from test.support import requires_hashdigest + from unittest.mock import Mock + + HOST = "localhost" +@@ -968,6 +970,7 @@ class SMTPSimTests(unittest.TestCase): + self.assertEqual(resp, (235, b'Authentication Succeeded')) + smtp.close() + ++ @requires_hashdigest('md5') + def testAUTH_CRAM_MD5(self): + self.serv.add_feature("AUTH CRAM-MD5") + smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) +@@ -984,7 +987,13 @@ class SMTPSimTests(unittest.TestCase): + smtp.close() + + def test_auth_function(self): +- supported = {'CRAM-MD5', 'PLAIN', 'LOGIN'} ++ supported = {'PLAIN', 'LOGIN'} ++ try: ++ hashlib.md5() ++ except ValueError: ++ pass ++ else: ++ supported.add('CRAM-MD5') + for mechanism in supported: + self.serv.add_feature("AUTH {}".format(mechanism)) + for mechanism in supported: +diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py +index 4cd7d5370f5..b5e855e0d7e 100644 +--- a/Lib/test/test_tarfile.py ++++ b/Lib/test/test_tarfile.py +@@ -1,7 +1,7 @@ + import sys + import os + import io +-from hashlib import md5 ++from hashlib import sha256 + from contextlib import contextmanager + from random import Random + import pathlib +@@ -11,7 +11,7 @@ import unittest.mock + import tarfile + + from test import support +-from test.support import script_helper ++from test.support import script_helper, requires_hashdigest + + # Check for our compression modules. + try: +@@ -27,8 +27,8 @@ try: + except ImportError: + lzma = None + +-def md5sum(data): +- return md5(data).hexdigest() ++def sha256sum(data): ++ return sha256(data).hexdigest() + + TEMPDIR = os.path.abspath(support.TESTFN) + "-tardir" + tarextdir = TEMPDIR + '-extract-test' +@@ -39,8 +39,12 @@ xzname = os.path.join(TEMPDIR, "testtar.tar.xz") + tmpname = os.path.join(TEMPDIR, "tmp.tar") + dotlessname = os.path.join(TEMPDIR, "testtar") + +-md5_regtype = "65f477c818ad9e15f7feab0c6d37742f" +-md5_sparse = "a54fbc4ca4f4399a90e1b27164012fc6" ++sha256_regtype = ( ++ "e09e4bc8b3c9d9177e77256353b36c159f5f040531bbd4b024a8f9b9196c71ce" ++) ++sha256_sparse = ( ++ "4f05a776071146756345ceee937b33fc5644f5a96b9780d1c7d6a32cdf164d7b" ++) + + + class TarTest: +@@ -95,7 +99,7 @@ class UstarReadTest(ReadTest, unittest.TestCase): + data = fobj.read() + self.assertEqual(len(data), tarinfo.size, + "regular file extraction failed") +- self.assertEqual(md5sum(data), md5_regtype, ++ self.assertEqual(sha256sum(data), sha256_regtype, + "regular file extraction failed") + + def test_fileobj_readlines(self): +@@ -180,7 +184,7 @@ class UstarReadTest(ReadTest, unittest.TestCase): + with self.tar.extractfile("ustar/regtype") as fobj: + fobj = io.TextIOWrapper(fobj) + data = fobj.read().encode("iso8859-1") +- self.assertEqual(md5sum(data), md5_regtype) ++ self.assertEqual(sha256sum(data), sha256_regtype) + try: + fobj.seek(100) + except AttributeError: +@@ -546,13 +550,13 @@ class MiscReadTestBase(CommonReadTest): + self.addCleanup(support.unlink, os.path.join(TEMPDIR, "ustar/lnktype")) + with open(os.path.join(TEMPDIR, "ustar/lnktype"), "rb") as f: + data = f.read() +- self.assertEqual(md5sum(data), md5_regtype) ++ self.assertEqual(sha256sum(data), sha256_regtype) + + tar.extract("ustar/symtype", TEMPDIR) + self.addCleanup(support.unlink, os.path.join(TEMPDIR, "ustar/symtype")) + with open(os.path.join(TEMPDIR, "ustar/symtype"), "rb") as f: + data = f.read() +- self.assertEqual(md5sum(data), md5_regtype) ++ self.assertEqual(sha256sum(data), sha256_regtype) + + def test_extractall(self): + # Test if extractall() correctly restores directory permissions +@@ -687,7 +691,7 @@ class StreamReadTest(CommonReadTest, unittest.TestCase): + data = fobj.read() + self.assertEqual(len(data), tarinfo.size, + "regular file extraction failed") +- self.assertEqual(md5sum(data), md5_regtype, ++ self.assertEqual(sha256sum(data), sha256_regtype, + "regular file extraction failed") + + def test_provoke_stream_error(self): +@@ -799,8 +803,8 @@ class MemberReadTest(ReadTest, unittest.TestCase): + def _test_member(self, tarinfo, chksum=None, **kwargs): + if chksum is not None: + with self.tar.extractfile(tarinfo) as f: +- self.assertEqual(md5sum(f.read()), chksum, +- "wrong md5sum for %s" % tarinfo.name) ++ self.assertEqual(sha256sum(f.read()), chksum, ++ "wrong sha256sum for %s" % tarinfo.name) + + kwargs["mtime"] = 0o7606136617 + kwargs["uid"] = 1000 +@@ -815,11 +819,11 @@ class MemberReadTest(ReadTest, unittest.TestCase): + + def test_find_regtype(self): + tarinfo = self.tar.getmember("ustar/regtype") +- self._test_member(tarinfo, size=7011, chksum=md5_regtype) ++ self._test_member(tarinfo, size=7011, chksum=sha256_regtype) + + def test_find_conttype(self): + tarinfo = self.tar.getmember("ustar/conttype") +- self._test_member(tarinfo, size=7011, chksum=md5_regtype) ++ self._test_member(tarinfo, size=7011, chksum=sha256_regtype) + + def test_find_dirtype(self): + tarinfo = self.tar.getmember("ustar/dirtype") +@@ -851,28 +855,28 @@ class MemberReadTest(ReadTest, unittest.TestCase): + + def test_find_sparse(self): + tarinfo = self.tar.getmember("ustar/sparse") +- self._test_member(tarinfo, size=86016, chksum=md5_sparse) ++ self._test_member(tarinfo, size=86016, chksum=sha256_sparse) + + def test_find_gnusparse(self): + tarinfo = self.tar.getmember("gnu/sparse") +- self._test_member(tarinfo, size=86016, chksum=md5_sparse) ++ self._test_member(tarinfo, size=86016, chksum=sha256_sparse) + + def test_find_gnusparse_00(self): + tarinfo = self.tar.getmember("gnu/sparse-0.0") +- self._test_member(tarinfo, size=86016, chksum=md5_sparse) ++ self._test_member(tarinfo, size=86016, chksum=sha256_sparse) + + def test_find_gnusparse_01(self): + tarinfo = self.tar.getmember("gnu/sparse-0.1") +- self._test_member(tarinfo, size=86016, chksum=md5_sparse) ++ self._test_member(tarinfo, size=86016, chksum=sha256_sparse) + + def test_find_gnusparse_10(self): + tarinfo = self.tar.getmember("gnu/sparse-1.0") +- self._test_member(tarinfo, size=86016, chksum=md5_sparse) ++ self._test_member(tarinfo, size=86016, chksum=sha256_sparse) + + def test_find_umlauts(self): + tarinfo = self.tar.getmember("ustar/umlauts-" + "\xc4\xd6\xdc\xe4\xf6\xfc\xdf") +- self._test_member(tarinfo, size=7011, chksum=md5_regtype) ++ self._test_member(tarinfo, size=7011, chksum=sha256_regtype) + + def test_find_ustar_longname(self): + name = "ustar/" + "12345/" * 39 + "1234567/longname" +@@ -880,7 +884,7 @@ class MemberReadTest(ReadTest, unittest.TestCase): + + def test_find_regtype_oldv7(self): + tarinfo = self.tar.getmember("misc/regtype-old-v7") +- self._test_member(tarinfo, size=7011, chksum=md5_regtype) ++ self._test_member(tarinfo, size=7011, chksum=sha256_regtype) + + def test_find_pax_umlauts(self): + self.tar.close() +@@ -888,7 +892,7 @@ class MemberReadTest(ReadTest, unittest.TestCase): + encoding="iso8859-1") + tarinfo = self.tar.getmember("pax/umlauts-" + "\xc4\xd6\xdc\xe4\xf6\xfc\xdf") +- self._test_member(tarinfo, size=7011, chksum=md5_regtype) ++ self._test_member(tarinfo, size=7011, chksum=sha256_regtype) + + + class LongnameTest: +@@ -950,8 +954,8 @@ class GNUReadTest(LongnameTest, ReadTest, unittest.TestCase): + filename = os.path.join(TEMPDIR, name) + with open(filename, "rb") as fobj: + data = fobj.read() +- self.assertEqual(md5sum(data), md5_sparse, +- "wrong md5sum for %s" % name) ++ self.assertEqual(sha256sum(data), sha256_sparse, ++ "wrong sha256sum for %s" % name) + + if self._fs_supports_holes(): + s = os.stat(filename) +@@ -2431,7 +2435,7 @@ class LinkEmulationTest(ReadTest, unittest.TestCase): + self.tar.extract(name, TEMPDIR) + with open(os.path.join(TEMPDIR, name), "rb") as f: + data = f.read() +- self.assertEqual(md5sum(data), md5_regtype) ++ self.assertEqual(sha256sum(data), sha256_regtype) + + # See issues #1578269, #8879, and #17689 for some history on these skips + @unittest.skipIf(hasattr(os.path, "islink"), +diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py +index ef0091c4930..895f97cc09a 100644 +--- a/Lib/test/test_urllib2_localnet.py ++++ b/Lib/test/test_urllib2_localnet.py +@@ -325,6 +325,7 @@ class ProxyAuthTests(unittest.TestCase): + PASSWD = "test123" + REALM = "TestRealm" + ++ @support.requires_hashdigest("md5") + def setUp(self): + super(ProxyAuthTests, self).setUp() + # Ignore proxy bypass settings in the environment. +-- +2.21.0 + + +From 75d9613294e1cbd5aab9363cf3c435871a25f065 Mon Sep 17 00:00:00 2001 +From: Christian Heimes +Date: Mon, 30 Sep 2019 09:10:38 +0200 +Subject: [PATCH 02/36] [3.8] bpo-38270: More fixes for strict crypto policy + (GH-16418) (#16437) + +test_hmac and test_hashlib test built-in hashing implementations and +OpenSSL-based hashing implementations. Add more checks to skip OpenSSL +implementations when a strict crypto policy is active. + +Use EVP_DigestInit_ex() instead of EVP_DigestInit() to initialize the +EVP context. The EVP_DigestInit() function clears alls flags and breaks +usedforsecurity flag again. + +Signed-off-by: Christian Heimes + +https://bugs.python.org/issue38270. +(cherry picked from commit 90558158093c0ad893102158fd3c2dd9f864e82e) + +Co-authored-by: Christian Heimes +--- + Lib/test/support/__init__.py | 19 ++++++++++++++++--- + Lib/test/test_hashlib.py | 3 +++ + Lib/test/test_hmac.py | 12 ++++++------ + 3 files changed, 25 insertions(+), 9 deletions(-) + +diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py +index a43819904e0..3342218cf0a 100644 +--- a/Lib/test/support/__init__.py ++++ b/Lib/test/support/__init__.py +@@ -71,6 +71,11 @@ try: + except ImportError: + resource = None + ++try: ++ import _hashlib ++except ImportError: ++ _hashlib = None ++ + __all__ = [ + # globals + "PIPE_MAX_SIZE", "verbose", "max_memuse", "use_resources", "failfast", +@@ -88,7 +93,8 @@ __all__ = [ + "create_empty_file", "can_symlink", "fs_is_case_insensitive", + # unittest + "is_resource_enabled", "requires", "requires_freebsd_version", +- "requires_linux_version", "requires_mac_ver", "check_syntax_error", ++ "requires_linux_version", "requires_mac_ver", "requires_hashdigest", ++ "check_syntax_error", + "TransientResource", "time_out", "socket_peer_reset", "ioerror_peer_reset", + "transient_internet", "BasicTestRunner", "run_unittest", "run_doctest", + "skip_unless_symlink", "requires_gzip", "requires_bz2", "requires_lzma", +@@ -628,12 +634,16 @@ def requires_mac_ver(*min_version): + return wrapper + return decorator + +-def requires_hashdigest(digestname): ++def requires_hashdigest(digestname, openssl=None): + """Decorator raising SkipTest if a hashing algorithm is not available + + The hashing algorithm could be missing or blocked by a strict crypto + policy. + ++ If 'openssl' is True, then the decorator checks that OpenSSL provides ++ the algorithm. Otherwise the check falls back to built-in ++ implementations. ++ + ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS + ValueError: unsupported hash type md4 + """ +@@ -641,7 +651,10 @@ def requires_hashdigest(digestname): + @functools.wraps(func) + def wrapper(*args, **kwargs): + try: +- hashlib.new(digestname) ++ if openssl and _hashlib is not None: ++ _hashlib.new(digestname) ++ else: ++ hashlib.new(digestname) + except ValueError: + raise unittest.SkipTest( + f"hash digest '{digestname}' is not available." +diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py +index 9711856853d..1b1b4d54112 100644 +--- a/Lib/test/test_hashlib.py ++++ b/Lib/test/test_hashlib.py +@@ -8,6 +8,7 @@ + + import array + from binascii import unhexlify ++import functools + import hashlib + import importlib + import itertools +@@ -21,6 +22,7 @@ import unittest + import warnings + from test import support + from test.support import _4G, bigmemtest, import_fresh_module ++from test.support import requires_hashdigest + from http.client import HTTPException + + # Were we compiled --with-pydebug or with #define Py_DEBUG? +@@ -117,6 +119,7 @@ class HashLibTestCase(unittest.TestCase): + constructors.add(_test_algorithm_via_hashlib_new) + + _hashlib = self._conditional_import_module('_hashlib') ++ self._hashlib = _hashlib + if _hashlib: + # These two algorithms should always be present when this module + # is compiled. If not, something was compiled wrong. +diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py +index 81c3485f761..2a5a0d3d061 100644 +--- a/Lib/test/test_hmac.py ++++ b/Lib/test/test_hmac.py +@@ -19,7 +19,7 @@ def ignore_warning(func): + + class TestVectorsTestCase(unittest.TestCase): + +- @requires_hashdigest('md5') ++ @requires_hashdigest('md5', openssl=True) + def test_md5_vectors(self): + # Test the HMAC module against test vectors from the RFC. + +@@ -66,7 +66,7 @@ class TestVectorsTestCase(unittest.TestCase): + b"and Larger Than One Block-Size Data"), + "6f630fad67cda0ee1fb1f562db3aa53e") + +- @requires_hashdigest('sha1') ++ @requires_hashdigest('sha1', openssl=True) + def test_sha_vectors(self): + def shatest(key, data, digest): + h = hmac.HMAC(key, data, digestmod=hashlib.sha1) +@@ -234,19 +234,19 @@ class TestVectorsTestCase(unittest.TestCase): + '134676fb6de0446065c97440fa8c6a58', + }) + +- @requires_hashdigest('sha224') ++ @requires_hashdigest('sha224', openssl=True) + def test_sha224_rfc4231(self): + self._rfc4231_test_cases(hashlib.sha224, 'sha224', 28, 64) + +- @requires_hashdigest('sha256') ++ @requires_hashdigest('sha256', openssl=True) + def test_sha256_rfc4231(self): + self._rfc4231_test_cases(hashlib.sha256, 'sha256', 32, 64) + +- @requires_hashdigest('sha384') ++ @requires_hashdigest('sha384', openssl=True) + def test_sha384_rfc4231(self): + self._rfc4231_test_cases(hashlib.sha384, 'sha384', 48, 128) + +- @requires_hashdigest('sha512') ++ @requires_hashdigest('sha512', openssl=True) + def test_sha512_rfc4231(self): + self._rfc4231_test_cases(hashlib.sha512, 'sha512', 64, 128) + +-- +2.21.0 + + +From 19a40f7e820bb991c03e03c05dc832539b676983 Mon Sep 17 00:00:00 2001 +From: stratakis +Date: Tue, 3 Dec 2019 16:35:54 +0100 +Subject: [PATCH 03/36] bpo-38270: Fix indentation of test_hmac assertions + (GH-17446) + +Since https://github.com/python/cpython/commit/c64a1a61e6fc542cada40eb069a239317e1af36e two assertions were indented and thus ignored when running test_hmac. + +This PR fixes it. As the change is quite trivial I didn't add a NEWS entry. + + +https://bugs.python.org/issue38270 +--- + Lib/test/test_hmac.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py +index 2a5a0d3d061..338e0215a41 100644 +--- a/Lib/test/test_hmac.py ++++ b/Lib/test/test_hmac.py +@@ -329,7 +329,7 @@ class ConstructorTestCase(unittest.TestCase): + digestmod="sha256") + except Exception: + self.fail("Constructor call with bytearray arguments raised exception.") +- self.assertEqual(h.hexdigest(), self.expected) ++ self.assertEqual(h.hexdigest(), self.expected) + + @requires_hashdigest('sha256') + def test_with_memoryview_msg(self): +@@ -337,7 +337,7 @@ class ConstructorTestCase(unittest.TestCase): + h = hmac.HMAC(b"key", memoryview(b"hash this!"), digestmod="sha256") + except Exception: + self.fail("Constructor call with memoryview msg raised exception.") +- self.assertEqual(h.hexdigest(), self.expected) ++ self.assertEqual(h.hexdigest(), self.expected) + + @requires_hashdigest('sha256') + def test_withmodule(self): +-- +2.21.0 + + +From 5fa96205b380f2cb555ac346e6b7039746cb51ca Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 25 Jul 2019 16:19:52 +0200 -Subject: [PATCH 01/36] Expose OpenSSL FIPS_mode() as hashlib.get_fips_mode() +Subject: [PATCH 04/36] Expose OpenSSL FIPS_mode() as hashlib.get_fips_mode() --- Lib/hashlib.py | 5 +++++ @@ -10,10 +786,10 @@ Subject: [PATCH 01/36] Expose OpenSSL FIPS_mode() as hashlib.get_fips_mode() 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/Lib/hashlib.py b/Lib/hashlib.py -index 98d2d7981a38..ae17c5851109 100644 +index 98d2d7981a3..ae17c585110 100644 --- a/Lib/hashlib.py +++ b/Lib/hashlib.py -@@ -236,6 +236,11 @@ def prf(msg, inner=inner, outer=outer): +@@ -236,6 +236,11 @@ try: except ImportError: pass @@ -26,7 +802,7 @@ index 98d2d7981a38..ae17c5851109 100644 for __func_name in __always_supported: # try them all, some may not work due to the OpenSSL diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c -index 84edd72c85a3..4876a7f7aa76 100644 +index 84edd72c85a..4876a7f7aa7 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -25,6 +25,9 @@ @@ -87,10 +863,10 @@ index 84edd72c85a3..4876a7f7aa76 100644 CONSTRUCTOR_METH_DEF(sha1), CONSTRUCTOR_METH_DEF(sha224), diff --git a/Modules/clinic/_hashopenssl.c.h b/Modules/clinic/_hashopenssl.c.h -index 04453526040b..8828e2776e95 100644 +index 04453526040..8828e2776e9 100644 --- a/Modules/clinic/_hashopenssl.c.h +++ b/Modules/clinic/_hashopenssl.c.h -@@ -54,7 +54,30 @@ _hashlib_scrypt(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *k +@@ -54,7 +54,30 @@ exit: #endif /* (OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(OPENSSL_NO_SCRYPT) && !defined(LIBRESSL_VERSION_NUMBER)) */ @@ -122,11 +898,14 @@ index 04453526040b..8828e2776e95 100644 #endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */ -/*[clinic end generated code: output=118cd7036fa0fb52 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7d683c930bbb7c36 input=a9049054013a1b77]*/ +-- +2.21.0 -From b8c716a651d5884e0dfdbb2cfefb0f49a0ee0540 Mon Sep 17 00:00:00 2001 + +From e60cc93037b913ca2a410d73b52d8301ab0d76cd Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Thu, 25 Jul 2019 17:04:06 +0200 -Subject: [PATCH 02/36] Use python's fall backs for the crypto it implements +Subject: [PATCH 05/36] Use python's fall backs for the crypto it implements only if we are not in FIPS mode --- @@ -135,10 +914,10 @@ Subject: [PATCH 02/36] Use python's fall backs for the crypto it implements 2 files changed, 81 insertions(+), 129 deletions(-) diff --git a/Lib/hashlib.py b/Lib/hashlib.py -index ae17c5851109..7db1e02601fe 100644 +index ae17c585110..7db1e02601f 100644 --- a/Lib/hashlib.py +++ b/Lib/hashlib.py -@@ -67,56 +67,64 @@ +@@ -67,56 +67,64 @@ algorithms_available = set(__always_supported) __all__ = __always_supported + ('new', 'algorithms_guaranteed', 'algorithms_available', 'pbkdf2_hmac') @@ -303,7 +1082,7 @@ index ae17c5851109..7db1e02601fe 100644 return __get_builtin_constructor(name)(data) -@@ -163,72 +176,14 @@ def __hash_new(name, data=b'', **kwargs): +@@ -163,72 +176,14 @@ try: algorithms_available = algorithms_available.union( _hashlib.openssl_md_meth_names) except ImportError: @@ -380,7 +1159,7 @@ index ae17c5851109..7db1e02601fe 100644 try: # OpenSSL's scrypt requires OpenSSL 1.1+ -@@ -236,12 +191,6 @@ def prf(msg, inner=inner, outer=outer): +@@ -236,12 +191,6 @@ try: except ImportError: pass @@ -393,7 +1172,7 @@ index ae17c5851109..7db1e02601fe 100644 for __func_name in __always_supported: # try them all, some may not work due to the OpenSSL # version not supporting that algorithm. -@@ -254,4 +203,6 @@ def prf(msg, inner=inner, outer=outer): +@@ -254,4 +203,6 @@ for __func_name in __always_supported: # Cleanup locals() del __always_supported, __func_name, __get_hash @@ -402,10 +1181,10 @@ index ae17c5851109..7db1e02601fe 100644 +if not get_fips_mode(): + del __py_new diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py -index 9711856853de..c67d2f6d00aa 100644 +index 1b1b4d54112..4e6b5b607a9 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py -@@ -930,6 +930,7 @@ def _test_pbkdf2_hmac(self, pbkdf2): +@@ -933,6 +933,7 @@ class KDFTests(unittest.TestCase): iterations=1, dklen=None) self.assertEqual(out, self.pbkdf2_results['sha1'][0][0]) @@ -413,11 +1192,14 @@ index 9711856853de..c67d2f6d00aa 100644 def test_pbkdf2_hmac_py(self): self._test_pbkdf2_hmac(py_hashlib.pbkdf2_hmac) +-- +2.21.0 -From 88185ade926f6a629acd8d24f00dfd10bfa9de0e Mon Sep 17 00:00:00 2001 + +From 4803386d980b9ad1a9bdde829e8642676acd8bf4 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 25 Jul 2019 17:19:06 +0200 -Subject: [PATCH 03/36] Disable Python's hash implementations in FIPS mode, +Subject: [PATCH 06/36] Disable Python's hash implementations in FIPS mode, forcing OpenSSL --- @@ -433,7 +1215,7 @@ Subject: [PATCH 03/36] Disable Python's hash implementations in FIPS mode, diff --git a/Include/_hashopenssl.h b/Include/_hashopenssl.h new file mode 100644 -index 000000000000..a726c0d3fbf3 +index 00000000000..a726c0d3fbf --- /dev/null +++ b/Include/_hashopenssl.h @@ -0,0 +1,66 @@ @@ -504,7 +1286,7 @@ index 000000000000..a726c0d3fbf3 + +#endif // !Py_HASHOPENSSL_H diff --git a/Modules/_blake2/blake2b_impl.c b/Modules/_blake2/blake2b_impl.c -index 418c0184006d..341e67a8fcc4 100644 +index 418c0184006..341e67a8fcc 100644 --- a/Modules/_blake2/blake2b_impl.c +++ b/Modules/_blake2/blake2b_impl.c @@ -14,6 +14,7 @@ @@ -534,7 +1316,7 @@ index 418c0184006d..341e67a8fcc4 100644 #ifdef WITH_THREAD diff --git a/Modules/_blake2/blake2module.c b/Modules/_blake2/blake2module.c -index e2a3d420d4eb..817b71656844 100644 +index e2a3d420d4e..817b7165684 100644 --- a/Modules/_blake2/blake2module.c +++ b/Modules/_blake2/blake2module.c @@ -9,6 +9,7 @@ @@ -555,7 +1337,7 @@ index e2a3d420d4eb..817b71656844 100644 if (m == NULL) return NULL; diff --git a/Modules/_blake2/blake2s_impl.c b/Modules/_blake2/blake2s_impl.c -index 24e529b6596a..0dfe0586b570 100644 +index 24e529b6596..0dfe0586b57 100644 --- a/Modules/_blake2/blake2s_impl.c +++ b/Modules/_blake2/blake2s_impl.c @@ -14,6 +14,7 @@ @@ -585,7 +1367,7 @@ index 24e529b6596a..0dfe0586b570 100644 #ifdef WITH_THREAD diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c -index 4876a7f7aa76..02cf6087a2ea 100644 +index 4876a7f7aa7..02cf6087a2e 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -17,16 +17,13 @@ @@ -645,7 +1427,7 @@ index 4876a7f7aa76..02cf6087a2ea 100644 newEVPobject(PyObject *name) { diff --git a/Modules/_sha3/sha3module.c b/Modules/_sha3/sha3module.c -index 2c2b2dbc5c7d..624f7f247d4f 100644 +index 2c2b2dbc5c7..624f7f247d4 100644 --- a/Modules/_sha3/sha3module.c +++ b/Modules/_sha3/sha3module.c @@ -18,6 +18,7 @@ @@ -682,10 +1464,10 @@ index 2c2b2dbc5c7d..624f7f247d4f 100644 return NULL; } diff --git a/setup.py b/setup.py -index e2c18982532b..e2e659ef7950 100644 +index e2c18982532..e2e659ef795 100644 --- a/setup.py +++ b/setup.py -@@ -901,31 +901,30 @@ def detect_modules(self): +@@ -901,31 +901,30 @@ class PyBuildExt(build_ext): have_usable_openssl = (have_any_openssl and openssl_ver >= min_openssl_ver) @@ -730,7 +1512,7 @@ index e2c18982532b..e2e659ef7950 100644 blake2_deps = glob(os.path.join(os.getcwd(), srcdir, 'Modules/_blake2/impl/*')) -@@ -944,6 +943,7 @@ def detect_modules(self): +@@ -944,6 +943,7 @@ class PyBuildExt(build_ext): '_blake2/blake2b_impl.c', '_blake2/blake2s_impl.c'], define_macros=blake2_macros, @@ -738,7 +1520,7 @@ index e2c18982532b..e2e659ef7950 100644 depends=blake2_deps) ) sha3_deps = glob(os.path.join(os.getcwd(), srcdir, -@@ -951,7 +951,8 @@ def detect_modules(self): +@@ -951,7 +951,8 @@ class PyBuildExt(build_ext): sha3_deps.append('hashlib.h') exts.append( Extension('_sha3', ['_sha3/sha3module.c'], @@ -748,11 +1530,14 @@ index e2c18982532b..e2e659ef7950 100644 # Modules that provide persistent dictionary-like semantics. You will # probably want to arrange for at least one of them to be available on +-- +2.21.0 -From ced78ca1f37efca7a43dc467756a4ff5b5669555 Mon Sep 17 00:00:00 2001 + +From 0f35f480e2134c7d5c4ea3d68d8c0af14f56afa3 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 25 Jul 2019 17:35:27 +0200 -Subject: [PATCH 04/36] Expose all hashes available to OpenSSL, using a list +Subject: [PATCH 07/36] Expose all hashes available to OpenSSL, using a list --- Modules/_hashopenssl.c | 44 ++++++++++++++----------------------- @@ -761,7 +1546,7 @@ Subject: [PATCH 04/36] Expose all hashes available to OpenSSL, using a list create mode 100644 Modules/_hashopenssl_list.h diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c -index 02cf6087a2ea..7dfd70822b99 100644 +index 02cf6087a2e..7dfd70822b9 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -66,12 +66,9 @@ static PyTypeObject EVPtype; @@ -858,7 +1643,7 @@ index 02cf6087a2ea..7dfd70822b99 100644 } diff --git a/Modules/_hashopenssl_list.h b/Modules/_hashopenssl_list.h new file mode 100644 -index 000000000000..3c11b2eb6c62 +index 00000000000..3c11b2eb6c6 --- /dev/null +++ b/Modules/_hashopenssl_list.h @@ -0,0 +1,21 @@ @@ -883,11 +1668,14 @@ index 000000000000..3c11b2eb6c62 +_HASH(sha3_512, "sha3-512") +_HASH(shake_128, "shake128") +_HASH(shake_256, "shake256") +-- +2.21.0 -From c05359891debdfd0f2b320c6c396e9baf4a9f6ab Mon Sep 17 00:00:00 2001 + +From 7e5b74b7268e4fb7d473d24cd023493e4e87eb76 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 25 Jul 2019 18:13:45 +0200 -Subject: [PATCH 05/36] Fix tests +Subject: [PATCH 08/36] Fix tests --- Lib/hashlib.py | 5 +++- @@ -895,10 +1683,10 @@ Subject: [PATCH 05/36] Fix tests 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/Lib/hashlib.py b/Lib/hashlib.py -index 7db1e02601fe..2def0a310c66 100644 +index 7db1e02601f..2def0a310c6 100644 --- a/Lib/hashlib.py +++ b/Lib/hashlib.py -@@ -122,7 +122,10 @@ def __get_builtin_constructor(name): +@@ -122,7 +122,10 @@ if not get_fips_mode(): def __get_openssl_constructor(name): if not get_fips_mode(): @@ -911,10 +1699,10 @@ index 7db1e02601fe..2def0a310c66 100644 return __get_builtin_constructor(name) try: diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py -index c67d2f6d00aa..645a3d01b91d 100644 +index 4e6b5b607a9..e57c93b42f5 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py -@@ -179,7 +179,9 @@ def test_hash_array(self): +@@ -182,7 +182,9 @@ class HashLibTestCase(unittest.TestCase): a = array.array("b", range(10)) for cons in self.hash_constructors: c = cons(a) @@ -925,7 +1713,7 @@ index c67d2f6d00aa..645a3d01b91d 100644 c.hexdigest(16) else: c.hexdigest() -@@ -226,7 +228,9 @@ def test_get_builtin_constructor(self): +@@ -229,7 +231,9 @@ class HashLibTestCase(unittest.TestCase): def test_hexdigest(self): for cons in self.hash_constructors: h = cons() @@ -936,7 +1724,7 @@ index c67d2f6d00aa..645a3d01b91d 100644 self.assertIsInstance(h.digest(16), bytes) self.assertEqual(hexstr(h.digest(16)), h.hexdigest(16)) else: -@@ -240,6 +244,8 @@ def test_digest_length_overflow(self): +@@ -243,6 +247,8 @@ class HashLibTestCase(unittest.TestCase): h = cons() if h.name not in self.shakes: continue @@ -945,7 +1733,7 @@ index c67d2f6d00aa..645a3d01b91d 100644 for digest in h.digest, h.hexdigest: with self.assertRaises((ValueError, OverflowError)): digest(-10) -@@ -269,7 +275,9 @@ def test_large_update(self): +@@ -272,7 +278,9 @@ class HashLibTestCase(unittest.TestCase): m1.update(bees) m1.update(cees) m1.update(dees) @@ -956,7 +1744,7 @@ index c67d2f6d00aa..645a3d01b91d 100644 args = (16,) else: args = () -@@ -296,15 +304,36 @@ def check(self, name, data, hexdigest, shake=False, **kwargs): +@@ -299,15 +307,36 @@ class HashLibTestCase(unittest.TestCase): # 2 is for hashlib.name(...) and hashlib.new(name, ...) self.assertGreaterEqual(len(constructors), 2) for hash_object_constructor in constructors: @@ -995,7 +1783,7 @@ index c67d2f6d00aa..645a3d01b91d 100644 digest = bytes.fromhex(hexdigest) self.assertEqual(computed, digest) if not shake: -@@ -344,12 +373,14 @@ def check_blocksize_name(self, name, block_size=0, digest_size=0, +@@ -347,12 +376,14 @@ class HashLibTestCase(unittest.TestCase): for hash_object_constructor in constructors: m = hash_object_constructor() self.assertEqual(m.block_size, block_size) @@ -1015,7 +1803,7 @@ index c67d2f6d00aa..645a3d01b91d 100644 else: self.assertEqual(len(m.digest()), digest_size) self.assertEqual(len(m.hexdigest()), 2*digest_size) -@@ -379,9 +410,10 @@ def check_sha3(self, name, capacity, rate, suffix): +@@ -382,9 +413,10 @@ class HashLibTestCase(unittest.TestCase): for hash_object_constructor in constructors: m = hash_object_constructor() self.assertEqual(capacity + rate, 1600) @@ -1029,11 +1817,14 @@ index c67d2f6d00aa..645a3d01b91d 100644 @requires_sha3 def test_extra_sha3(self): +-- +2.21.0 -From b9238e7d197c315d2c9c7aa34e5c8a4b728b25a0 Mon Sep 17 00:00:00 2001 + +From d6618795dd079acd8585f830b129d7f2fc9a6c52 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 26 Jul 2019 11:27:57 +0200 -Subject: [PATCH 06/36] Change FIPS exceptions from _blake2, _sha3 module init +Subject: [PATCH 09/36] Change FIPS exceptions from _blake2, _sha3 module init to ImportError --- @@ -1045,7 +1836,7 @@ Subject: [PATCH 06/36] Change FIPS exceptions from _blake2, _sha3 module init 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/Include/_hashopenssl.h b/Include/_hashopenssl.h -index a726c0d3fbf3..47ed00304220 100644 +index a726c0d3fbf..47ed0030422 100644 --- a/Include/_hashopenssl.h +++ b/Include/_hashopenssl.h @@ -39,7 +39,7 @@ _setException(PyObject *exc) @@ -1081,7 +1872,7 @@ index a726c0d3fbf3..47ed00304220 100644 #endif // !Py_HASHOPENSSL_H diff --git a/Modules/_blake2/blake2b_impl.c b/Modules/_blake2/blake2b_impl.c -index 341e67a8fcc4..f6bfce823b8f 100644 +index 341e67a8fcc..f6bfce823b8 100644 --- a/Modules/_blake2/blake2b_impl.c +++ b/Modules/_blake2/blake2b_impl.c @@ -104,7 +104,7 @@ py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size, @@ -1103,7 +1894,7 @@ index 341e67a8fcc4..f6bfce823b8f 100644 GET_BUFFER_VIEW_OR_ERROUT(data, &buf); diff --git a/Modules/_blake2/blake2module.c b/Modules/_blake2/blake2module.c -index 817b71656844..a9c7cbc7ebe9 100644 +index 817b7165684..a9c7cbc7ebe 100644 --- a/Modules/_blake2/blake2module.c +++ b/Modules/_blake2/blake2module.c @@ -58,7 +58,7 @@ PyInit__blake2(void) @@ -1116,7 +1907,7 @@ index 817b71656844..a9c7cbc7ebe9 100644 m = PyModule_Create(&blake2_module); if (m == NULL) diff --git a/Modules/_blake2/blake2s_impl.c b/Modules/_blake2/blake2s_impl.c -index 0dfe0586b570..28ae5b651019 100644 +index 0dfe0586b57..28ae5b65101 100644 --- a/Modules/_blake2/blake2s_impl.c +++ b/Modules/_blake2/blake2s_impl.c @@ -104,7 +104,7 @@ py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size, @@ -1138,7 +1929,7 @@ index 0dfe0586b570..28ae5b651019 100644 GET_BUFFER_VIEW_OR_ERROUT(data, &buf); diff --git a/Modules/_sha3/sha3module.c b/Modules/_sha3/sha3module.c -index 624f7f247d4f..2783a75644fc 100644 +index 624f7f247d4..2783a75644f 100644 --- a/Modules/_sha3/sha3module.c +++ b/Modules/_sha3/sha3module.c @@ -163,7 +163,7 @@ static PyTypeObject SHAKE256type; @@ -1168,18 +1959,21 @@ index 624f7f247d4f..2783a75644fc 100644 if ((m = PyModule_Create(&_SHA3module)) == NULL) { return NULL; +-- +2.21.0 -From d9cf1f68ed7c7d10846119d146583d6fd2d52143 Mon Sep 17 00:00:00 2001 + +From eb78e4b4179842185f53edba2073ab7644db7ad3 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 26 Jul 2019 11:24:09 +0200 -Subject: [PATCH 07/36] Make hashlib importable under FIPS mode +Subject: [PATCH 10/36] Make hashlib importable under FIPS mode --- Lib/hashlib.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Lib/hashlib.py b/Lib/hashlib.py -index 2def0a310c66..ca1dd2022515 100644 +index 2def0a310c6..ca1dd202251 100644 --- a/Lib/hashlib.py +++ b/Lib/hashlib.py @@ -132,12 +132,14 @@ def __get_openssl_constructor(name): @@ -1200,11 +1994,14 @@ index 2def0a310c66..ca1dd2022515 100644 return __get_builtin_constructor(name) if not get_fips_mode(): +-- +2.21.0 -From 5b21c029a9b69b06f9ef245264db2ddd227011f9 Mon Sep 17 00:00:00 2001 + +From 0f313f65457f1e7d0e7238a71935f5d4e0d197ee Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 26 Jul 2019 15:41:10 +0200 -Subject: [PATCH 08/36] Implement hmac.new using new built-in module, +Subject: [PATCH 11/36] Implement hmac.new using new built-in module, _hmacopenssl --- @@ -1217,10 +2014,10 @@ Subject: [PATCH 08/36] Implement hmac.new using new built-in module, create mode 100644 Modules/clinic/_hmacopenssl.c.h diff --git a/Lib/hmac.py b/Lib/hmac.py -index 121029aa670b..ed98406bd2e1 100644 +index 121029aa670..ed98406bd2e 100644 --- a/Lib/hmac.py +++ b/Lib/hmac.py -@@ -6,6 +6,8 @@ +@@ -6,6 +6,8 @@ Implements the HMAC algorithm as described by RFC 2104. import warnings as _warnings from _operator import _compare_digest as compare_digest import hashlib as _hashlib @@ -1229,7 +2026,7 @@ index 121029aa670b..ed98406bd2e1 100644 trans_5C = bytes((x ^ 0x5C) for x in range(256)) trans_36 = bytes((x ^ 0x36) for x in range(256)) -@@ -37,6 +39,11 @@ def __init__(self, key, msg = None, digestmod = None): +@@ -37,6 +39,11 @@ class HMAC: Note: key and msg must be a bytes or bytearray objects. """ @@ -1241,7 +2038,7 @@ index 121029aa670b..ed98406bd2e1 100644 if not isinstance(key, (bytes, bytearray)): raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__) -@@ -90,6 +97,8 @@ def name(self): +@@ -90,6 +97,8 @@ class HMAC: def update(self, msg): """Update this hashing object with the string msg. """ @@ -1250,7 +2047,7 @@ index 121029aa670b..ed98406bd2e1 100644 self.inner.update(msg) def copy(self): -@@ -130,6 +139,19 @@ def hexdigest(self): +@@ -130,6 +139,19 @@ class HMAC: h = self._current() return h.hexdigest() @@ -1287,7 +2084,7 @@ index 121029aa670b..ed98406bd2e1 100644 + return HMAC(key, msg, digestmod) diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c new file mode 100644 -index 000000000000..ca95d725f019 +index 00000000000..ca95d725f01 --- /dev/null +++ b/Modules/_hmacopenssl.c @@ -0,0 +1,396 @@ @@ -1689,7 +2486,7 @@ index 000000000000..ca95d725f019 +} diff --git a/Modules/clinic/_hmacopenssl.c.h b/Modules/clinic/_hmacopenssl.c.h new file mode 100644 -index 000000000000..b472a6eddd34 +index 00000000000..b472a6eddd3 --- /dev/null +++ b/Modules/clinic/_hmacopenssl.c.h @@ -0,0 +1,133 @@ @@ -1827,10 +2624,10 @@ index 000000000000..b472a6eddd34 +} +/*[clinic end generated code: output=10b6e8cac6d7a2c9 input=a9049054013a1b77]*/ diff --git a/setup.py b/setup.py -index e2e659ef7950..282aa4178ed3 100644 +index e2e659ef795..282aa4178ed 100644 --- a/setup.py +++ b/setup.py -@@ -922,6 +922,10 @@ def detect_modules(self): +@@ -922,6 +922,10 @@ class PyBuildExt(build_ext): openssl_ver) missing.append('_hashlib') @@ -1841,11 +2638,14 @@ index e2e659ef7950..282aa4178ed3 100644 # RHEL: Always force OpenSSL for md5, sha1, sha256, sha512; # don't build Python's implementations. # sha3 and blake2 have extra functionality, so do build those: +-- +2.21.0 -From 7eb3d47afdad9052f505ecbbbfab065dbbc240e0 Mon Sep 17 00:00:00 2001 + +From 37797b4d89e7b4859dc4728da91cbebf5fdb2a52 Mon Sep 17 00:00:00 2001 From: Marcel Plch Date: Mon, 29 Jul 2019 12:45:11 +0200 -Subject: [PATCH 09/36] FIPS review +Subject: [PATCH 12/36] FIPS review * Port _hmacopenssl to multiphase init. * Make _hmacopenssl.HMAC.copy create same type as self. @@ -1856,10 +2656,10 @@ Subject: [PATCH 09/36] FIPS review 2 files changed, 70 insertions(+), 44 deletions(-) diff --git a/Lib/hmac.py b/Lib/hmac.py -index ed98406bd2e1..b9bf16b84ca0 100644 +index ed98406bd2e..b9bf16b84ca 100644 --- a/Lib/hmac.py +++ b/Lib/hmac.py -@@ -42,7 +42,7 @@ def __init__(self, key, msg = None, digestmod = None): +@@ -42,7 +42,7 @@ class HMAC: if _hashlib.get_fips_mode(): raise ValueError( 'hmac.HMAC is not available in FIPS mode. ' @@ -1869,7 +2669,7 @@ index ed98406bd2e1..b9bf16b84ca0 100644 if not isinstance(key, (bytes, bytearray)): diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c -index ca95d725f019..216ed04f2360 100644 +index ca95d725f01..216ed04f236 100644 --- a/Modules/_hmacopenssl.c +++ b/Modules/_hmacopenssl.c @@ -24,7 +24,10 @@ @@ -2053,11 +2853,14 @@ index ca95d725f019..216ed04f2360 100644 +{ + return PyModuleDef_Init(&_hmacopenssl_def); } +-- +2.21.0 -From 641e76725f2660da75490ea0c10da52688093778 Mon Sep 17 00:00:00 2001 + +From 9a3bf73d382cda99a665cab8438f3cd0388256b0 Mon Sep 17 00:00:00 2001 From: Marcel Plch Date: Mon, 29 Jul 2019 13:05:04 +0200 -Subject: [PATCH 10/36] revert cosmetic nitpick and remove trailing whitespace +Subject: [PATCH 13/36] revert cosmetic nitpick and remove trailing whitespace --- Lib/hmac.py | 2 +- @@ -2065,10 +2868,10 @@ Subject: [PATCH 10/36] revert cosmetic nitpick and remove trailing whitespace 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/hmac.py b/Lib/hmac.py -index b9bf16b84ca0..ed98406bd2e1 100644 +index b9bf16b84ca..ed98406bd2e 100644 --- a/Lib/hmac.py +++ b/Lib/hmac.py -@@ -42,7 +42,7 @@ def __init__(self, key, msg = None, digestmod = None): +@@ -42,7 +42,7 @@ class HMAC: if _hashlib.get_fips_mode(): raise ValueError( 'hmac.HMAC is not available in FIPS mode. ' @@ -2078,7 +2881,7 @@ index b9bf16b84ca0..ed98406bd2e1 100644 if not isinstance(key, (bytes, bytearray)): diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c -index 216ed04f2360..221714ca4349 100644 +index 216ed04f236..221714ca434 100644 --- a/Modules/_hmacopenssl.c +++ b/Modules/_hmacopenssl.c @@ -363,7 +363,7 @@ static PyType_Slot HmacType_slots[] = { @@ -2099,11 +2902,14 @@ index 216ed04f2360..221714ca4349 100644 .m_name = "_hmacopenssl", .m_methods = hmacopenssl_functions, .m_slots = hmacopenssl_slots, +-- +2.21.0 -From 0a1522aacb0b070632f7feaad6f92bfe8fc9c89b Mon Sep 17 00:00:00 2001 + +From b2853963d35c60595cec7e5cd40f31b1c9c59426 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Wed, 31 Jul 2019 15:43:43 +0200 -Subject: [PATCH 11/36] Add initial tests for various hashes under FIPS mode +Subject: [PATCH 14/36] Add initial tests for various hashes under FIPS mode --- Lib/test/test_fips.py | 64 +++++++++++++++++++++++++++++++++++++++++++ @@ -2112,7 +2918,7 @@ Subject: [PATCH 11/36] Add initial tests for various hashes under FIPS mode diff --git a/Lib/test/test_fips.py b/Lib/test/test_fips.py new file mode 100644 -index 000000000000..bee911ef405a +index 00000000000..bee911ef405 --- /dev/null +++ b/Lib/test/test_fips.py @@ -0,0 +1,64 @@ @@ -2180,18 +2986,21 @@ index 000000000000..bee911ef405a + +if __name__ == "__main__": + unittest.main() +-- +2.21.0 -From f20b01bb18523587cb5beedc67a8ee08a502788d Mon Sep 17 00:00:00 2001 + +From b3a8214b5afe4809983e6a5e5d339527e8238318 Mon Sep 17 00:00:00 2001 From: Marcel Plch Date: Thu, 1 Aug 2019 16:39:37 +0200 -Subject: [PATCH 12/36] Initialize HMAC type. +Subject: [PATCH 15/36] Initialize HMAC type. --- Modules/_hmacopenssl.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c -index 221714ca4349..239445a0831b 100644 +index 221714ca434..239445a0831 100644 --- a/Modules/_hmacopenssl.c +++ b/Modules/_hmacopenssl.c @@ -22,12 +22,12 @@ @@ -2246,11 +3055,14 @@ index 221714ca4349..239445a0831b 100644 return 0; fail: +-- +2.21.0 -From b819ca654873ea36144ce1cb6f8c422a6d2f5d7d Mon Sep 17 00:00:00 2001 + +From 5bd6eb14097fe4ff2bb639e5c50260b1379d0a69 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 1 Aug 2019 17:57:05 +0200 -Subject: [PATCH 13/36] Use a stronger hash in multiprocessing handshake +Subject: [PATCH 16/36] Use a stronger hash in multiprocessing handshake Adapted from patch by David Malcolm, https://bugs.python.org/issue17258 @@ -2259,10 +3071,10 @@ https://bugs.python.org/issue17258 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py -index d3797503a755..a0b1538f88b3 100644 +index d3797503a75..a0b1538f88b 100644 --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py -@@ -42,6 +42,10 @@ +@@ -42,6 +42,10 @@ BUFSIZE = 8192 # A very generous timeout when it comes to local connections... CONNECTION_TIMEOUT = 20. @@ -2291,18 +3103,21 @@ index d3797503a755..a0b1538f88b3 100644 connection.send_bytes(digest) response = connection.recv_bytes(256) # reject large message if response != WELCOME: +-- +2.21.0 -From 01950bb63c0a52faf5304e3978a6308641305a03 Mon Sep 17 00:00:00 2001 + +From 1dd4b2d6c4797b828ac38d8c62f1e69fce49f1e9 Mon Sep 17 00:00:00 2001 From: Marcel Plch Date: Fri, 2 Aug 2019 17:36:01 +0200 -Subject: [PATCH 14/36] Fix refcounting +Subject: [PATCH 17/36] Fix refcounting --- Modules/_hmacopenssl.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c -index 239445a0831b..9c2882833d1c 100644 +index 239445a0831..9c2882833d1 100644 --- a/Modules/_hmacopenssl.c +++ b/Modules/_hmacopenssl.c @@ -373,6 +373,34 @@ static struct PyMethodDef hmacopenssl_functions[] = { @@ -2362,18 +3177,21 @@ index 239445a0831b..9c2882833d1c 100644 }; +-- +2.21.0 -From 823eae4610e3235f60a89715ba37a970c18a7c0b Mon Sep 17 00:00:00 2001 + +From 4e1351cc2d704e8da7bb8125ad0ab194e8a02ec4 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 5 Aug 2019 13:37:05 +0200 -Subject: [PATCH 15/36] hmac: Don't default to md5 in FIPS mode +Subject: [PATCH 18/36] hmac: Don't default to md5 in FIPS mode --- Lib/hmac.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/hmac.py b/Lib/hmac.py -index ed98406bd2e1..7b8821edd582 100644 +index ed98406bd2e..7b8821edd58 100644 --- a/Lib/hmac.py +++ b/Lib/hmac.py @@ -165,7 +165,7 @@ def new(key, msg = None, digestmod = None): @@ -2385,11 +3203,14 @@ index ed98406bd2e1..7b8821edd582 100644 name = _get_openssl_name(digestmod) result = _hmacopenssl.new(key, digestmod=name) if msg: +-- +2.21.0 -From fd74d1c00d95542eef3c238f990da5bc7fc05619 Mon Sep 17 00:00:00 2001 + +From ea44160c242101f14d22242a0722e730ef304b8b Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 5 Aug 2019 14:20:58 +0200 -Subject: [PATCH 16/36] Make _hmacopenssl.HMAC subclassable; subclass it as +Subject: [PATCH 19/36] Make _hmacopenssl.HMAC subclassable; subclass it as hmac.HMAC under FIPS This removes the _hmacopenssl.new function. @@ -2401,10 +3222,10 @@ This removes the _hmacopenssl.new function. 4 files changed, 56 insertions(+), 87 deletions(-) diff --git a/Lib/hmac.py b/Lib/hmac.py -index 7b8821edd582..d479c5a4492f 100644 +index 7b8821edd58..d479c5a4492 100644 --- a/Lib/hmac.py +++ b/Lib/hmac.py -@@ -141,6 +141,8 @@ def hexdigest(self): +@@ -141,6 +141,8 @@ class HMAC: def _get_openssl_name(digestmod): @@ -2450,10 +3271,10 @@ index 7b8821edd582..d479c5a4492f 100644 - return HMAC(key, msg, digestmod) + return HMAC(key, msg, digestmod) diff --git a/Lib/test/test_fips.py b/Lib/test/test_fips.py -index bee911ef405a..34812e6098ae 100644 +index bee911ef405..34812e6098a 100644 --- a/Lib/test/test_fips.py +++ b/Lib/test/test_fips.py -@@ -54,7 +54,7 @@ def test_sha(self): +@@ -54,7 +54,7 @@ class HashlibFipsTests(unittest.TestCase): self.compare_hashes(hashlib.sha512(b'abc'), _hashlib.openssl_sha512(b'abc')) def test_hmac_digests(self): @@ -2463,7 +3284,7 @@ index bee911ef405a..34812e6098ae 100644 diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c -index 9c2882833d1c..7d3d9739f3ab 100644 +index 9c2882833d1..7d3d9739f3a 100644 --- a/Modules/_hmacopenssl.c +++ b/Modules/_hmacopenssl.c @@ -41,33 +41,25 @@ typedef struct { @@ -2535,7 +3356,7 @@ index 9c2882833d1c..7d3d9739f3ab 100644 if (retval == NULL) { goto error; } -@@ -130,6 +125,7 @@ _hmacopenssl_new_impl(PyObject *module, Py_buffer *key, +@@ -130,6 +125,7 @@ error: if (ctx) HMAC_CTX_free(ctx); if (name) Py_DECREF(name); if (retval) PyObject_Del(name); @@ -2618,7 +3439,7 @@ index 9c2882833d1c..7d3d9739f3ab 100644 .m_size = sizeof(hmacopenssl_state), .m_traverse = hmacopenssl_traverse, diff --git a/Modules/clinic/_hmacopenssl.c.h b/Modules/clinic/_hmacopenssl.c.h -index b472a6eddd34..861acc11bfd9 100644 +index b472a6eddd3..861acc11bfd 100644 --- a/Modules/clinic/_hmacopenssl.c.h +++ b/Modules/clinic/_hmacopenssl.c.h @@ -2,43 +2,6 @@ @@ -2671,18 +3492,21 @@ index b472a6eddd34..861acc11bfd9 100644 } -/*[clinic end generated code: output=10b6e8cac6d7a2c9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d93ad460795d49b5 input=a9049054013a1b77]*/ +-- +2.21.0 -From d3b322a12c10890fee2bc4837a3d37f0a81455a6 Mon Sep 17 00:00:00 2001 + +From e3d6a5adbe0032726dff0b1f6473ce3ff63fad51 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 5 Aug 2019 16:10:36 +0200 -Subject: [PATCH 17/36] Fix _hmacopenssl.HMAC.block_size +Subject: [PATCH 20/36] Fix _hmacopenssl.HMAC.block_size --- Modules/_hmacopenssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c -index 7d3d9739f3ab..a24c8ba0229d 100644 +index 7d3d9739f3a..a24c8ba0229 100644 --- a/Modules/_hmacopenssl.c +++ b/Modules/_hmacopenssl.c @@ -318,7 +318,7 @@ _hmacopenssl_get_block_size(HmacObject *self, void *closure) @@ -2694,42 +3518,14 @@ index 7d3d9739f3ab..a24c8ba0229d 100644 } static PyMethodDef Hmac_methods[] = { +-- +2.21.0 -From e643e9c61bce62bcc3caed8c022f1afee979feb8 Mon Sep 17 00:00:00 2001 -From: Petr Viktorin -Date: Mon, 5 Aug 2019 14:45:52 +0200 -Subject: [PATCH 18/36] Skip hanging test ---- - Lib/test/test_logging.py | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py -index 763a5d1df0e3..0b229465983c 100644 ---- a/Lib/test/test_logging.py -+++ b/Lib/test/test_logging.py -@@ -46,6 +46,8 @@ - import unittest - import warnings - import weakref -+import hashlib -+ - try: - import threading - # The following imports are needed only for tests which -@@ -1815,6 +1817,7 @@ def handle_request(self, request): - request.end_headers() - self.handled.set() - -+ @unittest.skipIf(hashlib.get_fips_mode(), 'Hangs in FIPS mode.') - def test_output(self): - # The log message sent to the HTTPHandler is properly received. - logger = logging.getLogger("http") - -From 30e11ab9d19beea8dafe96da7f47bf1513849f3d Mon Sep 17 00:00:00 2001 +From f925a1165d7b07fb4d0bba216f7dbc387b94e94d Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 5 Aug 2019 15:02:08 +0200 -Subject: [PATCH 19/36] distutils upload: Skip md5 checksum in FIPS mode +Subject: [PATCH 21/36] distutils upload: Skip md5 checksum in FIPS mode --- Lib/distutils/command/upload.py | 11 ++++++++++- @@ -2737,10 +3533,10 @@ Subject: [PATCH 19/36] distutils upload: Skip md5 checksum in FIPS mode 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Lib/distutils/command/upload.py b/Lib/distutils/command/upload.py -index 32dda359badb..0edb39efd4cb 100644 +index 32dda359bad..0edb39efd4c 100644 --- a/Lib/distutils/command/upload.py +++ b/Lib/distutils/command/upload.py -@@ -102,7 +102,6 @@ def upload_file(self, command, pyversion, filename): +@@ -102,7 +102,6 @@ class upload(PyPIRCCommand): 'content': (os.path.basename(filename),content), 'filetype': command, 'pyversion': pyversion, @@ -2748,7 +3544,7 @@ index 32dda359badb..0edb39efd4cb 100644 # additional meta-data 'metadata_version': '1.0', -@@ -121,6 +120,16 @@ def upload_file(self, command, pyversion, filename): +@@ -121,6 +120,16 @@ class upload(PyPIRCCommand): 'requires': meta.get_requires(), 'obsoletes': meta.get_obsoletes(), } @@ -2766,10 +3562,10 @@ index 32dda359badb..0edb39efd4cb 100644 if command == 'bdist_rpm': dist, version, id = platform.dist() diff --git a/Lib/distutils/tests/test_upload.py b/Lib/distutils/tests/test_upload.py -index c17d8e7d54e9..b4b64e97737d 100644 +index c17d8e7d54e..b4b64e97737 100644 --- a/Lib/distutils/tests/test_upload.py +++ b/Lib/distutils/tests/test_upload.py -@@ -3,6 +3,7 @@ +@@ -3,6 +3,7 @@ import os import unittest import unittest.mock as mock from urllib.request import HTTPError @@ -2777,7 +3573,7 @@ index c17d8e7d54e9..b4b64e97737d 100644 from test.support import run_unittest -@@ -130,7 +131,11 @@ def test_upload(self): +@@ -130,7 +131,11 @@ class uploadTestCase(BasePyPIRCCommandTestCase): # what did we send ? headers = dict(self.last_open.req.headers) @@ -2790,7 +3586,7 @@ index c17d8e7d54e9..b4b64e97737d 100644 content_type = headers['Content-type'] self.assertTrue(content_type.startswith('multipart/form-data')) self.assertEqual(self.last_open.req.get_method(), 'POST') -@@ -166,7 +171,11 @@ def test_upload_correct_cr(self): +@@ -166,7 +171,11 @@ class uploadTestCase(BasePyPIRCCommandTestCase): cmd.run() headers = dict(self.last_open.req.headers) @@ -2803,19 +3599,22 @@ index c17d8e7d54e9..b4b64e97737d 100644 self.assertIn(b'long description\r', self.last_open.req.data) def test_upload_fails(self): +-- +2.21.0 -From 8eb2ce39572904704ada072e25d8e6bf5727f492 Mon Sep 17 00:00:00 2001 + +From 936a7835a1873952eab8f7ec3b9b67f63786c001 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 5 Aug 2019 15:32:25 +0200 -Subject: [PATCH 20/36] Fix HMAC tests on FIPS mode +Subject: [PATCH 22/36] Fix HMAC tests on FIPS mode --- Lib/hmac.py | 3 +++ - Lib/test/test_hmac.py | 50 ++++++++++++++++++++++++++++++++++--------- - 2 files changed, 43 insertions(+), 10 deletions(-) + Lib/test/test_hmac.py | 26 ++++++++++++++++++++++++++ + 2 files changed, 29 insertions(+) diff --git a/Lib/hmac.py b/Lib/hmac.py -index d479c5a4492f..7af94c39ed63 100644 +index d479c5a4492..7af94c39ed6 100644 --- a/Lib/hmac.py +++ b/Lib/hmac.py @@ -157,6 +157,9 @@ def _get_openssl_name(digestmod): @@ -2829,45 +3628,21 @@ index d479c5a4492f..7af94c39ed63 100644 result = _hmacopenssl.HMAC.__new__(cls, key, digestmod=name) if msg: diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py -index 067e13f1079a..6f53a6d1fd5b 100644 +index 338e0215a41..5b090727ef6 100644 --- a/Lib/test/test_hmac.py +++ b/Lib/test/test_hmac.py -@@ -17,6 +17,7 @@ def wrapper(*args, **kwargs): - - class TestVectorsTestCase(unittest.TestCase): - -+ @unittest.skipIf(hashlib.get_fips_mode(), 'md5 unacceptable in FIPS mode.') - def test_md5_vectors(self): - # Test the HMAC module against test vectors from the RFC. - -@@ -242,6 +243,7 @@ def test_sha384_rfc4231(self): +@@ -250,6 +250,7 @@ class TestVectorsTestCase(unittest.TestCase): def test_sha512_rfc4231(self): self._rfc4231_test_cases(hashlib.sha512, 'sha512', 64, 128) + @unittest.skipIf(hashlib.get_fips_mode(), 'MockCrazyHash unacceptable in FIPS mode.') + @requires_hashdigest('sha256') def test_legacy_block_size_warnings(self): class MockCrazyHash(object): - """Ain't no block_size attribute here.""" -@@ -264,6 +266,7 @@ def digest(self): - hmac.HMAC(b'a', b'b', digestmod=MockCrazyHash) - self.fail('Expected warning about small block_size') - -+ @unittest.skipIf(hashlib.get_fips_mode(), 'md5 is not default in FIPS mode.') - def test_with_digestmod_warning(self): - with self.assertWarns(PendingDeprecationWarning): - key = b"\x0b" * 16 -@@ -275,6 +278,7 @@ def test_with_digestmod_warning(self): - - class ConstructorTestCase(unittest.TestCase): - -+ @unittest.skipIf(hashlib.get_fips_mode(), 'md5 is not default in FIPS mode.') - @ignore_warning - def test_normal(self): - # Standard constructor call. -@@ -284,6 +288,14 @@ def test_normal(self): - except Exception: +@@ -298,6 +299,14 @@ class ConstructorTestCase(unittest.TestCase): self.fail("Standard constructor call raised exception.") + @ignore_warning + def test_normal_digestmod(self): + # Standard constructor call. + failed = 0 @@ -2876,83 +3651,26 @@ index 067e13f1079a..6f53a6d1fd5b 100644 + except Exception: + self.fail("Standard constructor call raised exception.") + - @ignore_warning + @requires_hashdigest('sha256') def test_with_str_key(self): # Pass a key of type str, which is an error, because it expects a key -@@ -302,25 +314,25 @@ def test_dot_new_with_str_key(self): - def test_withtext(self): - # Constructor call with text. - try: -- h = hmac.HMAC(b"key", b"hash this!") -+ h = hmac.HMAC(b"key", b"hash this!", digestmod='sha1') - except Exception: - self.fail("Constructor call with text argument raised exception.") -- self.assertEqual(h.hexdigest(), '34325b639da4cfd95735b381e28cb864') -+ self.assertEqual(h.hexdigest(), '3f2e20f3e2f006270db98760b9725a008c5bd114') - - def test_with_bytearray(self): - try: - h = hmac.HMAC(bytearray(b"key"), bytearray(b"hash this!"), -- digestmod="md5") -+ digestmod="sha1") - except Exception: - self.fail("Constructor call with bytearray arguments raised exception.") -- self.assertEqual(h.hexdigest(), '34325b639da4cfd95735b381e28cb864') -+ self.assertEqual(h.hexdigest(), '3f2e20f3e2f006270db98760b9725a008c5bd114') - - def test_with_memoryview_msg(self): - try: -- h = hmac.HMAC(b"key", memoryview(b"hash this!"), digestmod="md5") -+ h = hmac.HMAC(b"key", memoryview(b"hash this!"), digestmod="sha1") - except Exception: - self.fail("Constructor call with memoryview msg raised exception.") -- self.assertEqual(h.hexdigest(), '34325b639da4cfd95735b381e28cb864') -+ self.assertEqual(h.hexdigest(), '3f2e20f3e2f006270db98760b9725a008c5bd114') - - def test_withmodule(self): - # Constructor call with text and digest module. -@@ -331,6 +343,7 @@ def test_withmodule(self): - - class SanityTestCase(unittest.TestCase): - -+ @unittest.skipIf(hashlib.get_fips_mode(), "md5 is not default in FIPS mode") - @ignore_warning - def test_default_is_md5(self): - # Testing if HMAC defaults to MD5 algorithm. -@@ -342,7 +355,7 @@ def test_exercise_all_methods(self): - # Exercising all methods once. - # This must not raise any exceptions - try: -- h = hmac.HMAC(b"my secret key", digestmod="md5") -+ h = hmac.HMAC(b"my secret key", digestmod="sha1") - h.update(b"compute the hash of this text!") - dig = h.digest() - dig = h.hexdigest() -@@ -352,9 +365,10 @@ def test_exercise_all_methods(self): +@@ -366,6 +375,7 @@ class SanityTestCase(unittest.TestCase): class CopyTestCase(unittest.TestCase): + @unittest.skipIf(hashlib.get_fips_mode(), "Internal attributes unavailable in FIPS mode") + @requires_hashdigest('sha256') def test_attributes(self): # Testing if attributes are of same type. -- h1 = hmac.HMAC(b"key", digestmod="md5") -+ h1 = hmac.HMAC(b"key", digestmod="sha1") - h2 = h1.copy() - self.assertTrue(h1.digest_cons == h2.digest_cons, - "digest constructors don't match.") -@@ -363,9 +377,10 @@ def test_attributes(self): +@@ -378,6 +388,7 @@ class CopyTestCase(unittest.TestCase): self.assertEqual(type(h1.outer), type(h2.outer), "Types of outer don't match.") + @unittest.skipIf(hashlib.get_fips_mode(), "Internal attributes unavailable in FIPS mode") + @requires_hashdigest('sha256') def test_realcopy(self): # Testing if the copy method created a real copy. -- h1 = hmac.HMAC(b"key", digestmod="md5") -+ h1 = hmac.HMAC(b"key", digestmod="sha1") - h2 = h1.copy() - # Using id() in case somebody has overridden __eq__/__ne__. - self.assertTrue(id(h1) != id(h2), "No real copy of the HMAC instance.") -@@ -374,9 +389,24 @@ def test_realcopy(self): +@@ -390,6 +401,21 @@ class CopyTestCase(unittest.TestCase): self.assertTrue(id(h1.outer) != id(h2.outer), "No real copy of the attribute 'outer'.") @@ -2971,247 +3689,14 @@ index 067e13f1079a..6f53a6d1fd5b 100644 + h2.update(b'hi') + assert h1.digest() == h2.digest() == new_digest + + @requires_hashdigest('sha256') def test_equality(self): # Testing if the copy has the same digests. -- h1 = hmac.HMAC(b"key", digestmod="md5") -+ h1 = hmac.HMAC(b"key", digestmod="sha1") - h1.update(b"some random text") - h2 = h1.copy() - self.assertEqual(h1.digest(), h2.digest(), +-- +2.21.0 -From d7ac1f3fe2f7024d582ba9d0f10008499f832b76 Mon Sep 17 00:00:00 2001 -From: Petr Viktorin -Date: Mon, 5 Aug 2019 16:24:40 +0200 -Subject: [PATCH 21/36] test_smtplib: Skip tests of CRAM-MD5 auth ---- - Lib/test/test_smtplib.py | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py -index 87047514e7aa..150e9fbcf053 100644 ---- a/Lib/test/test_smtplib.py -+++ b/Lib/test/test_smtplib.py -@@ -15,6 +15,7 @@ - import select - import errno - import textwrap -+import hashlib - - import unittest - from test import support, mock_socket -@@ -968,6 +969,7 @@ def testAUTH_LOGIN(self): - self.assertEqual(resp, (235, b'Authentication Succeeded')) - smtp.close() - -+ @unittest.skipIf(hashlib.get_fips_mode(), "md5 auth unacceptable in FIPS mode") - def testAUTH_CRAM_MD5(self): - self.serv.add_feature("AUTH CRAM-MD5") - smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) -@@ -975,6 +977,7 @@ def testAUTH_CRAM_MD5(self): - self.assertEqual(resp, (235, b'Authentication Succeeded')) - smtp.close() - -+ @unittest.skipIf(hashlib.get_fips_mode(), "md5 auth unacceptable in FIPS mode") - def testAUTH_multiple(self): - # Test that multiple authentication methods are tried. - self.serv.add_feature("AUTH BOGUS PLAIN LOGIN CRAM-MD5") -@@ -983,6 +986,7 @@ def testAUTH_multiple(self): - self.assertEqual(resp, (235, b'Authentication Succeeded')) - smtp.close() - -+ @unittest.skipIf(hashlib.get_fips_mode(), "md5 auth unacceptable in FIPS mode") - def test_auth_function(self): - supported = {'CRAM-MD5', 'PLAIN', 'LOGIN'} - for mechanism in supported: - -From d1e2300f593d8c32bd3d23cd43eae02192e3eb03 Mon Sep 17 00:00:00 2001 -From: Petr Viktorin -Date: Mon, 5 Aug 2019 16:34:49 +0200 -Subject: [PATCH 22/36] test_tarfile: Replace md5 checksums with sha1 - ---- - Lib/test/test_tarfile.py | 50 ++++++++++++++++++++-------------------- - 1 file changed, 25 insertions(+), 25 deletions(-) - -diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py -index 4cd7d5370f58..c8c8eebd3194 100644 ---- a/Lib/test/test_tarfile.py -+++ b/Lib/test/test_tarfile.py -@@ -1,7 +1,7 @@ - import sys - import os - import io --from hashlib import md5 -+from hashlib import sha1 - from contextlib import contextmanager - from random import Random - import pathlib -@@ -27,8 +27,8 @@ - except ImportError: - lzma = None - --def md5sum(data): -- return md5(data).hexdigest() -+def sha1sum(data): -+ return sha1(data).hexdigest() - - TEMPDIR = os.path.abspath(support.TESTFN) + "-tardir" - tarextdir = TEMPDIR + '-extract-test' -@@ -39,8 +39,8 @@ def md5sum(data): - tmpname = os.path.join(TEMPDIR, "tmp.tar") - dotlessname = os.path.join(TEMPDIR, "testtar") - --md5_regtype = "65f477c818ad9e15f7feab0c6d37742f" --md5_sparse = "a54fbc4ca4f4399a90e1b27164012fc6" -+sha1_regtype = "bc5bb0da4d26c3e37a76d2fbf89a2a9972aeceaa" -+sha1_sparse = "693f6a770ef62ebdffc5666bd426b9506e6d8285" - - - class TarTest: -@@ -95,7 +95,7 @@ def test_fileobj_regular_file(self): - data = fobj.read() - self.assertEqual(len(data), tarinfo.size, - "regular file extraction failed") -- self.assertEqual(md5sum(data), md5_regtype, -+ self.assertEqual(sha1sum(data), sha1_regtype, - "regular file extraction failed") - - def test_fileobj_readlines(self): -@@ -180,7 +180,7 @@ def test_fileobj_text(self): - with self.tar.extractfile("ustar/regtype") as fobj: - fobj = io.TextIOWrapper(fobj) - data = fobj.read().encode("iso8859-1") -- self.assertEqual(md5sum(data), md5_regtype) -+ self.assertEqual(sha1sum(data), sha1_regtype) - try: - fobj.seek(100) - except AttributeError: -@@ -546,13 +546,13 @@ def test_extract_hardlink(self): - self.addCleanup(support.unlink, os.path.join(TEMPDIR, "ustar/lnktype")) - with open(os.path.join(TEMPDIR, "ustar/lnktype"), "rb") as f: - data = f.read() -- self.assertEqual(md5sum(data), md5_regtype) -+ self.assertEqual(sha1sum(data), sha1_regtype) - - tar.extract("ustar/symtype", TEMPDIR) - self.addCleanup(support.unlink, os.path.join(TEMPDIR, "ustar/symtype")) - with open(os.path.join(TEMPDIR, "ustar/symtype"), "rb") as f: - data = f.read() -- self.assertEqual(md5sum(data), md5_regtype) -+ self.assertEqual(sha1sum(data), sha1_regtype) - - def test_extractall(self): - # Test if extractall() correctly restores directory permissions -@@ -687,7 +687,7 @@ def test_fileobj_regular_file(self): - data = fobj.read() - self.assertEqual(len(data), tarinfo.size, - "regular file extraction failed") -- self.assertEqual(md5sum(data), md5_regtype, -+ self.assertEqual(sha1sum(data), sha1_regtype, - "regular file extraction failed") - - def test_provoke_stream_error(self): -@@ -799,8 +799,8 @@ class MemberReadTest(ReadTest, unittest.TestCase): - def _test_member(self, tarinfo, chksum=None, **kwargs): - if chksum is not None: - with self.tar.extractfile(tarinfo) as f: -- self.assertEqual(md5sum(f.read()), chksum, -- "wrong md5sum for %s" % tarinfo.name) -+ self.assertEqual(sha1sum(f.read()), chksum, -+ "wrong sha1sum for %s" % tarinfo.name) - - kwargs["mtime"] = 0o7606136617 - kwargs["uid"] = 1000 -@@ -815,11 +815,11 @@ def _test_member(self, tarinfo, chksum=None, **kwargs): - - def test_find_regtype(self): - tarinfo = self.tar.getmember("ustar/regtype") -- self._test_member(tarinfo, size=7011, chksum=md5_regtype) -+ self._test_member(tarinfo, size=7011, chksum=sha1_regtype) - - def test_find_conttype(self): - tarinfo = self.tar.getmember("ustar/conttype") -- self._test_member(tarinfo, size=7011, chksum=md5_regtype) -+ self._test_member(tarinfo, size=7011, chksum=sha1_regtype) - - def test_find_dirtype(self): - tarinfo = self.tar.getmember("ustar/dirtype") -@@ -851,28 +851,28 @@ def test_find_fifotype(self): - - def test_find_sparse(self): - tarinfo = self.tar.getmember("ustar/sparse") -- self._test_member(tarinfo, size=86016, chksum=md5_sparse) -+ self._test_member(tarinfo, size=86016, chksum=sha1_sparse) - - def test_find_gnusparse(self): - tarinfo = self.tar.getmember("gnu/sparse") -- self._test_member(tarinfo, size=86016, chksum=md5_sparse) -+ self._test_member(tarinfo, size=86016, chksum=sha1_sparse) - - def test_find_gnusparse_00(self): - tarinfo = self.tar.getmember("gnu/sparse-0.0") -- self._test_member(tarinfo, size=86016, chksum=md5_sparse) -+ self._test_member(tarinfo, size=86016, chksum=sha1_sparse) - - def test_find_gnusparse_01(self): - tarinfo = self.tar.getmember("gnu/sparse-0.1") -- self._test_member(tarinfo, size=86016, chksum=md5_sparse) -+ self._test_member(tarinfo, size=86016, chksum=sha1_sparse) - - def test_find_gnusparse_10(self): - tarinfo = self.tar.getmember("gnu/sparse-1.0") -- self._test_member(tarinfo, size=86016, chksum=md5_sparse) -+ self._test_member(tarinfo, size=86016, chksum=sha1_sparse) - - def test_find_umlauts(self): - tarinfo = self.tar.getmember("ustar/umlauts-" - "\xc4\xd6\xdc\xe4\xf6\xfc\xdf") -- self._test_member(tarinfo, size=7011, chksum=md5_regtype) -+ self._test_member(tarinfo, size=7011, chksum=sha1_regtype) - - def test_find_ustar_longname(self): - name = "ustar/" + "12345/" * 39 + "1234567/longname" -@@ -880,7 +880,7 @@ def test_find_ustar_longname(self): - - def test_find_regtype_oldv7(self): - tarinfo = self.tar.getmember("misc/regtype-old-v7") -- self._test_member(tarinfo, size=7011, chksum=md5_regtype) -+ self._test_member(tarinfo, size=7011, chksum=sha1_regtype) - - def test_find_pax_umlauts(self): - self.tar.close() -@@ -888,7 +888,7 @@ def test_find_pax_umlauts(self): - encoding="iso8859-1") - tarinfo = self.tar.getmember("pax/umlauts-" - "\xc4\xd6\xdc\xe4\xf6\xfc\xdf") -- self._test_member(tarinfo, size=7011, chksum=md5_regtype) -+ self._test_member(tarinfo, size=7011, chksum=sha1_regtype) - - - class LongnameTest: -@@ -950,8 +950,8 @@ def _test_sparse_file(self, name): - filename = os.path.join(TEMPDIR, name) - with open(filename, "rb") as fobj: - data = fobj.read() -- self.assertEqual(md5sum(data), md5_sparse, -- "wrong md5sum for %s" % name) -+ self.assertEqual(sha1sum(data), sha1_sparse, -+ "wrong sha1sum for %s" % name) - - if self._fs_supports_holes(): - s = os.stat(filename) -@@ -2431,7 +2431,7 @@ def _test_link_extraction(self, name): - self.tar.extract(name, TEMPDIR) - with open(os.path.join(TEMPDIR, name), "rb") as f: - data = f.read() -- self.assertEqual(md5sum(data), md5_regtype) -+ self.assertEqual(sha1sum(data), sha1_regtype) - - # See issues #1578269, #8879, and #17689 for some history on these skips - @unittest.skipIf(hasattr(os.path, "islink"), - -From 4e35a5240d0bf99b60a76d3d25a82f9b8c901d59 Mon Sep 17 00:00:00 2001 +From 264c6eed5a5d060fe7bad7e4410d920cecbb083c Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 5 Aug 2019 16:37:12 +0200 Subject: [PATCH 23/36] test_tools: Skip md5sum tests in FIPS mode @@ -3221,10 +3706,10 @@ Subject: [PATCH 23/36] test_tools: Skip md5sum tests in FIPS mode 1 file changed, 4 insertions(+) diff --git a/Lib/test/test_tools/test_md5sum.py b/Lib/test/test_tools/test_md5sum.py -index fb565b73778f..7028a4dc2143 100644 +index fb565b73778..7028a4dc214 100644 --- a/Lib/test/test_tools/test_md5sum.py +++ b/Lib/test/test_tools/test_md5sum.py -@@ -4,11 +4,15 @@ +@@ -4,11 +4,15 @@ import os import unittest from test import support from test.support.script_helper import assert_python_ok, assert_python_failure @@ -3240,70 +3725,21 @@ index fb565b73778f..7028a4dc2143 100644 class MD5SumTests(unittest.TestCase): @classmethod def setUpClass(cls): +-- +2.21.0 -From 82d94582bf36170c924b26f33b56c6177a1e30f7 Mon Sep 17 00:00:00 2001 -From: Petr Viktorin -Date: Mon, 5 Aug 2019 16:43:13 +0200 -Subject: [PATCH 24/36] test_urllib2_localnet: Skip tests of md5 auth ---- - Lib/test/test_urllib2_localnet.py | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py -index ef0091c49300..2d0d62f610ef 100644 ---- a/Lib/test/test_urllib2_localnet.py -+++ b/Lib/test/test_urllib2_localnet.py -@@ -317,6 +317,7 @@ def test_basic_auth_httperror(self): - self.assertRaises(urllib.error.HTTPError, urllib.request.urlopen, self.server_url) - - -+@unittest.skipIf(hashlib.get_fips_mode(), "md5 digest auth unacceptable in FIPS mode") - @unittest.skipUnless(threading, "Threading required for this test.") - class ProxyAuthTests(unittest.TestCase): - URL = "http://localhost" - -From 78d82fdbe050e6fb27f5d736f3030357046cb60e Mon Sep 17 00:00:00 2001 -From: Petr Viktorin -Date: Mon, 5 Aug 2019 16:45:21 +0200 -Subject: [PATCH 25/36] test_uuid: Skip uuid3 test - ---- - Lib/test/test_uuid.py | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py -index aa3de74cef0a..a4ec69058889 100644 ---- a/Lib/test/test_uuid.py -+++ b/Lib/test/test_uuid.py -@@ -6,6 +6,7 @@ - import shutil - import subprocess - import uuid -+import hashlib - - def importable(name): - try: -@@ -366,6 +367,7 @@ def test_uuid1(self): - equal(((u.clock_seq_hi_variant & 0x3f) << 8) | - u.clock_seq_low, 0x3fff) - -+ @unittest.skipIf(hashlib.get_fips_mode(), "uuid3 (md5-based) unacceptable in FIPS mode") - def test_uuid3(self): - equal = self.assertEqual - - -From c7bfe61f072475b900bb68c824aa0b1fa696a975 Mon Sep 17 00:00:00 2001 +From c5373f5e7ae4ecfe8337ee3c73b594b5f0ebb411 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 5 Aug 2019 17:21:16 +0200 -Subject: [PATCH 26/36] _hashopenssl: Include hash name in the error message +Subject: [PATCH 24/36] _hashopenssl: Include hash name in the error message --- Modules/_hashopenssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c -index 7dfd70822b99..0563473c627e 100644 +index 7dfd70822b9..0563473c627 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -431,7 +431,7 @@ EVPnew(PyObject *name_obj, @@ -3324,11 +3760,14 @@ index 7dfd70822b99..0563473c627e 100644 goto end; } +-- +2.21.0 -From 5c732e6288270c247cc443fe2c2fd4fb4d95442b Mon Sep 17 00:00:00 2001 + +From c3f9e194eb5f86ebec4db2820b8968d6896abc8b Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 5 Aug 2019 18:23:57 +0200 -Subject: [PATCH 27/36] Make hashlib tests pass in FIPS mode (with some hashlib +Subject: [PATCH 25/36] Make hashlib tests pass in FIPS mode (with some hashlib changes) --- @@ -3338,7 +3777,7 @@ Subject: [PATCH 27/36] Make hashlib tests pass in FIPS mode (with some hashlib 3 files changed, 78 insertions(+), 21 deletions(-) diff --git a/Lib/hashlib.py b/Lib/hashlib.py -index ca1dd2022515..d3344f60b2ea 100644 +index ca1dd202251..d3344f60b2e 100644 --- a/Lib/hashlib.py +++ b/Lib/hashlib.py @@ -155,7 +155,18 @@ def __hash_new(name, data=b'', **kwargs): @@ -3374,10 +3813,10 @@ index ca1dd2022515..d3344f60b2ea 100644 # If the _hashlib module (OpenSSL) doesn't support the named # hash, try using our builtin implementations. diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py -index 645a3d01b91d..30b6abcbef90 100644 +index e57c93b42f5..9745bfd6fa2 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py -@@ -29,6 +29,11 @@ +@@ -31,6 +31,11 @@ COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount') c_hashlib = import_fresh_module('hashlib', fresh=['_hashlib']) py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib']) @@ -3389,7 +3828,7 @@ index 645a3d01b91d..30b6abcbef90 100644 try: import _blake2 except ImportError: -@@ -84,6 +89,11 @@ class HashLibTestCase(unittest.TestCase): +@@ -86,6 +91,11 @@ class HashLibTestCase(unittest.TestCase): # Issue #14693: fallback modules are always compiled under POSIX _warn_on_extension_import = os.name == 'posix' or COMPILED_WITH_PYDEBUG @@ -3401,7 +3840,7 @@ index 645a3d01b91d..30b6abcbef90 100644 def _conditional_import_module(self, module_name): """Import a module and return a reference to it or None on failure.""" try: -@@ -91,8 +101,20 @@ def _conditional_import_module(self, module_name): +@@ -93,8 +103,20 @@ class HashLibTestCase(unittest.TestCase): except ModuleNotFoundError as error: if self._warn_on_extension_import: warnings.warn('Did a C extension fail to compile? %s' % error) @@ -3422,7 +3861,7 @@ index 645a3d01b91d..30b6abcbef90 100644 def __init__(self, *args, **kwargs): algorithms = set() for algorithm in self.supported_hash_names: -@@ -179,15 +201,13 @@ def test_hash_array(self): +@@ -182,15 +204,13 @@ class HashLibTestCase(unittest.TestCase): a = array.array("b", range(10)) for cons in self.hash_constructors: c = cons(a) @@ -3440,7 +3879,7 @@ index 645a3d01b91d..30b6abcbef90 100644 set(_algo for _algo in self.supported_hash_names if _algo.islower())) -@@ -199,6 +219,12 @@ def test_unknown_hash(self): +@@ -202,6 +222,12 @@ class HashLibTestCase(unittest.TestCase): self.assertRaises(ValueError, hashlib.new, 'spam spam spam spam spam') self.assertRaises(TypeError, hashlib.new, 1) @@ -3453,7 +3892,7 @@ index 645a3d01b91d..30b6abcbef90 100644 def test_get_builtin_constructor(self): get_builtin_constructor = getattr(hashlib, '__get_builtin_constructor') -@@ -228,9 +254,7 @@ def test_get_builtin_constructor(self): +@@ -231,9 +257,7 @@ class HashLibTestCase(unittest.TestCase): def test_hexdigest(self): for cons in self.hash_constructors: h = cons() @@ -3464,7 +3903,7 @@ index 645a3d01b91d..30b6abcbef90 100644 self.assertIsInstance(h.digest(16), bytes) self.assertEqual(hexstr(h.digest(16)), h.hexdigest(16)) else: -@@ -242,9 +266,7 @@ def test_digest_length_overflow(self): +@@ -245,9 +269,7 @@ class HashLibTestCase(unittest.TestCase): large_sizes = (2**29, 2**32-10, 2**32+10, 2**61, 2**64-10, 2**64+10) for cons in self.hash_constructors: h = cons() @@ -3475,7 +3914,7 @@ index 645a3d01b91d..30b6abcbef90 100644 continue for digest in h.digest, h.hexdigest: with self.assertRaises((ValueError, OverflowError)): -@@ -275,9 +297,7 @@ def test_large_update(self): +@@ -278,9 +300,7 @@ class HashLibTestCase(unittest.TestCase): m1.update(bees) m1.update(cees) m1.update(dees) @@ -3486,7 +3925,7 @@ index 645a3d01b91d..30b6abcbef90 100644 args = (16,) else: args = () -@@ -346,7 +366,8 @@ def check_no_unicode(self, algorithm_name): +@@ -349,7 +369,8 @@ class HashLibTestCase(unittest.TestCase): self.assertRaises(TypeError, hash_object_constructor, 'spam') def test_no_unicode(self): @@ -3496,7 +3935,7 @@ index 645a3d01b91d..30b6abcbef90 100644 self.check_no_unicode('sha1') self.check_no_unicode('sha224') self.check_no_unicode('sha256') -@@ -389,7 +410,8 @@ def check_blocksize_name(self, name, block_size=0, digest_size=0, +@@ -392,7 +413,8 @@ class HashLibTestCase(unittest.TestCase): self.assertIn(name.split("_")[0], repr(m)) def test_blocksize_name(self): @@ -3506,7 +3945,7 @@ index 645a3d01b91d..30b6abcbef90 100644 self.check_blocksize_name('sha1', 64, 20) self.check_blocksize_name('sha224', 64, 28) self.check_blocksize_name('sha256', 64, 32) -@@ -429,22 +451,27 @@ def test_blocksize_name_blake2(self): +@@ -432,22 +454,27 @@ class HashLibTestCase(unittest.TestCase): self.check_blocksize_name('blake2b', 128, 64) self.check_blocksize_name('blake2s', 64, 32) @@ -3534,7 +3973,7 @@ index 645a3d01b91d..30b6abcbef90 100644 @unittest.skipIf(sys.maxsize < _4G - 1, 'test cannot run on 32-bit systems') @bigmemtest(size=_4G - 1, memuse=1, dry_run=False) def test_case_md5_uintmax(self, size): -@@ -826,14 +853,16 @@ def test_gil(self): +@@ -829,14 +856,16 @@ class HashLibTestCase(unittest.TestCase): m = cons(b'x' * gil_minsize) m.update(b'1') @@ -3556,7 +3995,7 @@ index 645a3d01b91d..30b6abcbef90 100644 @unittest.skipUnless(threading, 'Threading required for this test.') @support.reap_threads diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c -index 0563473c627e..e330423e2662 100644 +index 0563473c627..e330423e266 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -256,11 +256,25 @@ EVP_update(EVPobject *self, PyObject *args) @@ -3585,107 +4024,14 @@ index 0563473c627e..e330423e2662 100644 {NULL, NULL} /* sentinel */ }; +-- +2.21.0 -From 9f8dde4113dc93248ed376f17ceef349bcd2f855 Mon Sep 17 00:00:00 2001 -From: Petr Viktorin -Date: Mon, 5 Aug 2019 19:12:38 +0200 -Subject: [PATCH 28/36] Fixups -- Adjust error message of the original hmac.HMAC class -- Don't duplicate a atest name ---- - Lib/hmac.py | 2 +- - Lib/test/test_hmac.py | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/Lib/hmac.py b/Lib/hmac.py -index 7af94c39ed63..33b5be613d96 100644 ---- a/Lib/hmac.py -+++ b/Lib/hmac.py -@@ -41,7 +41,7 @@ def __init__(self, key, msg = None, digestmod = None): - """ - if _hashlib.get_fips_mode(): - raise ValueError( -- 'hmac.HMAC is not available in FIPS mode. ' -+ 'This class is not available in FIPS mode. ' - + 'Use hmac.new().' - ) - -diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py -index 6f53a6d1fd5b..17ffcf37eb14 100644 ---- a/Lib/test/test_hmac.py -+++ b/Lib/test/test_hmac.py -@@ -389,7 +389,7 @@ def test_realcopy(self): - self.assertTrue(id(h1.outer) != id(h2.outer), - "No real copy of the attribute 'outer'.") - -- def test_realcopy(self): -+ def test_realcopy_by_digest(self): - # Testing if the copy method created a real copy. - h1 = hmac.HMAC(b"key", digestmod="sha1") - h2 = h1.copy() - -From 0056a10cb639a97b6deac312752be9ed0f19f2cf Mon Sep 17 00:00:00 2001 -From: Petr Viktorin -Date: Mon, 19 Aug 2019 13:59:40 +0200 -Subject: [PATCH 29/36] Make uuid.uuid3 work (using libuuid via ctypes) - ---- - Lib/test/test_uuid.py | 1 - - Lib/uuid.py | 9 +++++++++ - 2 files changed, 9 insertions(+), 1 deletion(-) - -diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py -index a4ec69058889..17e03388ce7b 100644 ---- a/Lib/test/test_uuid.py -+++ b/Lib/test/test_uuid.py -@@ -367,7 +367,6 @@ def test_uuid1(self): - equal(((u.clock_seq_hi_variant & 0x3f) << 8) | - u.clock_seq_low, 0x3fff) - -- @unittest.skipIf(hashlib.get_fips_mode(), "uuid3 (md5-based) unacceptable in FIPS mode") - def test_uuid3(self): - equal = self.assertEqual - -diff --git a/Lib/uuid.py b/Lib/uuid.py -index db8b2ef94ed4..42291ff5e0d6 100644 ---- a/Lib/uuid.py -+++ b/Lib/uuid.py -@@ -476,6 +476,7 @@ def _netbios_getnode(): - # If ctypes is available, use it to find system routines for UUID generation. - # XXX This makes the module non-thread-safe! - _uuid_generate_time = _UuidCreate = None -+_uuid_generate_md5 = None - try: - import ctypes, ctypes.util - import sys -@@ -492,6 +493,8 @@ def _netbios_getnode(): - continue - if hasattr(lib, 'uuid_generate_time'): - _uuid_generate_time = lib.uuid_generate_time -+ # The library that has uuid_generate_time should have md5 too. -+ _uuid_generate_md5 = getattr(lib, 'uuid_generate_md5') - break - del _libnames - -@@ -614,6 +617,12 @@ def uuid1(node=None, clock_seq=None): - - def uuid3(namespace, name): - """Generate a UUID from the MD5 hash of a namespace UUID and a name.""" -+ if _uuid_generate_md5: -+ name_b = bytes(name, "utf-8") -+ _buffer = ctypes.create_string_buffer(16) -+ _uuid_generate_md5(_buffer, namespace.bytes, name_b, len(name_b)) -+ return UUID(bytes=bytes_(_buffer.raw)) -+ - from hashlib import md5 - hash = md5(namespace.bytes + bytes(name, "utf-8")).digest() - return UUID(bytes=hash[:16], version=3) - -From 27805c1110b734c5aa039443f4cf217f0d2da44d Mon Sep 17 00:00:00 2001 +From a40d1cb8672bc2c5403b6e9ff6eaa3324282de09 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Wed, 14 Aug 2019 14:43:07 +0200 -Subject: [PATCH 30/36] distutils upload: only add md5 if available, but +Subject: [PATCH 26/36] distutils upload: only add md5 if available, but *always* use sha256 --- @@ -3694,10 +4040,10 @@ Subject: [PATCH 30/36] distutils upload: only add md5 if available, but 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Lib/distutils/command/upload.py b/Lib/distutils/command/upload.py -index 0edb39efd4cb..170acb3d6b65 100644 +index 0edb39efd4c..170acb3d6b6 100644 --- a/Lib/distutils/command/upload.py +++ b/Lib/distutils/command/upload.py -@@ -102,6 +102,7 @@ def upload_file(self, command, pyversion, filename): +@@ -102,6 +102,7 @@ class upload(PyPIRCCommand): 'content': (os.path.basename(filename),content), 'filetype': command, 'pyversion': pyversion, @@ -3705,7 +4051,7 @@ index 0edb39efd4cb..170acb3d6b65 100644 # additional meta-data 'metadata_version': '1.0', -@@ -124,7 +125,7 @@ def upload_file(self, command, pyversion, filename): +@@ -124,7 +125,7 @@ class upload(PyPIRCCommand): digest = hashlib.md5(content).hexdigest() except ValueError as e: msg = 'calculating md5 checksum failed: %s' % e @@ -3715,10 +4061,10 @@ index 0edb39efd4cb..170acb3d6b65 100644 # this really shouldn't fail raise diff --git a/Lib/distutils/tests/test_upload.py b/Lib/distutils/tests/test_upload.py -index b4b64e97737d..f720a7905dd8 100644 +index b4b64e97737..f720a7905dd 100644 --- a/Lib/distutils/tests/test_upload.py +++ b/Lib/distutils/tests/test_upload.py -@@ -132,10 +132,11 @@ def test_upload(self): +@@ -132,10 +132,11 @@ class uploadTestCase(BasePyPIRCCommandTestCase): # what did we send ? headers = dict(self.last_open.req.headers) if hashlib.get_fips_mode(): @@ -3733,7 +4079,7 @@ index b4b64e97737d..f720a7905dd8 100644 content_type = headers['Content-type'] self.assertTrue(content_type.startswith('multipart/form-data')) self.assertEqual(self.last_open.req.get_method(), 'POST') -@@ -172,10 +173,11 @@ def test_upload_correct_cr(self): +@@ -172,10 +173,11 @@ class uploadTestCase(BasePyPIRCCommandTestCase): headers = dict(self.last_open.req.headers) if hashlib.get_fips_mode(): @@ -3748,11 +4094,14 @@ index b4b64e97737d..f720a7905dd8 100644 self.assertIn(b'long description\r', self.last_open.req.data) def test_upload_fails(self): +-- +2.21.0 -From 584d432c6a3e987fdd661e994626befaed523a40 Mon Sep 17 00:00:00 2001 + +From e0d2cca338186bbc5cb9c67bb4402dec38fed5a7 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 26 Aug 2019 15:55:48 +0200 -Subject: [PATCH 31/36] Add the usedforsecurity argument back +Subject: [PATCH 27/36] Add the usedforsecurity argument back --- Lib/hashlib.py | 4 ++- @@ -3760,7 +4109,7 @@ Subject: [PATCH 31/36] Add the usedforsecurity argument back 2 files changed, 65 insertions(+), 21 deletions(-) diff --git a/Lib/hashlib.py b/Lib/hashlib.py -index d3344f60b2ea..cd3b035b1d76 100644 +index d3344f60b2e..cd3b035b1d7 100644 --- a/Lib/hashlib.py +++ b/Lib/hashlib.py @@ -174,7 +174,9 @@ def __hash_new(name, data=b'', **kwargs): @@ -3775,7 +4124,7 @@ index d3344f60b2ea..cd3b035b1d76 100644 retval._set_name(orig_name) return retval diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c -index e330423e2662..b621c330c32d 100644 +index e330423e266..b621c330c32 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -318,6 +318,25 @@ EVP_repr(EVPobject *self) @@ -3951,11 +4300,14 @@ index e330423e2662..b621c330c32d 100644 PyDoc_STR("Returns a " #NAME \ " hash object; optionally initialized with a string") \ }, +-- +2.21.0 -From 07c8dd0441a76fe841461a1b81d4c7f9c697d643 Mon Sep 17 00:00:00 2001 + +From 0d169ad7d9aa48bdb3313b6d72682d097dc9dea5 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 26 Aug 2019 18:59:15 +0200 -Subject: [PATCH 32/36] Add no-op usedforsecurity argument to internal hash +Subject: [PATCH 28/36] Add no-op usedforsecurity argument to internal hash implementations --- @@ -3967,7 +4319,7 @@ Subject: [PATCH 32/36] Add no-op usedforsecurity argument to internal hash 5 files changed, 31 insertions(+), 18 deletions(-) diff --git a/Modules/_blake2/blake2b_impl.c b/Modules/_blake2/blake2b_impl.c -index f6bfce823b8f..ae9d244200ab 100644 +index f6bfce823b8..ae9d244200a 100644 --- a/Modules/_blake2/blake2b_impl.c +++ b/Modules/_blake2/blake2b_impl.c @@ -87,6 +87,8 @@ _blake2.blake2b.__new__ as py_blake2b_new @@ -3991,7 +4343,7 @@ index f6bfce823b8f..ae9d244200ab 100644 BLAKE2bObject *self = NULL; Py_buffer buf; diff --git a/Modules/_blake2/blake2s_impl.c b/Modules/_blake2/blake2s_impl.c -index 28ae5b651019..bf80d6b7428c 100644 +index 28ae5b65101..bf80d6b7428 100644 --- a/Modules/_blake2/blake2s_impl.c +++ b/Modules/_blake2/blake2s_impl.c @@ -87,6 +87,8 @@ _blake2.blake2s.__new__ as py_blake2s_new @@ -4015,7 +4367,7 @@ index 28ae5b651019..bf80d6b7428c 100644 BLAKE2sObject *self = NULL; Py_buffer buf; diff --git a/Modules/_blake2/clinic/blake2b_impl.c.h b/Modules/_blake2/clinic/blake2b_impl.c.h -index 9b2965eb6b31..9688c04dda80 100644 +index 9b2965eb6b3..9688c04dda8 100644 --- a/Modules/_blake2/clinic/blake2b_impl.c.h +++ b/Modules/_blake2/clinic/blake2b_impl.c.h @@ -5,7 +5,8 @@ preserve @@ -4069,7 +4421,7 @@ index 9b2965eb6b31..9688c04dda80 100644 -/*[clinic end generated code: output=0eb559f418fc0a21 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d5f214b052c75135 input=a9049054013a1b77]*/ diff --git a/Modules/_blake2/clinic/blake2s_impl.c.h b/Modules/_blake2/clinic/blake2s_impl.c.h -index 42b87b7099df..5653e93044d1 100644 +index 42b87b7099d..5653e93044d 100644 --- a/Modules/_blake2/clinic/blake2s_impl.c.h +++ b/Modules/_blake2/clinic/blake2s_impl.c.h @@ -5,7 +5,8 @@ preserve @@ -4123,7 +4475,7 @@ index 42b87b7099df..5653e93044d1 100644 -/*[clinic end generated code: output=13d4b08ea9ee2d62 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2373a3b3fa542e89 input=a9049054013a1b77]*/ diff --git a/Modules/_sha3/sha3module.c b/Modules/_sha3/sha3module.c -index 2783a75644fc..62db9cb5616f 100644 +index 2783a75644f..62db9cb5616 100644 --- a/Modules/_sha3/sha3module.c +++ b/Modules/_sha3/sha3module.c @@ -185,6 +185,11 @@ py_sha3_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) @@ -4138,29 +4490,32 @@ index 2783a75644fc..62db9cb5616f 100644 if (!_PyArg_NoKeywords(type->tp_name, kwargs)) { return NULL; } +-- +2.21.0 -From 595066f4993f94838f53f06b2729739f30a60eb8 Mon Sep 17 00:00:00 2001 + +From c451744d82f78f42bfa947b782a24ff7c8c6ad9d Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 26 Aug 2019 19:09:39 +0200 -Subject: [PATCH 33/36] Test the usedforsecurity flag +Subject: [PATCH 29/36] Test the usedforsecurity flag --- Lib/test/test_hashlib.py | 82 ++++++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 28 deletions(-) diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py -index 30b6abcbef90..b359c4fb14a9 100644 +index 9745bfd6fa2..19a2fbdf294 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py -@@ -22,6 +22,7 @@ - from test import support +@@ -24,6 +24,7 @@ from test import support from test.support import _4G, bigmemtest, import_fresh_module + from test.support import requires_hashdigest from http.client import HTTPException +from functools import partial # Were we compiled --with-pydebug or with #define Py_DEBUG? COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount') -@@ -30,8 +31,10 @@ +@@ -32,8 +33,10 @@ c_hashlib = import_fresh_module('hashlib', fresh=['_hashlib']) py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib']) if hashlib.get_fips_mode(): @@ -4172,7 +4527,7 @@ index 30b6abcbef90..b359c4fb14a9 100644 FIPS_DISABLED = set() try: -@@ -76,6 +79,15 @@ def read_vectors(hash_name): +@@ -78,6 +81,15 @@ def read_vectors(hash_name): yield parts @@ -4188,7 +4543,7 @@ index 30b6abcbef90..b359c4fb14a9 100644 class HashLibTestCase(unittest.TestCase): supported_hash_names = ( 'md5', 'MD5', 'sha1', 'SHA1', 'sha224', 'SHA224', 'sha256', 'SHA256', -@@ -91,8 +103,6 @@ class HashLibTestCase(unittest.TestCase): +@@ -93,8 +105,6 @@ class HashLibTestCase(unittest.TestCase): if hashlib.get_fips_mode(): shakes = set() @@ -4197,7 +4552,7 @@ index 30b6abcbef90..b359c4fb14a9 100644 def _conditional_import_module(self, module_name): """Import a module and return a reference to it or None on failure.""" -@@ -118,7 +128,8 @@ def _has_shake_extras(self, hasher): +@@ -120,7 +130,8 @@ class HashLibTestCase(unittest.TestCase): def __init__(self, *args, **kwargs): algorithms = set() for algorithm in self.supported_hash_names: @@ -4207,7 +4562,7 @@ index 30b6abcbef90..b359c4fb14a9 100644 _blake2 = self._conditional_import_module('_blake2') if _blake2: -@@ -128,15 +139,21 @@ def __init__(self, *args, **kwargs): +@@ -130,15 +141,21 @@ class HashLibTestCase(unittest.TestCase): for algorithm in algorithms: self.constructors_to_test[algorithm] = set() @@ -4230,8 +4585,8 @@ index 30b6abcbef90..b359c4fb14a9 100644 + _add_constructor(algorithm, _test_algorithm_via_hashlib_new) _hashlib = self._conditional_import_module('_hashlib') - if _hashlib: -@@ -147,7 +164,7 @@ def _test_algorithm_via_hashlib_new(data=None, _alg=algorithm, **kwargs): + self._hashlib = _hashlib +@@ -150,7 +167,7 @@ class HashLibTestCase(unittest.TestCase): for algorithm, constructors in self.constructors_to_test.items(): constructor = getattr(_hashlib, 'openssl_'+algorithm, None) if constructor: @@ -4240,7 +4595,7 @@ index 30b6abcbef90..b359c4fb14a9 100644 def add_builtin_constructor(name): constructor = getattr(hashlib, "__get_builtin_constructor")(name) -@@ -207,7 +224,7 @@ def test_hash_array(self): +@@ -210,7 +227,7 @@ class HashLibTestCase(unittest.TestCase): c.hexdigest() def test_algorithms_guaranteed(self): @@ -4249,7 +4604,7 @@ index 30b6abcbef90..b359c4fb14a9 100644 set(_algo for _algo in self.supported_hash_names if _algo.islower())) -@@ -283,7 +300,9 @@ def test_name_attribute(self): +@@ -286,7 +303,9 @@ class HashLibTestCase(unittest.TestCase): self.assertIn(h.name, self.supported_hash_names) else: self.assertNotIn(h.name, self.supported_hash_names) @@ -4260,7 +4615,7 @@ index 30b6abcbef90..b359c4fb14a9 100644 def test_large_update(self): aas = b'a' * 128 -@@ -325,13 +344,15 @@ def check(self, name, data, hexdigest, shake=False, **kwargs): +@@ -328,13 +347,15 @@ class HashLibTestCase(unittest.TestCase): self.assertGreaterEqual(len(constructors), 2) for hash_object_constructor in constructors: if ( @@ -4279,7 +4634,7 @@ index 30b6abcbef90..b359c4fb14a9 100644 if length > m.digest_size: # OpenSSL doesn't give long digests return -@@ -348,7 +369,7 @@ def check(self, name, data, hexdigest, shake=False, **kwargs): +@@ -351,7 +372,7 @@ class HashLibTestCase(unittest.TestCase): % (name, hash_object_constructor, computed, len(data), hexdigest)) if shake: @@ -4288,7 +4643,7 @@ index 30b6abcbef90..b359c4fb14a9 100644 computed = m.digest()[:length] else: computed = m.digest(length) -@@ -366,8 +387,7 @@ def check_no_unicode(self, algorithm_name): +@@ -369,8 +390,7 @@ class HashLibTestCase(unittest.TestCase): self.assertRaises(TypeError, hash_object_constructor, 'spam') def test_no_unicode(self): @@ -4298,7 +4653,7 @@ index 30b6abcbef90..b359c4fb14a9 100644 self.check_no_unicode('sha1') self.check_no_unicode('sha224') self.check_no_unicode('sha256') -@@ -394,10 +414,10 @@ def check_blocksize_name(self, name, block_size=0, digest_size=0, +@@ -397,10 +417,10 @@ class HashLibTestCase(unittest.TestCase): for hash_object_constructor in constructors: m = hash_object_constructor() self.assertEqual(m.block_size, block_size) @@ -4311,7 +4666,7 @@ index 30b6abcbef90..b359c4fb14a9 100644 self.assertEqual(len(m.digest(digest_length)), digest_length) self.assertEqual(len(m.hexdigest(digest_length)), -@@ -432,7 +452,7 @@ def check_sha3(self, name, capacity, rate, suffix): +@@ -435,7 +455,7 @@ class HashLibTestCase(unittest.TestCase): for hash_object_constructor in constructors: m = hash_object_constructor() self.assertEqual(capacity + rate, 1600) @@ -4320,7 +4675,7 @@ index 30b6abcbef90..b359c4fb14a9 100644 self.assertEqual(m._capacity_bits, capacity) self.assertEqual(m._rate_bits, rate) self.assertEqual(m._suffix, suffix) -@@ -451,31 +471,27 @@ def test_blocksize_name_blake2(self): +@@ -454,31 +474,27 @@ class HashLibTestCase(unittest.TestCase): self.check_blocksize_name('blake2b', 128, 64) self.check_blocksize_name('blake2s', 64, 32) @@ -4358,7 +4713,7 @@ index 30b6abcbef90..b359c4fb14a9 100644 # use the three examples from Federal Information Processing Standards # Publication 180-1, Secure Hash Standard, 1995 April 17 -@@ -901,6 +917,16 @@ def hash_in_chunks(chunk_size): +@@ -904,6 +920,16 @@ class HashLibTestCase(unittest.TestCase): self.assertEqual(expected_hash, hasher.hexdigest()) @@ -4375,8 +4730,179 @@ index 30b6abcbef90..b359c4fb14a9 100644 class KDFTests(unittest.TestCase): +-- +2.21.0 -From 723bfe45d5a7666a75a12633b21a9f153805eccf Mon Sep 17 00:00:00 2001 + +From 327707f185572cf13da66851e0af824a81d65aa9 Mon Sep 17 00:00:00 2001 +From: Petr Viktorin +Date: Thu, 29 Aug 2019 10:25:28 +0200 +Subject: [PATCH 30/36] Skip error checking in _hashlib.get_fips_mode + +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1745499 +--- + Modules/_hashopenssl.c | 30 ++++++++++++++++-------------- + 1 file changed, 16 insertions(+), 14 deletions(-) + +diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c +index b621c330c32..6bfb12c5618 100644 +--- a/Modules/_hashopenssl.c ++++ b/Modules/_hashopenssl.c +@@ -1021,20 +1021,22 @@ static PyObject * + _hashlib_get_fips_mode_impl(PyObject *module) + /*[clinic end generated code: output=ad8a7793310d3f98 input=f42a2135df2a5e11]*/ + { +- int result = FIPS_mode(); +- if (result == 0) { +- // "If the library was built without support of the FIPS Object Module, +- // then the function will return 0 with an error code of +- // CRYPTO_R_FIPS_MODE_NOT_SUPPORTED (0x0f06d065)." +- // But 0 is also a valid result value. +- +- unsigned long errcode = ERR_peek_last_error(); +- if (errcode) { +- _setException(PyExc_ValueError); +- return NULL; +- } +- } +- return PyLong_FromLong(result); ++ // XXX: This function skips error checking. ++ // This is only appropriate for RHEL. ++ ++ // From the OpenSSL docs: ++ // "If the library was built without support of the FIPS Object Module, ++ // then the function will return 0 with an error code of ++ // CRYPTO_R_FIPS_MODE_NOT_SUPPORTED (0x0f06d065)." ++ // In RHEL: ++ // * we do build with FIPS, so the function always succeeds ++ // * even if it didn't, people seem used to errors being left on the ++ // OpenSSL error stack. ++ ++ // For more info, see: ++ // https://bugzilla.redhat.com/show_bug.cgi?id=1745499 ++ ++ return PyLong_FromLong(FIPS_mode()); + } + + +-- +2.21.0 + + +From 695039674b78b19d9ff26d637c11acea99c44807 Mon Sep 17 00:00:00 2001 +From: Petr Viktorin +Date: Thu, 10 Oct 2019 13:04:50 +0200 +Subject: [PATCH 31/36] Skip error checking in _Py_hashlib_fips_error + +https://bugzilla.redhat.com/show_bug.cgi?id=1760106 +--- + Include/_hashopenssl.h | 12 +++--------- + 1 file changed, 3 insertions(+), 9 deletions(-) + +diff --git a/Include/_hashopenssl.h b/Include/_hashopenssl.h +index 47ed0030422..d4cbdef984d 100644 +--- a/Include/_hashopenssl.h ++++ b/Include/_hashopenssl.h +@@ -42,16 +42,10 @@ static int + _Py_hashlib_fips_error(PyObject *exc, char *name) { + int result = FIPS_mode(); + if (result == 0) { +- // "If the library was built without support of the FIPS Object Module, +- // then the function will return 0 with an error code of +- // CRYPTO_R_FIPS_MODE_NOT_SUPPORTED (0x0f06d065)." +- // But 0 is also a valid result value. ++ // XXX: This function skips error checking. ++ // This is only appropriate for RHEL. ++ // See _hashlib.get_fips_mode for details. + +- unsigned long errcode = ERR_peek_last_error(); +- if (errcode) { +- _setException(exc); +- return 1; +- } + return 0; + } + PyErr_Format(exc, "%s is not available in FIPS mode", name); +-- +2.21.0 + + +From 0f9008e92b62f5f22e2bfd0a73d5325d16eedf6f Mon Sep 17 00:00:00 2001 +From: Charalampos Stratakis +Date: Thu, 21 Nov 2019 00:20:09 +0100 +Subject: [PATCH 32/36] Use usedforsecurity=False in uuid + +Partially backport commit 7cad53e6b084435a220e6604010f1fa5778bd0b1 +only for uuid +--- + Lib/uuid.py | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/Lib/uuid.py b/Lib/uuid.py +index db8b2ef94ed..7e680a24d06 100644 +--- a/Lib/uuid.py ++++ b/Lib/uuid.py +@@ -615,8 +615,11 @@ def uuid1(node=None, clock_seq=None): + def uuid3(namespace, name): + """Generate a UUID from the MD5 hash of a namespace UUID and a name.""" + from hashlib import md5 +- hash = md5(namespace.bytes + bytes(name, "utf-8")).digest() +- return UUID(bytes=hash[:16], version=3) ++ digest = md5( ++ namespace.bytes + bytes(name, "utf-8"), ++ usedforsecurity=False ++ ).digest() ++ return UUID(bytes=digest[:16], version=3) + + def uuid4(): + """Generate a random UUID.""" +-- +2.21.0 + + +From 75829df72b65fb573f3b310033978e493ff700b4 Mon Sep 17 00:00:00 2001 +From: Petr Viktorin +Date: Mon, 5 Aug 2019 19:12:38 +0200 +Subject: [PATCH 33/36] Fixups + +- Adjust error message of the original hmac.HMAC class +- Don't duplicate a test name +--- + Lib/hmac.py | 2 +- + Lib/test/test_hmac.py | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Lib/hmac.py b/Lib/hmac.py +index 7af94c39ed6..33b5be613d9 100644 +--- a/Lib/hmac.py ++++ b/Lib/hmac.py +@@ -41,7 +41,7 @@ class HMAC: + """ + if _hashlib.get_fips_mode(): + raise ValueError( +- 'hmac.HMAC is not available in FIPS mode. ' ++ 'This class is not available in FIPS mode. ' + + 'Use hmac.new().' + ) + +diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py +index 5b090727ef6..449b1366314 100644 +--- a/Lib/test/test_hmac.py ++++ b/Lib/test/test_hmac.py +@@ -401,7 +401,7 @@ class CopyTestCase(unittest.TestCase): + self.assertTrue(id(h1.outer) != id(h2.outer), + "No real copy of the attribute 'outer'.") + +- def test_realcopy(self): ++ def test_realcopy_by_digest(self): + # Testing if the copy method created a real copy. + h1 = hmac.HMAC(b"key", digestmod="sha1") + h2 = h1.copy() +-- +2.21.0 + + +From 86f1f161b5aab08975379dbae6ebac08a697e3d7 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 26 Aug 2019 19:39:48 +0200 Subject: [PATCH 34/36] Don't re-export get_fips_mode from hashlib @@ -4389,18 +4915,18 @@ Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1745685 Lib/hmac.py | 6 +++--- Lib/test/test_fips.py | 6 +++--- Lib/test/test_hashlib.py | 16 +++++++++------- - Lib/test/test_hmac.py | 15 ++++++++------- - Lib/test/test_logging.py | 3 ++- - Lib/test/test_smtplib.py | 7 ++++--- + Lib/test/test_hmac.py | 8 +++++--- + Lib/test/test_logging.py | 1 + + Lib/test/test_smtplib.py | 4 +++- Lib/test/test_tools/test_md5sum.py | 4 ++-- - Lib/test/test_urllib2_localnet.py | 3 ++- - 11 files changed, 50 insertions(+), 41 deletions(-) + Lib/test/test_urllib2_localnet.py | 1 + + 11 files changed, 44 insertions(+), 33 deletions(-) diff --git a/Lib/distutils/command/upload.py b/Lib/distutils/command/upload.py -index 170acb3d6b65..d0a4aee001ea 100644 +index 170acb3d6b6..d0a4aee001e 100644 --- a/Lib/distutils/command/upload.py +++ b/Lib/distutils/command/upload.py -@@ -126,7 +126,8 @@ def upload_file(self, command, pyversion, filename): +@@ -126,7 +126,8 @@ class upload(PyPIRCCommand): except ValueError as e: msg = 'calculating md5 checksum failed: %s' % e self.announce(msg, log.INFO) @@ -4411,10 +4937,10 @@ index 170acb3d6b65..d0a4aee001ea 100644 raise else: diff --git a/Lib/distutils/tests/test_upload.py b/Lib/distutils/tests/test_upload.py -index f720a7905dd8..a198b213577b 100644 +index f720a7905dd..a198b213577 100644 --- a/Lib/distutils/tests/test_upload.py +++ b/Lib/distutils/tests/test_upload.py -@@ -4,6 +4,7 @@ +@@ -4,6 +4,7 @@ import unittest import unittest.mock as mock from urllib.request import HTTPError import hashlib @@ -4422,7 +4948,7 @@ index f720a7905dd8..a198b213577b 100644 from test.support import run_unittest -@@ -131,7 +132,7 @@ def test_upload(self): +@@ -131,7 +132,7 @@ class uploadTestCase(BasePyPIRCCommandTestCase): # what did we send ? headers = dict(self.last_open.req.headers) @@ -4431,7 +4957,7 @@ index f720a7905dd8..a198b213577b 100644 # only sha256 hash is used self.assertEqual(headers['Content-length'], '2197') else: -@@ -172,7 +173,7 @@ def test_upload_correct_cr(self): +@@ -172,7 +173,7 @@ class uploadTestCase(BasePyPIRCCommandTestCase): cmd.run() headers = dict(self.last_open.req.headers) @@ -4441,10 +4967,10 @@ index f720a7905dd8..a198b213577b 100644 self.assertEqual(headers['Content-length'], '2207') else: diff --git a/Lib/hashlib.py b/Lib/hashlib.py -index cd3b035b1d76..3e9a4aa27a79 100644 +index cd3b035b1d7..3e9a4aa27a7 100644 --- a/Lib/hashlib.py +++ b/Lib/hashlib.py -@@ -68,13 +68,13 @@ +@@ -68,13 +68,13 @@ __all__ = __always_supported + ('new', 'algorithms_guaranteed', 'algorithms_available', 'pbkdf2_hmac') try: @@ -4461,7 +4987,7 @@ index cd3b035b1d76..3e9a4aa27a79 100644 __builtin_constructor_cache = {} def __get_builtin_constructor(name): -@@ -121,7 +121,7 @@ def __get_builtin_constructor(name): +@@ -121,7 +121,7 @@ if not get_fips_mode(): def __get_openssl_constructor(name): @@ -4515,7 +5041,7 @@ index cd3b035b1d76..3e9a4aa27a79 100644 raise return __get_builtin_constructor(name)(data) -@@ -197,7 +197,7 @@ def __hash_new(name, data=b'', **kwargs): +@@ -197,7 +197,7 @@ try: algorithms_available = algorithms_available.union( _hashlib.openssl_md_meth_names) except ImportError: @@ -4524,7 +5050,7 @@ index cd3b035b1d76..3e9a4aa27a79 100644 raise new = __py_new __get_hash = __get_builtin_constructor -@@ -225,5 +225,6 @@ def __hash_new(name, data=b'', **kwargs): +@@ -225,5 +225,6 @@ for __func_name in __always_supported: # Cleanup locals() del __always_supported, __func_name, __get_hash del __hash_new, __get_openssl_constructor @@ -4533,10 +5059,10 @@ index cd3b035b1d76..3e9a4aa27a79 100644 del __py_new +del _hashlib_get_fips_mode diff --git a/Lib/hmac.py b/Lib/hmac.py -index 33b5be613d96..ca83d9dc0d35 100644 +index 33b5be613d9..ca83d9dc0d3 100644 --- a/Lib/hmac.py +++ b/Lib/hmac.py -@@ -39,7 +39,7 @@ def __init__(self, key, msg = None, digestmod = None): +@@ -39,7 +39,7 @@ class HMAC: Note: key and msg must be a bytes or bytearray objects. """ @@ -4545,7 +5071,7 @@ index 33b5be613d96..ca83d9dc0d35 100644 raise ValueError( 'This class is not available in FIPS mode. ' + 'Use hmac.new().' -@@ -97,7 +97,7 @@ def name(self): +@@ -97,7 +97,7 @@ class HMAC: def update(self, msg): """Update this hashing object with the string msg. """ @@ -4554,7 +5080,7 @@ index 33b5be613d96..ca83d9dc0d35 100644 raise ValueError('hmac.HMAC is not available in FIPS mode') self.inner.update(msg) -@@ -167,7 +167,7 @@ def __new__(cls, key, msg = None, digestmod = None): +@@ -167,7 +167,7 @@ class HMAC_openssl(_hmacopenssl.HMAC): return result @@ -4564,10 +5090,10 @@ index 33b5be613d96..ca83d9dc0d35 100644 diff --git a/Lib/test/test_fips.py b/Lib/test/test_fips.py -index 34812e6098ae..86e61e29c0b4 100644 +index 34812e6098a..86e61e29c0b 100644 --- a/Lib/test/test_fips.py +++ b/Lib/test/test_fips.py -@@ -6,7 +6,7 @@ +@@ -6,7 +6,7 @@ import hashlib, _hashlib class HashlibFipsTests(unittest.TestCase): @@ -4576,7 +5102,7 @@ index 34812e6098ae..86e61e29c0b4 100644 def test_fips_imports(self): """blake2s and blake2b should fail to import in FIPS mode """ -@@ -30,7 +30,7 @@ def compare_hashes(self, python_hash, openssl_hash): +@@ -30,7 +30,7 @@ class HashlibFipsTests(unittest.TestCase): self.assertEqual(m, h) @@ -4585,7 +5111,7 @@ index 34812e6098ae..86e61e29c0b4 100644 def test_blake2_hashes(self): self.compare_hashes(hashlib.blake2b(b'abc'), _hashlib.openssl_blake2b(b'abc')) self.compare_hashes(hashlib.blake2s(b'abc'), _hashlib.openssl_blake2s(b'abc')) -@@ -41,7 +41,7 @@ def test_sha3_hashes(self): +@@ -41,7 +41,7 @@ class HashlibFipsTests(unittest.TestCase): self.compare_hashes(hashlib.sha3_384(b'abc'), _hashlib.openssl_sha3_384(b'abc')) self.compare_hashes(hashlib.sha3_512(b'abc'), _hashlib.openssl_sha3_512(b'abc')) @@ -4595,10 +5121,10 @@ index 34812e6098ae..86e61e29c0b4 100644 self.compare_hashes(hashlib.shake_128(b'abc'), _hashlib.openssl_shake_128(b'abc')) self.compare_hashes(hashlib.shake_256(b'abc'), _hashlib.openssl_shake_256(b'abc')) diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py -index b359c4fb14a9..eadfb7968be8 100644 +index 19a2fbdf294..a6f9a353fd1 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py -@@ -30,7 +30,9 @@ +@@ -32,7 +32,9 @@ COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount') c_hashlib = import_fresh_module('hashlib', fresh=['_hashlib']) py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib']) @@ -4609,7 +5135,7 @@ index b359c4fb14a9..eadfb7968be8 100644 FIPS_UNAVAILABLE = {'blake2b', 'blake2s'} FIPS_DISABLED = {'md5', 'MD5', *FIPS_UNAVAILABLE} else: -@@ -101,7 +103,7 @@ class HashLibTestCase(unittest.TestCase): +@@ -103,7 +105,7 @@ class HashLibTestCase(unittest.TestCase): # Issue #14693: fallback modules are always compiled under POSIX _warn_on_extension_import = os.name == 'posix' or COMPILED_WITH_PYDEBUG @@ -4618,7 +5144,7 @@ index b359c4fb14a9..eadfb7968be8 100644 shakes = set() def _conditional_import_module(self, module_name): -@@ -112,7 +114,7 @@ def _conditional_import_module(self, module_name): +@@ -114,7 +116,7 @@ class HashLibTestCase(unittest.TestCase): if self._warn_on_extension_import: warnings.warn('Did a C extension fail to compile? %s' % error) except ImportError as error: @@ -4627,7 +5153,7 @@ index b359c4fb14a9..eadfb7968be8 100644 raise return None -@@ -236,12 +238,12 @@ def test_unknown_hash(self): +@@ -239,12 +241,12 @@ class HashLibTestCase(unittest.TestCase): self.assertRaises(ValueError, hashlib.new, 'spam spam spam spam spam') self.assertRaises(TypeError, hashlib.new, 1) @@ -4642,7 +5168,7 @@ index b359c4fb14a9..eadfb7968be8 100644 def test_get_builtin_constructor(self): get_builtin_constructor = getattr(hashlib, '__get_builtin_constructor') -@@ -430,7 +432,7 @@ def check_blocksize_name(self, name, block_size=0, digest_size=0, +@@ -433,7 +435,7 @@ class HashLibTestCase(unittest.TestCase): self.assertIn(name.split("_")[0], repr(m)) def test_blocksize_name(self): @@ -4651,7 +5177,7 @@ index b359c4fb14a9..eadfb7968be8 100644 self.check_blocksize_name('md5', 64, 16) self.check_blocksize_name('sha1', 64, 20) self.check_blocksize_name('sha224', 64, 28) -@@ -917,7 +919,7 @@ def hash_in_chunks(chunk_size): +@@ -920,7 +922,7 @@ class HashLibTestCase(unittest.TestCase): self.assertEqual(expected_hash, hasher.hexdigest()) @@ -4661,145 +5187,91 @@ index b359c4fb14a9..eadfb7968be8 100644 """Make sure usedforsecurity flag isn't copied to other contexts""" for i in range(3): diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py -index 17ffcf37eb14..7fbbe057d736 100644 +index 449b1366314..35b893509cb 100644 --- a/Lib/test/test_hmac.py +++ b/Lib/test/test_hmac.py -@@ -3,6 +3,7 @@ +@@ -3,6 +3,7 @@ import hmac import hashlib import unittest import warnings +from _hashlib import get_fips_mode + from test.support import requires_hashdigest - def ignore_warning(func): -@@ -17,7 +18,7 @@ def wrapper(*args, **kwargs): - - class TestVectorsTestCase(unittest.TestCase): - -- @unittest.skipIf(hashlib.get_fips_mode(), 'md5 unacceptable in FIPS mode.') -+ @unittest.skipIf(get_fips_mode(), 'md5 unacceptable in FIPS mode.') - def test_md5_vectors(self): - # Test the HMAC module against test vectors from the RFC. - -@@ -243,7 +244,7 @@ def test_sha384_rfc4231(self): +@@ -250,7 +251,7 @@ class TestVectorsTestCase(unittest.TestCase): def test_sha512_rfc4231(self): self._rfc4231_test_cases(hashlib.sha512, 'sha512', 64, 128) - @unittest.skipIf(hashlib.get_fips_mode(), 'MockCrazyHash unacceptable in FIPS mode.') + @unittest.skipIf(get_fips_mode(), 'MockCrazyHash unacceptable in FIPS mode.') + @requires_hashdigest('sha256') def test_legacy_block_size_warnings(self): class MockCrazyHash(object): - """Ain't no block_size attribute here.""" -@@ -266,7 +267,7 @@ def digest(self): +@@ -274,6 +275,7 @@ class TestVectorsTestCase(unittest.TestCase): hmac.HMAC(b'a', b'b', digestmod=MockCrazyHash) self.fail('Expected warning about small block_size') -- @unittest.skipIf(hashlib.get_fips_mode(), 'md5 is not default in FIPS mode.') + @unittest.skipIf(get_fips_mode(), 'md5 is not default in FIPS mode.') def test_with_digestmod_warning(self): with self.assertWarns(PendingDeprecationWarning): key = b"\x0b" * 16 -@@ -278,7 +279,7 @@ def test_with_digestmod_warning(self): - - class ConstructorTestCase(unittest.TestCase): - -- @unittest.skipIf(hashlib.get_fips_mode(), 'md5 is not default in FIPS mode.') -+ @unittest.skipIf(get_fips_mode(), 'md5 is not default in FIPS mode.') - @ignore_warning - def test_normal(self): - # Standard constructor call. -@@ -343,7 +344,7 @@ def test_withmodule(self): - - class SanityTestCase(unittest.TestCase): - -- @unittest.skipIf(hashlib.get_fips_mode(), "md5 is not default in FIPS mode") -+ @unittest.skipIf(get_fips_mode(), "md5 is not default in FIPS mode") - @ignore_warning - def test_default_is_md5(self): - # Testing if HMAC defaults to MD5 algorithm. -@@ -365,7 +366,7 @@ def test_exercise_all_methods(self): +@@ -375,7 +377,7 @@ class SanityTestCase(unittest.TestCase): class CopyTestCase(unittest.TestCase): - @unittest.skipIf(hashlib.get_fips_mode(), "Internal attributes unavailable in FIPS mode") + @unittest.skipIf(get_fips_mode(), "Internal attributes unavailable in FIPS mode") + @requires_hashdigest('sha256') def test_attributes(self): # Testing if attributes are of same type. - h1 = hmac.HMAC(b"key", digestmod="sha1") -@@ -377,7 +378,7 @@ def test_attributes(self): +@@ -388,7 +390,7 @@ class CopyTestCase(unittest.TestCase): self.assertEqual(type(h1.outer), type(h2.outer), "Types of outer don't match.") - @unittest.skipIf(hashlib.get_fips_mode(), "Internal attributes unavailable in FIPS mode") + @unittest.skipIf(get_fips_mode(), "Internal attributes unavailable in FIPS mode") + @requires_hashdigest('sha256') def test_realcopy(self): # Testing if the copy method created a real copy. - h1 = hmac.HMAC(b"key", digestmod="sha1") diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py -index 0b229465983c..0028ae05a1b5 100644 +index d5c63b483ee..45b72e3bc7e 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py -@@ -47,6 +47,7 @@ +@@ -46,6 +46,7 @@ import time + import unittest import warnings import weakref - import hashlib -+from _hashlib import get_fips_mode - ++ try: import threading -@@ -1817,7 +1818,7 @@ def handle_request(self, request): - request.end_headers() - self.handled.set() - -- @unittest.skipIf(hashlib.get_fips_mode(), 'Hangs in FIPS mode.') -+ @unittest.skipIf(get_fips_mode(), 'Hangs in FIPS mode.') - def test_output(self): - # The log message sent to the HTTPHandler is properly received. - logger = logging.getLogger("http") + # The following imports are needed only for tests which diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py -index 150e9fbcf053..987b114f99ef 100644 +index 64b3201254a..704b2bc0d35 100644 --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py -@@ -16,6 +16,7 @@ +@@ -16,6 +16,8 @@ import time + import select import errno import textwrap - import hashlib ++import hashlib +from _hashlib import get_fips_mode import unittest from test import support, mock_socket -@@ -969,7 +970,7 @@ def testAUTH_LOGIN(self): - self.assertEqual(resp, (235, b'Authentication Succeeded')) - smtp.close() +@@ -980,7 +982,7 @@ class SMTPSimTests(unittest.TestCase): -- @unittest.skipIf(hashlib.get_fips_mode(), "md5 auth unacceptable in FIPS mode") -+ @unittest.skipIf(get_fips_mode(), "md5 auth unacceptable in FIPS mode") - def testAUTH_CRAM_MD5(self): - self.serv.add_feature("AUTH CRAM-MD5") - smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) -@@ -977,7 +978,7 @@ def testAUTH_CRAM_MD5(self): - self.assertEqual(resp, (235, b'Authentication Succeeded')) - smtp.close() - -- @unittest.skipIf(hashlib.get_fips_mode(), "md5 auth unacceptable in FIPS mode") -+ @unittest.skipIf(get_fips_mode(), "md5 auth unacceptable in FIPS mode") def testAUTH_multiple(self): # Test that multiple authentication methods are tried. - self.serv.add_feature("AUTH BOGUS PLAIN LOGIN CRAM-MD5") -@@ -986,7 +987,7 @@ def testAUTH_multiple(self): +- self.serv.add_feature("AUTH BOGUS PLAIN LOGIN CRAM-MD5") ++ self.serv.add_feature("AUTH BOGUS PLAIN LOGIN") + smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) + resp = smtp.login(sim_auth[0], sim_auth[1]) self.assertEqual(resp, (235, b'Authentication Succeeded')) - smtp.close() - -- @unittest.skipIf(hashlib.get_fips_mode(), "md5 auth unacceptable in FIPS mode") -+ @unittest.skipIf(get_fips_mode(), "md5 auth unacceptable in FIPS mode") - def test_auth_function(self): - supported = {'CRAM-MD5', 'PLAIN', 'LOGIN'} - for mechanism in supported: diff --git a/Lib/test/test_tools/test_md5sum.py b/Lib/test/test_tools/test_md5sum.py -index 7028a4dc2143..3ba1ca0f146c 100644 +index 7028a4dc214..3ba1ca0f146 100644 --- a/Lib/test/test_tools/test_md5sum.py +++ b/Lib/test/test_tools/test_md5sum.py -@@ -4,13 +4,13 @@ +@@ -4,13 +4,13 @@ import os import unittest from test import support from test.support.script_helper import assert_python_ok, assert_python_failure @@ -4816,10 +5288,10 @@ index 7028a4dc2143..3ba1ca0f146c 100644 class MD5SumTests(unittest.TestCase): diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py -index 2d0d62f610ef..84831ab2ac0e 100644 +index 895f97cc09a..b4fb13ad092 100644 --- a/Lib/test/test_urllib2_localnet.py +++ b/Lib/test/test_urllib2_localnet.py -@@ -6,6 +6,7 @@ +@@ -6,6 +6,7 @@ import urllib.request import http.server import unittest import hashlib @@ -4827,99 +5299,273 @@ index 2d0d62f610ef..84831ab2ac0e 100644 from test import support -@@ -317,7 +318,7 @@ def test_basic_auth_httperror(self): - self.assertRaises(urllib.error.HTTPError, urllib.request.urlopen, self.server_url) - - --@unittest.skipIf(hashlib.get_fips_mode(), "md5 digest auth unacceptable in FIPS mode") -+@unittest.skipIf(get_fips_mode(), "md5 digest auth unacceptable in FIPS mode") - @unittest.skipUnless(threading, "Threading required for this test.") - class ProxyAuthTests(unittest.TestCase): - URL = "http://localhost" +-- +2.21.0 -From 60afcf719206757577b6fc8c6ea119e02130a0f4 Mon Sep 17 00:00:00 2001 -From: Petr Viktorin -Date: Thu, 29 Aug 2019 10:25:28 +0200 -Subject: [PATCH 35/36] Skip error checking in _hashlib.get_fips_mode -Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1745499 +From 3538f31cc15c633f1df2d6ed18471c1f771c4a52 Mon Sep 17 00:00:00 2001 +From: Christian Heimes +Date: Wed, 20 Nov 2019 10:59:25 +0100 +Subject: [PATCH 35/36] Use FIPS compliant CSPRNG + +Kernel's getrandom() source is not yet FIPS compliant. Use OpenSSL's +DRBG in FIPS mode and disable os.getrandom() function. + +Signed-off-by: Christian Heimes --- - Modules/_hashopenssl.c | 30 ++++++++++++++++-------------- - 1 file changed, 16 insertions(+), 14 deletions(-) + Lib/test/test_os.py | 5 +++ + Makefile.pre.in | 2 +- + Modules/posixmodule.c | 8 +++++ + Python/random.c | 75 +++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 89 insertions(+), 1 deletion(-) -diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c -index b621c330c32d..6bfb12c5618b 100644 ---- a/Modules/_hashopenssl.c -+++ b/Modules/_hashopenssl.c -@@ -1021,20 +1021,22 @@ static PyObject * - _hashlib_get_fips_mode_impl(PyObject *module) - /*[clinic end generated code: output=ad8a7793310d3f98 input=f42a2135df2a5e11]*/ - { -- int result = FIPS_mode(); -- if (result == 0) { -- // "If the library was built without support of the FIPS Object Module, -- // then the function will return 0 with an error code of -- // CRYPTO_R_FIPS_MODE_NOT_SUPPORTED (0x0f06d065)." -- // But 0 is also a valid result value. -- -- unsigned long errcode = ERR_peek_last_error(); -- if (errcode) { -- _setException(PyExc_ValueError); -- return NULL; -- } -- } -- return PyLong_FromLong(result); -+ // XXX: This function skips error checking. -+ // This is only appropriate for RHEL. +diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py +index 7a839c83fe4..91816afa47d 100644 +--- a/Lib/test/test_os.py ++++ b/Lib/test/test_os.py +@@ -1362,6 +1362,11 @@ class GetRandomTests(unittest.TestCase): + raise unittest.SkipTest("getrandom() syscall fails with ENOSYS") + else: + raise ++ except ValueError as exc: ++ if exc.args[0] == "getrandom is not FIPS compliant": ++ raise unittest.SkipTest("Skip in FIPS mode") ++ else: ++ raise + + def test_getrandom_type(self): + data = os.getrandom(16) +diff --git a/Makefile.pre.in b/Makefile.pre.in +index d15d93509d1..40502fc36d6 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -112,7 +112,7 @@ CFLAGSFORSHARED=@CFLAGSFORSHARED@ + # C flags used for building the interpreter object files + PY_CORE_CFLAGS= $(PY_CFLAGS) $(PY_CFLAGS_NODIST) $(PY_CPPFLAGS) $(CFLAGSFORSHARED) -DPy_BUILD_CORE + # Linker flags used for building the interpreter object files +-PY_CORE_LDFLAGS=$(PY_LDFLAGS) $(PY_LDFLAGS_NODIST) ++PY_CORE_LDFLAGS=$(PY_LDFLAGS) $(PY_LDFLAGS_NODIST) -lcrypto + # Strict or non-strict aliasing flags used to compile dtoa.c, see above + CFLAGS_ALIASING=@CFLAGS_ALIASING@ + +diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c +index 776a3d249a8..647dbd3b4d6 100644 +--- a/Modules/posixmodule.c ++++ b/Modules/posixmodule.c +@@ -397,6 +397,9 @@ static int win32_can_symlink = 0; + #define MODNAME "posix" + #endif + ++/* for FIPS check in os.getrandom() */ ++#include + -+ // From the OpenSSL docs: -+ // "If the library was built without support of the FIPS Object Module, -+ // then the function will return 0 with an error code of -+ // CRYPTO_R_FIPS_MODE_NOT_SUPPORTED (0x0f06d065)." -+ // In RHEL: -+ // * we do build with FIPS, so the function always succeeds -+ // * even if it didn't, people seem used to errors being left on the -+ // OpenSSL error stack. + #ifdef MS_WINDOWS + /* defined in fileutils.c */ + PyAPI_FUNC(void) _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *); +@@ -12196,6 +12199,11 @@ os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags) + return posix_error(); + } + ++ if (FIPS_mode()) { ++ PyErr_SetString(PyExc_ValueError, "getrandom is not FIPS compliant"); ++ return NULL; ++ } + -+ // For more info, see: -+ // https://bugzilla.redhat.com/show_bug.cgi?id=1745499 -+ -+ return PyLong_FromLong(FIPS_mode()); + bytes = PyBytes_FromStringAndSize(NULL, size); + if (bytes == NULL) { + PyErr_NoMemory(); +diff --git a/Python/random.c b/Python/random.c +index d4747d61eb8..ab3cee29a39 100644 +--- a/Python/random.c ++++ b/Python/random.c +@@ -410,6 +410,77 @@ dev_urandom_close(void) } + #endif /* !MS_WINDOWS */ ++#include ++#include ++#include ++ ++#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || defined(LIBRESSL_VERSION_NUMBER) ++# error "py_openssl_drbg_urandom requires OpenSSL 1.1.1 for fork safety" ++#endif ++ ++static void ++py_openssl_set_exception(PyObject* exc) { ++ unsigned long errcode; ++ const char *lib, *func, *reason; ++ ++ errcode = ERR_peek_last_error(); ++ if (!errcode) { ++ PyErr_SetString(exc, "unknown reasons"); ++ } ++ ERR_clear_error(); ++ ++ lib = ERR_lib_error_string(errcode); ++ func = ERR_func_error_string(errcode); ++ reason = ERR_reason_error_string(errcode); ++ ++ if (lib && func) { ++ PyErr_Format(exc, "[%s: %s] %s", lib, func, reason); ++ } ++ else if (lib) { ++ PyErr_Format(exc, "[%s] %s", lib, reason); ++ } ++ else { ++ PyErr_SetString(exc, reason); ++ } ++} ++ ++static int ++py_openssl_drbg_urandom(char *buffer, Py_ssize_t size, int raise) ++{ ++ int res; ++ static int init = 0; ++ ++ if (!init) { ++ init = 1; ++ res = OPENSSL_init_crypto(OPENSSL_INIT_ATFORK, NULL); ++ if (res == 0) { ++ if (raise) { ++ py_openssl_set_exception(PyExc_RuntimeError); ++ } ++ return 0; ++ } ++ } ++ ++ if (size > INT_MAX) { ++ if (raise) { ++ PyErr_Format(PyExc_OverflowError, ++ "RAND_bytes() size is limited to 2GB."); ++ } ++ return -1; ++ } ++ ++ res = RAND_bytes((unsigned char*)buffer, (int)size); ++ ++ if (res == 1) { ++ return 1; ++ } else { ++ if (raise) { ++ py_openssl_set_exception(PyExc_RuntimeError); ++ } ++ return 0; ++ } ++} ++ -From 68b3c51d9c7d6bb635174e8d02db5c73ab521ea0 Mon Sep 17 00:00:00 2001 -From: Petr Viktorin -Date: Thu, 10 Oct 2019 13:04:50 +0200 -Subject: [PATCH] Skip error checking in _Py_hashlib_fips_error - -https://bugzilla.redhat.com/show_bug.cgi?id=1760106 ---- - Include/_hashopenssl.h | 12 +++--------- - 1 file changed, 3 insertions(+), 9 deletions(-) - -diff --git a/Include/_hashopenssl.h b/Include/_hashopenssl.h -index 47ed003042209..d4cbdef984d83 100644 ---- a/Include/_hashopenssl.h -+++ b/Include/_hashopenssl.h -@@ -42,16 +42,10 @@ static int - _Py_hashlib_fips_error(PyObject *exc, char *name) { - int result = FIPS_mode(); - if (result == 0) { -- // "If the library was built without support of the FIPS Object Module, -- // then the function will return 0 with an error code of -- // CRYPTO_R_FIPS_MODE_NOT_SUPPORTED (0x0f06d065)." -- // But 0 is also a valid result value. -+ // XXX: This function skips error checking. -+ // This is only appropriate for RHEL. -+ // See _hashlib.get_fips_mode for details. - -- unsigned long errcode = ERR_peek_last_error(); -- if (errcode) { -- _setException(exc); -- return 1; -- } + /* Fill buffer with pseudo-random bytes generated by a linear congruent + generator (LCG): +@@ -494,6 +565,10 @@ pyurandom(void *buffer, Py_ssize_t size, int blocking, int raise) return 0; } - PyErr_Format(exc, "%s is not available in FIPS mode", name); + ++ if (FIPS_mode()) { ++ return py_openssl_drbg_urandom(buffer, size, raise); ++ } ++ + #ifdef MS_WINDOWS + return win32_urandom((unsigned char *)buffer, size, raise); + #else +-- +2.21.0 + + +From ed4103bbd15a09bff4fb94a38d1b3f02df5e7c96 Mon Sep 17 00:00:00 2001 +From: Charalampos Stratakis +Date: Thu, 28 Nov 2019 17:26:02 +0100 +Subject: [PATCH 36/36] Fixups for FIPS compliant CSPRNG + +--- + Lib/test/test_os.py | 3 ++- + Python/random.c | 33 +++------------------------------ + 2 files changed, 5 insertions(+), 31 deletions(-) + +diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py +index 91816afa47d..f2572bb6c44 100644 +--- a/Lib/test/test_os.py ++++ b/Lib/test/test_os.py +@@ -27,6 +27,7 @@ import time + import unittest + import uuid + import warnings ++from _hashlib import get_fips_mode + from test import support + try: + import threading +@@ -1363,7 +1364,7 @@ class GetRandomTests(unittest.TestCase): + else: + raise + except ValueError as exc: +- if exc.args[0] == "getrandom is not FIPS compliant": ++ if get_fips_mode() and exc.args[0] == "getrandom is not FIPS compliant": + raise unittest.SkipTest("Skip in FIPS mode") + else: + raise +diff --git a/Python/random.c b/Python/random.c +index ab3cee29a39..222d651407c 100644 +--- a/Python/random.c ++++ b/Python/random.c +@@ -410,40 +410,13 @@ dev_urandom_close(void) + } + #endif /* !MS_WINDOWS */ + +-#include +-#include + #include ++#include <_hashopenssl.h> + + #if (OPENSSL_VERSION_NUMBER < 0x10101000L) || defined(LIBRESSL_VERSION_NUMBER) + # error "py_openssl_drbg_urandom requires OpenSSL 1.1.1 for fork safety" + #endif + +-static void +-py_openssl_set_exception(PyObject* exc) { +- unsigned long errcode; +- const char *lib, *func, *reason; +- +- errcode = ERR_peek_last_error(); +- if (!errcode) { +- PyErr_SetString(exc, "unknown reasons"); +- } +- ERR_clear_error(); +- +- lib = ERR_lib_error_string(errcode); +- func = ERR_func_error_string(errcode); +- reason = ERR_reason_error_string(errcode); +- +- if (lib && func) { +- PyErr_Format(exc, "[%s: %s] %s", lib, func, reason); +- } +- else if (lib) { +- PyErr_Format(exc, "[%s] %s", lib, reason); +- } +- else { +- PyErr_SetString(exc, reason); +- } +-} +- + static int + py_openssl_drbg_urandom(char *buffer, Py_ssize_t size, int raise) + { +@@ -455,7 +428,7 @@ py_openssl_drbg_urandom(char *buffer, Py_ssize_t size, int raise) + res = OPENSSL_init_crypto(OPENSSL_INIT_ATFORK, NULL); + if (res == 0) { + if (raise) { +- py_openssl_set_exception(PyExc_RuntimeError); ++ _setException(PyExc_RuntimeError); + } + return 0; + } +@@ -475,7 +448,7 @@ py_openssl_drbg_urandom(char *buffer, Py_ssize_t size, int raise) + return 1; + } else { + if (raise) { +- py_openssl_set_exception(PyExc_RuntimeError); ++ _setException(PyExc_RuntimeError); + } + return 0; + } +-- +2.21.0 diff --git a/SOURCES/00330-CVE-2018-20852.patch b/SOURCES/00330-CVE-2018-20852.patch new file mode 100644 index 0000000..380fc33 --- /dev/null +++ b/SOURCES/00330-CVE-2018-20852.patch @@ -0,0 +1,93 @@ +diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py +index adf956d..97599d4 100644 +--- a/Lib/http/cookiejar.py ++++ b/Lib/http/cookiejar.py +@@ -1148,6 +1148,11 @@ class DefaultCookiePolicy(CookiePolicy): + req_host, erhn = eff_request_host(request) + domain = cookie.domain + ++ if domain and not domain.startswith("."): ++ dotdomain = "." + domain ++ else: ++ dotdomain = domain ++ + # strict check of non-domain cookies: Mozilla does this, MSIE5 doesn't + if (cookie.version == 0 and + (self.strict_ns_domain & self.DomainStrictNonDomain) and +@@ -1160,7 +1165,7 @@ class DefaultCookiePolicy(CookiePolicy): + _debug(" effective request-host name %s does not domain-match " + "RFC 2965 cookie domain %s", erhn, domain) + return False +- if cookie.version == 0 and not ("."+erhn).endswith(domain): ++ if cookie.version == 0 and not ("."+erhn).endswith(dotdomain): + _debug(" request-host %s does not match Netscape cookie domain " + "%s", req_host, domain) + return False +@@ -1174,7 +1179,11 @@ class DefaultCookiePolicy(CookiePolicy): + req_host = "."+req_host + if not erhn.startswith("."): + erhn = "."+erhn +- if not (req_host.endswith(domain) or erhn.endswith(domain)): ++ if domain and not domain.startswith("."): ++ dotdomain = "." + domain ++ else: ++ dotdomain = domain ++ if not (req_host.endswith(dotdomain) or erhn.endswith(dotdomain)): + #_debug(" request domain %s does not match cookie domain %s", + # req_host, domain) + return False +diff --git a/Lib/test/test_http_cookiejar.py b/Lib/test/test_http_cookiejar.py +index abc625d..6e1b308 100644 +--- a/Lib/test/test_http_cookiejar.py ++++ b/Lib/test/test_http_cookiejar.py +@@ -415,6 +415,7 @@ class CookieTests(unittest.TestCase): + ("http://foo.bar.com/", ".foo.bar.com", True), + ("http://foo.bar.com/", "foo.bar.com", True), + ("http://foo.bar.com/", ".bar.com", True), ++ ("http://foo.bar.com/", "bar.com", True), + ("http://foo.bar.com/", "com", True), + ("http://foo.com/", "rhubarb.foo.com", False), + ("http://foo.com/", ".foo.com", True), +@@ -425,6 +426,8 @@ class CookieTests(unittest.TestCase): + ("http://foo/", "foo", True), + ("http://foo/", "foo.local", True), + ("http://foo/", ".local", True), ++ ("http://barfoo.com", ".foo.com", False), ++ ("http://barfoo.com", "foo.com", False), + ]: + request = urllib.request.Request(url) + r = pol.domain_return_ok(domain, request) +@@ -959,6 +962,33 @@ class CookieTests(unittest.TestCase): + c.add_cookie_header(req) + self.assertFalse(req.has_header("Cookie")) + ++ c.clear() ++ ++ pol.set_blocked_domains([]) ++ req = urllib.request.Request("http://acme.com/") ++ res = FakeResponse(headers, "http://acme.com/") ++ cookies = c.make_cookies(res, req) ++ c.extract_cookies(res, req) ++ self.assertEqual(len(c), 1) ++ ++ req = urllib.request.Request("http://acme.com/") ++ c.add_cookie_header(req) ++ self.assertTrue(req.has_header("Cookie")) ++ ++ req = urllib.request.Request("http://badacme.com/") ++ c.add_cookie_header(req) ++ self.assertFalse(pol.return_ok(cookies[0], req)) ++ self.assertFalse(req.has_header("Cookie")) ++ ++ p = pol.set_blocked_domains(["acme.com"]) ++ req = urllib.request.Request("http://acme.com/") ++ c.add_cookie_header(req) ++ self.assertFalse(req.has_header("Cookie")) ++ ++ req = urllib.request.Request("http://badacme.com/") ++ c.add_cookie_header(req) ++ self.assertFalse(req.has_header("Cookie")) ++ + def test_secure(self): + for ns in True, False: + for whitespace in " ", "": diff --git a/SOURCES/00332-CVE-2019-16056.patch b/SOURCES/00332-CVE-2019-16056.patch new file mode 100644 index 0000000..ca2e3d4 --- /dev/null +++ b/SOURCES/00332-CVE-2019-16056.patch @@ -0,0 +1,95 @@ +diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py +index 737951e4b1b1..bc9c9b6241d4 100644 +--- a/Lib/email/_header_value_parser.py ++++ b/Lib/email/_header_value_parser.py +@@ -1561,6 +1561,8 @@ def get_domain(value): + token, value = get_dot_atom(value) + except errors.HeaderParseError: + token, value = get_atom(value) ++ if value and value[0] == '@': ++ raise errors.HeaderParseError('Invalid Domain') + if leader is not None: + token[:0] = [leader] + domain.append(token) +diff --git a/Lib/email/_parseaddr.py b/Lib/email/_parseaddr.py +index cdfa3729adc7..41ff6f8c000d 100644 +--- a/Lib/email/_parseaddr.py ++++ b/Lib/email/_parseaddr.py +@@ -379,7 +379,12 @@ def getaddrspec(self): + aslist.append('@') + self.pos += 1 + self.gotonext() +- return EMPTYSTRING.join(aslist) + self.getdomain() ++ domain = self.getdomain() ++ if not domain: ++ # Invalid domain, return an empty address instead of returning a ++ # local part to denote failed parsing. ++ return EMPTYSTRING ++ return EMPTYSTRING.join(aslist) + domain + + def getdomain(self): + """Get the complete domain name from an address.""" +@@ -394,6 +399,10 @@ def getdomain(self): + elif self.field[self.pos] == '.': + self.pos += 1 + sdlist.append('.') ++ elif self.field[self.pos] == '@': ++ # bpo-34155: Don't parse domains with two `@` like ++ # `a@malicious.org@important.com`. ++ return EMPTYSTRING + elif self.field[self.pos] in self.atomends: + break + else: +diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py +index a2c900fa7fd2..02ef3e1006c6 100644 +--- a/Lib/test/test_email/test__header_value_parser.py ++++ b/Lib/test/test_email/test__header_value_parser.py +@@ -1418,6 +1418,16 @@ def test_get_addr_spec_dot_atom(self): + self.assertEqual(addr_spec.domain, 'example.com') + self.assertEqual(addr_spec.addr_spec, 'star.a.star@example.com') + ++ def test_get_addr_spec_multiple_domains(self): ++ with self.assertRaises(errors.HeaderParseError): ++ parser.get_addr_spec('star@a.star@example.com') ++ ++ with self.assertRaises(errors.HeaderParseError): ++ parser.get_addr_spec('star@a@example.com') ++ ++ with self.assertRaises(errors.HeaderParseError): ++ parser.get_addr_spec('star@172.17.0.1@example.com') ++ + # get_obs_route + + def test_get_obs_route_simple(self): +diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py +index f97ccc6711cc..68d052279987 100644 +--- a/Lib/test/test_email/test_email.py ++++ b/Lib/test/test_email/test_email.py +@@ -3035,6 +3035,20 @@ def test_parseaddr_empty(self): + self.assertEqual(utils.parseaddr('<>'), ('', '')) + self.assertEqual(utils.formataddr(utils.parseaddr('<>')), '') + ++ def test_parseaddr_multiple_domains(self): ++ self.assertEqual( ++ utils.parseaddr('a@b@c'), ++ ('', '') ++ ) ++ self.assertEqual( ++ utils.parseaddr('a@b.c@c'), ++ ('', '') ++ ) ++ self.assertEqual( ++ utils.parseaddr('a@172.17.0.1@c'), ++ ('', '') ++ ) ++ + def test_noquote_dump(self): + self.assertEqual( + utils.formataddr(('A Silly Person', 'person@dom.ain')), +diff --git a/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst +new file mode 100644 +index 000000000000..50292e29ed1d +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst +@@ -0,0 +1 @@ ++Fix parsing of invalid email addresses with more than one ``@`` (e.g. a@b@c.com.) to not return the part before 2nd ``@`` as valid email address. Patch by maxking & jpic. diff --git a/SOURCES/00333-reduce-pgo-tests.patch b/SOURCES/00333-reduce-pgo-tests.patch new file mode 100644 index 0000000..7dcd3b9 --- /dev/null +++ b/SOURCES/00333-reduce-pgo-tests.patch @@ -0,0 +1,296 @@ +diff --git a/Lib/test/libregrtest/cmdline.py b/Lib/test/libregrtest/cmdline.py +index 538ff05..e7f2013 100644 +--- a/Lib/test/libregrtest/cmdline.py ++++ b/Lib/test/libregrtest/cmdline.py +@@ -263,7 +263,9 @@ def _create_parser(): + help='only write the name of test cases that will be run' + ' , don\'t execute them') + group.add_argument('-P', '--pgo', dest='pgo', action='store_true', +- help='enable Profile Guided Optimization training') ++ help='enable Profile Guided Optimization (PGO) training') ++ group.add_argument('--pgo-extended', action='store_true', ++ help='enable extended PGO training (slower training)') + group.add_argument('--fail-env-changed', action='store_true', + help='if a test file alters the environment, mark ' + 'the test as failed') +@@ -339,6 +341,8 @@ def _parse_args(args, **kwargs): + parser.error("-G/--failfast needs either -v or -W") + if ns.pgo and (ns.verbose or ns.verbose2 or ns.verbose3): + parser.error("--pgo/-v don't go together!") ++ if ns.pgo_extended: ++ ns.pgo = True # pgo_extended implies pgo + + if ns.nowindows: + print("Warning: the --nowindows (-n) option is deprecated. " +diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py +index b6d05f6..524dbfa 100644 +--- a/Lib/test/libregrtest/main.py ++++ b/Lib/test/libregrtest/main.py +@@ -17,6 +17,7 @@ from test.libregrtest.runtest import ( + INTERRUPTED, CHILD_ERROR, TEST_DID_NOT_RUN, + PROGRESS_MIN_TIME, format_test_result) + from test.libregrtest.setup import setup_tests ++from test.libregrtest.pgo import setup_pgo_tests + from test.libregrtest.utils import removepy, count, format_duration, printlist + from test import support + try: +@@ -214,6 +215,10 @@ class Regrtest: + + removepy(self.tests) + ++ if self.ns.pgo: ++ # add default PGO tests if no tests are specified ++ setup_pgo_tests(self.ns) ++ + stdtests = STDTESTS[:] + nottests = NOTTESTS.copy() + if self.ns.exclude: +@@ -601,6 +606,7 @@ class Regrtest: + input("Press any key to continue...") + + support.PGO = self.ns.pgo ++ support.PGO_EXTENDED = self.ns.pgo_extended + + setup_tests(self.ns) + +diff --git a/Lib/test/libregrtest/pgo.py b/Lib/test/libregrtest/pgo.py +new file mode 100644 +index 0000000..379ff05 +--- /dev/null ++++ b/Lib/test/libregrtest/pgo.py +@@ -0,0 +1,55 @@ ++# Set of tests run by default if --pgo is specified. The tests below were ++# chosen based on the following criteria: either they exercise a commonly used ++# C extension module or type, or they run some relatively typical Python code. ++# Long running tests should be avoided because the PGO instrumented executable ++# runs slowly. ++PGO_TESTS = [ ++ 'test_array', ++ 'test_base64', ++ 'test_binascii', ++ 'test_binop', ++ 'test_bisect', ++ 'test_bytes', ++ 'test_bz2', ++ 'test_cmath', ++ 'test_codecs', ++ 'test_collections', ++ 'test_complex', ++ 'test_dataclasses', ++ 'test_datetime', ++ 'test_decimal', ++ 'test_difflib', ++ 'test_embed', ++ 'test_float', ++ 'test_fstring', ++ 'test_functools', ++ 'test_generators', ++ 'test_hashlib', ++ 'test_heapq', ++ 'test_int', ++ 'test_itertools', ++ 'test_json', ++ 'test_long', ++ 'test_lzma', ++ 'test_math', ++ 'test_memoryview', ++ 'test_operator', ++ 'test_ordered_dict', ++ 'test_pickle', ++ 'test_pprint', ++ 'test_re', ++ 'test_set', ++ 'test_sqlite', ++ 'test_statistics', ++ 'test_struct', ++ 'test_tabnanny', ++ 'test_time', ++ 'test_unicode', ++ 'test_xml_etree', ++ 'test_xml_etree_c', ++] ++ ++def setup_pgo_tests(ns): ++ if not ns.args and not ns.pgo_extended: ++ # run default set of tests for PGO training ++ ns.args = PGO_TESTS[:] +diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py +index 764057a..468ee46 100644 +--- a/Lib/test/pickletester.py ++++ b/Lib/test/pickletester.py +@@ -2039,6 +2039,7 @@ class AbstractPickleTests(unittest.TestCase): + + FRAME_SIZE_TARGET = 64 * 1024 + ++ @support.skip_if_pgo_task + def check_frame_opcodes(self, pickled): + """ + Check the arguments of FRAME opcodes in a protocol 4+ pickle. +@@ -2059,6 +2060,7 @@ class AbstractPickleTests(unittest.TestCase): + frame_size = len(pickled) - last_pos - frame_opcode_size + self.assertEqual(frame_size, last_arg) + ++ @support.skip_if_pgo_task + def test_framing_many_objects(self): + obj = list(range(10**5)) + for proto in range(4, pickle.HIGHEST_PROTOCOL + 1): +diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py +index 66c0fed..e80a819 100644 +--- a/Lib/test/support/__init__.py ++++ b/Lib/test/support/__init__.py +@@ -953,6 +953,10 @@ SAVEDCWD = os.getcwd() + # useful for PGO + PGO = False + ++# Set by libregrtest/main.py if we are running the extended (time consuming) ++# PGO task. If this is True, PGO is also True. ++PGO_EXTENDED = False ++ + @contextlib.contextmanager + def temp_dir(path=None, quiet=False): + """Return a context manager that creates a temporary directory. +@@ -2442,6 +2446,11 @@ def skip_unless_xattr(test): + msg = "no non-broken extended attribute support" + return test if ok else unittest.skip(msg)(test) + ++def skip_if_pgo_task(test): ++ """Skip decorator for tests not run in (non-extended) PGO task""" ++ ok = not PGO or PGO_EXTENDED ++ msg = "Not run for (non-extended) PGO task" ++ return test if ok else unittest.skip(msg)(test) + + def fs_is_case_insensitive(directory): + """Detects if the file system for the specified directory is case-insensitive.""" +diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py +index f340f23..ebb151c 100644 +--- a/Lib/test/test_bz2.py ++++ b/Lib/test/test_bz2.py +@@ -654,6 +654,7 @@ class BZ2CompressorTest(BaseTest): + data += bz2c.flush() + self.assertEqual(ext_decompress(data), self.TEXT) + ++ @support.skip_if_pgo_task + @bigmemtest(size=_4G + 100, memuse=2) + def testCompress4G(self, size): + # "Test BZ2Compressor.compress()/flush() with >4GiB input" +@@ -712,6 +713,7 @@ class BZ2DecompressorTest(BaseTest): + self.assertRaises(EOFError, bz2d.decompress, b"anything") + self.assertRaises(EOFError, bz2d.decompress, b"") + ++ @support.skip_if_pgo_task + @bigmemtest(size=_4G + 100, memuse=3.3) + def testDecompress4G(self, size): + # "Test BZ2Decompressor.decompress() with >4GiB input" +diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py +index 9317951..8c1d016 100644 +--- a/Lib/test/test_itertools.py ++++ b/Lib/test/test_itertools.py +@@ -2023,6 +2023,7 @@ class RegressionTests(unittest.TestCase): + self.assertRaises(AssertionError, list, cycle(gen1())) + self.assertEqual(hist, [0,1]) + ++ @support.skip_if_pgo_task + def test_long_chain_of_empty_iterables(self): + # Make sure itertools.chain doesn't run into recursion limits when + # dealing with long chains of empty iterables. Even with a high +diff --git a/Lib/test/test_lzma.py b/Lib/test/test_lzma.py +index 3dc2c1e..117de0a 100644 +--- a/Lib/test/test_lzma.py ++++ b/Lib/test/test_lzma.py +@@ -333,6 +333,7 @@ class CompressorDecompressorTestCase(unittest.TestCase): + + # Test with inputs larger than 4GiB. + ++ @support.skip_if_pgo_task + @bigmemtest(size=_4G + 100, memuse=2) + def test_compressor_bigmem(self, size): + lzc = LZMACompressor() +@@ -344,6 +345,7 @@ class CompressorDecompressorTestCase(unittest.TestCase): + finally: + ddata = None + ++ @support.skip_if_pgo_task + @bigmemtest(size=_4G + 100, memuse=3) + def test_decompressor_bigmem(self, size): + lzd = LZMADecompressor() +diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py +index 5347bb1..9d83217 100644 +--- a/Lib/test/test_regrtest.py ++++ b/Lib/test/test_regrtest.py +@@ -6,6 +6,7 @@ Note: test_regrtest cannot be run twice in parallel. + + import contextlib + import faulthandler ++import glob + import io + import os.path + import platform +@@ -532,6 +533,31 @@ class BaseTestCase(unittest.TestCase): + return proc.stdout + + ++class CheckActualTests(BaseTestCase): ++ """ ++ Check that regrtest appears to find the expected set of tests. ++ """ ++ ++ def test_finds_expected_number_of_tests(self): ++ args = ['-Wd', '-E', '-bb', '-m', 'test.regrtest', '--list-tests'] ++ output = self.run_python(args) ++ rough_number_of_tests_found = len(output.splitlines()) ++ actual_testsuite_glob = os.path.join(os.path.dirname(__file__), ++ 'test*.py') ++ rough_counted_test_py_files = len(glob.glob(actual_testsuite_glob)) ++ # We're not trying to duplicate test finding logic in here, ++ # just give a rough estimate of how many there should be and ++ # be near that. This is a regression test to prevent mishaps ++ # such as https://bugs.python.org/issue37667 in the future. ++ # If you need to change the values in here during some ++ # mythical future test suite reorganization, don't go ++ # overboard with logic and keep that goal in mind. ++ self.assertGreater(rough_number_of_tests_found, ++ rough_counted_test_py_files*9//10, ++ msg='Unexpectedly low number of tests found in:\n' ++ f'{", ".join(output.splitlines())}') ++ ++ + class ProgramsTestCase(BaseTestCase): + """ + Test various ways to run the Python test suite. Use options close +diff --git a/Makefile.pre.in b/Makefile.pre.in +index b452289..cc428ac 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -247,9 +247,10 @@ TCLTK_INCLUDES= @TCLTK_INCLUDES@ + TCLTK_LIBS= @TCLTK_LIBS@ + + # The task to run while instrumented when building the profile-opt target. +-# We exclude unittests with -x that take a rediculious amount of time to +-# run in the instrumented training build or do not provide much value. +-PROFILE_TASK=-m test.regrtest --pgo ++# To speed up profile generation, we don't run the full unit test suite ++# by default. The default is "-m test --pgo". To run more tests, use ++# PROFILE_TASK="-m test --pgo-extended" ++PROFILE_TASK= @PROFILE_TASK@ + + # report files for gcov / lcov coverage report + COVERAGE_INFO= $(abs_builddir)/coverage.info +diff --git a/configure.ac b/configure.ac +index c071ec3..816fc5a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1308,6 +1308,14 @@ else + DEF_MAKE_RULE="all" + fi + ++AC_ARG_VAR(PROFILE_TASK, Python args for PGO generation task) ++AC_MSG_CHECKING(PROFILE_TASK) ++if test -z "$PROFILE_TASK" ++then ++ PROFILE_TASK='-m test --pgo' ++fi ++AC_MSG_RESULT($PROFILE_TASK) ++ + # Make llvm-relatec checks work on systems where llvm tools are not installed with their + # normal names in the default $PATH (ie: Ubuntu). They exist under the + # non-suffixed name in their versioned llvm directory. diff --git a/SPECS/python3.spec b/SPECS/python3.spec index f61528d..d786e5c 100644 --- a/SPECS/python3.spec +++ b/SPECS/python3.spec @@ -14,7 +14,7 @@ URL: https://www.python.org/ # WARNING When rebasing to a new Python version, # remember to update the python3-docs package as well Version: %{pybasever}.8 -Release: 15.1%{?dist} +Release: 23%{?dist} License: Python @@ -30,13 +30,7 @@ License: Python %bcond_without rpmwheels # Expensive optimizations (mainly, profile-guided optimizations) -%ifarch %{ix86} x86_64 %bcond_without optimizations -%else -# On some architectures, the optimized build takes tens of hours, possibly -# longer than Koji's 24-hour timeout. Disable optimizations here. -%bcond_with optimizations -%endif # Run the test suite in %%check %bcond_without tests @@ -357,6 +351,13 @@ Patch274: 00274-fix-arch-names.patch # See also: https://bugzilla.redhat.com/show_bug.cgi?id=1489816 Patch294: 00294-define-TLS-cipher-suite-on-build-time.patch +# 00316 # +# We remove the exe files from distutil's bdist_wininst +# So we mark the command as unsupported - and the tests are skipped +# Fixed upstream and backported from the 3.7 branch: https://bugs.python.org/issue10945 +# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1754040 +Patch316: 00316-mark-bdist_wininst-unsupported.patch + # 00317 # # Security fix for CVE-2019-5010: Fix segfault in ssl's cert parser # https://bugzilla.redhat.com/show_bug.cgi?id=1666789 @@ -364,11 +365,29 @@ Patch294: 00294-define-TLS-cipher-suite-on-build-time.patch Patch317: 00317-CVE-2019-5010.patch # 00318 # -# test_ssl fixes for TLS 1.3 and OpenSSL 1.1.1 +# Various fixes for TLS 1.3 and OpenSSL 1.1.1 # https://bugzilla.redhat.com/show_bug.cgi?id=1639531 + +# test_ssl fixes for TLS 1.3 and OpenSSL 1.1.1 # https://bugs.python.org/issue32947#msg333990 # https://github.com/python/cpython/pull/11612 -Patch318: 00318-test-ssl-fix-for-tls-13.patch + +# Encrypt private key test files with AES256 +# https://bugs.python.org/issue38271 +# https://github.com/python/cpython/pull/16396 + +# Prefer PROTOCOL_TLS_CLIENT/SERVER (partial backport) +# https://bugs.python.org/issue31346 +# https://github.com/python/cpython/pull/3058 + +# Enable TLS 1.3 in tests (partial backport) +# https://bugs.python.org/issue33618 +# https://github.com/python/cpython/pull/7082 + +# OpenSSL 1.1.1-pre1 / TLS 1.3 fixes (partial backport) +# https://bugs.python.org/issue32947 +# https://github.com/python/cpython/pull/5923 +Patch318: 00318-fixes-for-tls-13.patch # 00319 # # Fix test_tarfile on ppc64 @@ -419,6 +438,8 @@ Patch327: 00327-enable-tls-1.3-PHA-in-http.client.patch # - add a new "usedforsecurity" keyword argument to the various digest # algorithms in hashlib so that you can whitelist a callsite with # "usedforsecurity=False" +# The change has been implemented upstream since Python 3.9: +# https://bugs.python.org/issue9216 # - OpenSSL wrappers for the hashes blake2{b512,s256}, # sha3_{224,256,384,512}, shake_{128,256} are now exported from _hashlib # - In FIPS mode, the blake2, sha3 and shake hashes use OpenSSL wrappers @@ -426,9 +447,47 @@ Patch327: 00327-enable-tls-1.3-PHA-in-http.client.patch # - In FIPS mode, hmac.HMAC can only be instantiated with an OpenSSL wrapper # or an string with OpenSSL hash name as the "digestmod" argument. # The argument must be specified (instead of defaulting to ‘md5’). +# +# - Also while in FIPS mode, we utilize OpenSSL's DRBG and disable the +# os.getrandom() function. +# +# Upstream changes that have also been backported with this patch +# to allow tests to pass on stricter environments: +# +# Avoid MD5 or check for MD5 availablity +# https://bugs.python.org/issue38270 +# https://github.com/python/cpython/pull/16393 +# https://github.com/python/cpython/pull/16437 +# https://github.com/python/cpython/pull/17446 +# +# add usedforsecurity to hashlib constructors (partial backport for fixing a uuid test) +# https://github.com/python/cpython/pull/16044 # Resolves: rhbz#1731424 Patch329: 00329-fips.patch +# 00330 # +# Fix CVE-2018-20852: cookie domain check returning incorrect results +# Fixed upstream: https://bugs.python.org/issue35121 +# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1741553 +Patch330: 00330-CVE-2018-20852.patch + +# 00332 # +# Fix CVE-2019-16056: Don't parse email addresses containing +# multiple '@' characters. +# Fixed upstream: https://bugs.python.org/issue34155 +# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1750776 +Patch332: 00332-CVE-2019-16056.patch + +# 00333 # +# Reduce the number of tests run during the profile guided optimizations build, +# as running the whole test suite during profiling increases the build time +# substantially, with negligible performance gain. +# Fixed upstream and backported from the 3.8 branch: +# https://bugs.python.org/issue36044 +# https://bugs.python.org/issue37667 +# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1749576 +Patch333: 00333-reduce-pgo-tests.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -456,16 +515,20 @@ Requires: %{name}-libs%{?_isa} = %{version}-%{release} %if %{with rpmwheels} -# RHEL8 was forked from F28 and thus required python3-setuptools/pip here +# RHEL8 was forked from F28 and thus required python3-setuptools here # for the rewheel module to work. We've since backported the use of RPM # prepared wheels from F29+ into RHEL8, and thus this dependency isn't # strictly needed. # However, it is possible, that some packages in BaseOS actually depend on -# setuptools/pip without declaring the dependency in their spec file. Thus -# we're keeping these dependencies here to avoid the possibility of breaking +# setuptools without declaring the dependency in their spec file. Thus +# we're keeping this dependency here to avoid the possibility of breaking # them. Requires: platform-python-setuptools -Requires: platform-python-pip +# For python3-pip the Requires has been reduced to Recommends, as there are +# generally less packages that depend on pip than packages that depend on +# setuptools at runtime, and thus there's less chance of breakage. +# (rhbz#1756217). +Recommends: platform-python-pip Requires: python3-setuptools-wheel Requires: python3-pip-wheel @@ -727,6 +790,7 @@ rm Lib/ensurepip/_bundled/*.whl %patch262 -p1 %patch274 -p1 %patch294 -p1 +%patch316 -p1 %patch317 -p1 %patch318 -p1 %patch319 -p1 @@ -736,6 +800,9 @@ rm Lib/ensurepip/_bundled/*.whl %patch326 -p1 %patch327 -p1 %patch329 -p1 +%patch330 -p1 +%patch332 -p1 +%patch333 -p1 # Remove files that should be generated by the build @@ -823,7 +890,7 @@ BuildPython() { %{nil} # Invoke the build - make EXTRA_CFLAGS="$CFLAGS $MoreCFlags" %{?_smp_mflags} + %make_build CFLAGS_NODIST="$CFLAGS_NODIST $MoreCFlags" popd echo FINISHED: BUILD OF PYTHON FOR CONFIGURATION: $ConfName @@ -1162,17 +1229,10 @@ CheckPython() { WITHIN_PYTHON_RPM_BUILD= \ LD_LIBRARY_PATH=$ConfDir $ConfDir/python -m test.regrtest \ -wW --slowest --findleaks \ - -x test_distutils \ -x test_bdist_rpm \ %ifarch %{mips64} -x test_ctypes \ %endif - %ifarch s390x - -x test_gdb \ - %endif - %ifarch ppc64le - -x test_gdb \ - %endif echo FINISHED: CHECKING OF PYTHON FOR CONFIGURATION: $ConfName @@ -1660,11 +1720,42 @@ fi # ====================================================== %changelog -* Fri Oct 11 2019 Tomas Orsava - 3.6.8-15.1 +* Wed Nov 27 2019 Charalampos Stratakis - 3.6.8-23 +- Modify the test suite to better handle disabled SSL/TLS versions and FIPS mode +- Use OpenSSL's DRBG and disable os.getrandom() function in FIPS mode +Resolves: rhbz#1754028, rhbz#1754027, rhbz#1754026, rhbz#1774471 + +* Thu Oct 24 2019 Tomas Orsava - 3.6.8-22 +- Changed Requires into Recommends for python3-pip to allow a lower RHEL8 + footprint for containers and other minimal environments +Resolves: rhbz#1756217 + +* Wed Oct 16 2019 Tomas Orsava - 3.6.8-21 - Patch 329 (FIPS) modified: Added workaround for mod_ssl: Skip error checking in _Py_hashlib_fips_error Resolves: rhbz#1760106 +* Mon Oct 14 2019 Charalampos Stratakis - 3.6.8-20 +- Security fix for CVE-2019-16056 +Resolves: rhbz#1750776 + +* Wed Oct 09 2019 Charalampos Stratakis - 3.6.8-19 +- Skip windows specific test_get_exe_bytes test case and enable test_distutils +Resolves: rhbz#1754040 + +* Mon Oct 07 2019 Charalampos Stratakis - 3.6.8-18 +- Reduce the number of tests running during the profile guided optimizations build +- Enable profile guided optimizations for all the supported architectures +Resolves: rhbz#1749576 + +* Mon Oct 07 2019 Charalampos Stratakis - 3.6.8-17 +- Security fix for CVE-2018-20852 +Resolves: rhbz#1741553 + +* Fri Oct 04 2019 Charalampos Stratakis - 3.6.8-16 +- Properly pass the -Og optimization flag to the debug build +Resolves: rhbz#1712977 and rhbz#1714733 + * Thu Aug 29 2019 Tomas Orsava - 3.6.8-15 - Patch 329 that adds support for OpenSSL FIPS mode has been improved and bugfixed