carlwgeorge / rpms / python34

Forked from rpms/python34 6 years ago
Clone

Blame 00146-hashlib-fips.patch

Matej Stuchlik 2c1c983
--- Python-3.4.0b1/Lib/hashlib.py.hashlib-fips	2013-11-24 21:36:54.000000000 +0100
Matej Stuchlik 2c1c983
+++ Python-3.4.0b1/Lib/hashlib.py	2013-11-27 11:45:17.073617547 +0100
Matej Stuchlik 2c1c983
@@ -23,6 +23,16 @@
Matej Stuchlik 2c1c983
 Choose your hash function wisely.  Some have known collision weaknesses.
Matej Stuchlik 2c1c983
 sha384 and sha512 will be slow on 32 bit platforms.
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
+If the underlying implementation supports "FIPS mode", and this is enabled, it
Matej Stuchlik 2c1c983
+may restrict the available hashes to only those that are compliant with FIPS
Matej Stuchlik 2c1c983
+regulations.  For example, it may deny the use of MD5, on the grounds that this
Matej Stuchlik 2c1c983
+is not secure for uses such as authentication, system integrity checking, or
Matej Stuchlik 2c1c983
+digital signatures.   If you need to use such a hash for non-security purposes
Matej Stuchlik 2c1c983
+(such as indexing into a data structure for speed), you can override the keyword
Matej Stuchlik 2c1c983
+argument "usedforsecurity" from True to False to signify that your code is not
Matej Stuchlik 2c1c983
+relying on the hash for security purposes, and this will allow the hash to be
Matej Stuchlik 2c1c983
+usable even in FIPS mode.
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
 Hash objects have these methods:
Matej Stuchlik 2c1c983
  - update(arg): Update the hash object with the bytes in arg. Repeated calls
Matej Stuchlik 2c1c983
                 are equivalent to a single call with the concatenation of all
Matej Stuchlik 2c1c983
@@ -63,6 +73,19 @@
Matej Stuchlik 2c1c983
 __all__ = __always_supported + ('new', 'algorithms_guaranteed',
Matej Stuchlik 2c1c983
                                 'algorithms_available', 'pbkdf2_hmac')
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
+import functools
Matej Stuchlik 2c1c983
+def __ignore_usedforsecurity(func):
Matej Stuchlik 2c1c983
+    """Used for sha3_* functions. Until OpenSSL implements them, we want
Matej Stuchlik 2c1c983
+    to use them from Python _sha3 module, but we want them to accept
Matej Stuchlik 2c1c983
+    usedforsecurity argument too."""
Matej Stuchlik 2c1c983
+    # TODO: remove this function when OpenSSL implements sha3
Matej Stuchlik 2c1c983
+    @functools.wraps(func)
Matej Stuchlik 2c1c983
+    def inner(*args, **kwargs):
Matej Stuchlik 2c1c983
+        if 'usedforsecurity' in kwargs:
Matej Stuchlik 2c1c983
+            kwargs.pop('usedforsecurity')
Matej Stuchlik 2c1c983
+        return func(*args, **kwargs)
Matej Stuchlik 2c1c983
+    return inner
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
 __builtin_constructor_cache = {}
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
@@ -108,34 +131,41 @@
Matej Stuchlik 2c1c983
         f = getattr(_hashlib, 'openssl_' + name)
Matej Stuchlik 2c1c983
         # Allow the C module to raise ValueError.  The function will be
Matej Stuchlik 2c1c983
         # defined but the hash not actually available thanks to OpenSSL.
Matej Stuchlik 2c1c983
-        f()
Matej Stuchlik 2c1c983
+        # We pass "usedforsecurity=False" to disable FIPS-based restrictions:
Matej Stuchlik 2c1c983
+        # at this stage we're merely seeing if the function is callable,
Matej Stuchlik 2c1c983
+        # rather than using it for actual work.
Matej Stuchlik 2c1c983
+        f(usedforsecurity=False)
Matej Stuchlik 2c1c983
         # Use the C function directly (very fast)
Matej Stuchlik 2c1c983
         return f
Matej Stuchlik 2c1c983
     except (AttributeError, ValueError):
Matej Stuchlik 2c1c983
+        # TODO: We want to just raise here when OpenSSL implements sha3
Matej Stuchlik 2c1c983
+        # because we want to make sure that Fedora uses everything from OpenSSL
Matej Stuchlik 2c1c983
         return __get_builtin_constructor(name)
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
-def __py_new(name, data=b''):
Matej Stuchlik 2c1c983
-    """new(name, data=b'') - Return a new hashing object using the named algorithm;
Matej Stuchlik 2c1c983
-    optionally initialized with data (which must be bytes).
Matej Stuchlik 2c1c983
+def __py_new(name, data=b'', usedforsecurity=True):
Matej Stuchlik 2c1c983
+    """new(name, data=b'', usedforsecurity=True) - Return a new hashing object using
Matej Stuchlik 2c1c983
+    the named algorithm; optionally initialized with data (which must be bytes).
Matej Stuchlik 2c1c983
+    The 'usedforsecurity' keyword argument does nothing, and is for compatibilty
Matej Stuchlik 2c1c983
+    with the OpenSSL implementation
Matej Stuchlik 2c1c983
     """
Matej Stuchlik 2c1c983
     return __get_builtin_constructor(name)(data)
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
-def __hash_new(name, data=b''):
Matej Stuchlik 2c1c983
-    """new(name, data=b'') - Return a new hashing object using the named algorithm;
Matej Stuchlik 2c1c983
-    optionally initialized with data (which must be bytes).
Matej Stuchlik 2c1c983
+def __hash_new(name, data=b'', usedforsecurity=True):
Matej Stuchlik 2c1c983
+    """new(name, data=b'', usedforsecurity=True) - Return a new hashing object using
Matej Stuchlik 2c1c983
+    the named algorithm; optionally initialized with data (which must be bytes).
Matej Stuchlik 2c1c983
+    
Matej Stuchlik 2c1c983
+    Override 'usedforsecurity' to False when using for non-security purposes in
Matej Stuchlik 2c1c983
+    a FIPS environment
Matej Stuchlik 2c1c983
     """
Matej Stuchlik 2c1c983
     try:
Matej Stuchlik 2c1c983
-        return _hashlib.new(name, data)
Matej Stuchlik 2c1c983
+        return _hashlib.new(name, data, usedforsecurity)
Matej Stuchlik 2c1c983
     except ValueError:
Matej Stuchlik 2c1c983
-        # If the _hashlib module (OpenSSL) doesn't support the named
Matej Stuchlik 2c1c983
-        # hash, try using our builtin implementations.
Matej Stuchlik 2c1c983
-        # This allows for SHA224/256 and SHA384/512 support even though
Matej Stuchlik 2c1c983
-        # the OpenSSL library prior to 0.9.8 doesn't provide them.
Matej Stuchlik 2c1c983
+        # TODO: We want to just raise here when OpenSSL implements sha3
Matej Stuchlik 2c1c983
+        # because we want to make sure that Fedora uses everything from OpenSSL
Matej Stuchlik 2c1c983
         return __get_builtin_constructor(name)(data)
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
-
Matej Stuchlik 2c1c983
 try:
Matej Stuchlik 2c1c983
     import _hashlib
Matej Stuchlik 2c1c983
     new = __hash_new
Matej Stuchlik 2c1c983
@@ -215,7 +245,10 @@
Matej Stuchlik 2c1c983
     # try them all, some may not work due to the OpenSSL
Matej Stuchlik 2c1c983
     # version not supporting that algorithm.
Matej Stuchlik 2c1c983
     try:
Matej Stuchlik 2c1c983
-        globals()[__func_name] = __get_hash(__func_name)
Matej Stuchlik 2c1c983
+        func = __get_hash(__func_name)
Matej Stuchlik 2c1c983
+        if 'sha3_' in __func_name:
Matej Stuchlik 2c1c983
+            func = __ignore_usedforsecurity(func)
Matej Stuchlik 2c1c983
+        globals()[__func_name] = func
Matej Stuchlik 2c1c983
     except ValueError:
Matej Stuchlik 2c1c983
         import logging
Matej Stuchlik 2c1c983
         logging.exception('code for hash %s was not found.', __func_name)
Matej Stuchlik 2c1c983
@@ -223,3 +256,4 @@
Matej Stuchlik 2c1c983
 # Cleanup locals()
Matej Stuchlik 2c1c983
 del __always_supported, __func_name, __get_hash
Matej Stuchlik 2c1c983
 del __py_new, __hash_new, __get_openssl_constructor
Matej Stuchlik 2c1c983
+del __ignore_usedforsecurity
Matej Stuchlik 2c1c983
--- Python-3.4.0b1/Lib/test/test_hashlib.py	2013-11-27 11:55:42.769601363 +0100
Matej Stuchlik 2c1c983
+++ Python-3.4.0b1/Lib/test/test_hashlib.py	2013-11-28 09:33:03.929008508 +0100
Matej Stuchlik 2c1c983
@@ -24,7 +24,22 @@
Matej Stuchlik 2c1c983
 COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount')
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
 c_hashlib = import_fresh_module('hashlib', fresh=['_hashlib'])
Matej Stuchlik 2c1c983
-py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib'])
Matej Stuchlik 2c1c983
+# skipped on Fedora, since we always use OpenSSL implementation
Matej Stuchlik 2c1c983
+# py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib'])
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+def openssl_enforces_fips():
Matej Stuchlik 2c1c983
+    # Use the "openssl" command (if present) to try to determine if the local
Matej Stuchlik 2c1c983
+    # OpenSSL is configured to enforce FIPS
Matej Stuchlik 2c1c983
+    from subprocess import Popen, PIPE
Matej Stuchlik 2c1c983
+    try:
Matej Stuchlik 2c1c983
+        p = Popen(['openssl', 'md5'],
Matej Stuchlik 2c1c983
+                  stdin=PIPE, stdout=PIPE, stderr=PIPE)
Matej Stuchlik 2c1c983
+    except OSError:
Matej Stuchlik 2c1c983
+        # "openssl" command not found
Matej Stuchlik 2c1c983
+        return False
Matej Stuchlik 2c1c983
+    stdout, stderr = p.communicate(input=b'abc')
Matej Stuchlik 2c1c983
+    return b'unknown cipher' in stderr
Matej Stuchlik 2c1c983
+OPENSSL_ENFORCES_FIPS = openssl_enforces_fips()
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
 def hexstr(s):
Matej Stuchlik 2c1c983
     assert isinstance(s, bytes), repr(s)
Matej Stuchlik 2c1c983
@@ -34,6 +49,16 @@
Matej Stuchlik 2c1c983
         r += h[(i >> 4) & 0xF] + h[i & 0xF]
Matej Stuchlik 2c1c983
     return r
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
+# hashlib and _hashlib-based functions support a "usedforsecurity" keyword
Matej Stuchlik 2c1c983
+# argument, and FIPS mode requires that it be used overridden with a False
Matej Stuchlik 2c1c983
+# value for these selftests to work.  Other cryptographic code within Python
Matej Stuchlik 2c1c983
+# doesn't support this keyword.
Matej Stuchlik 2c1c983
+# Modify a function to one in which "usedforsecurity=False" is added to the
Matej Stuchlik 2c1c983
+# keyword arguments:
Matej Stuchlik 2c1c983
+def suppress_fips(f):
Matej Stuchlik 2c1c983
+    def g(*args, **kwargs):
Matej Stuchlik 2c1c983
+        return f(*args, usedforsecurity=False, **kwargs)
Matej Stuchlik 2c1c983
+    return g
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
 class HashLibTestCase(unittest.TestCase):
Matej Stuchlik 2c1c983
     supported_hash_names = ( 'md5', 'MD5', 'sha1', 'SHA1',
Matej Stuchlik 2c1c983
@@ -66,11 +91,11 @@
Matej Stuchlik 2c1c983
         # For each algorithm, test the direct constructor and the use
Matej Stuchlik 2c1c983
         # of hashlib.new given the algorithm name.
Matej Stuchlik 2c1c983
         for algorithm, constructors in self.constructors_to_test.items():
Matej Stuchlik 2c1c983
-            constructors.add(getattr(hashlib, algorithm))
Matej Stuchlik 2c1c983
+            constructors.add(suppress_fips(getattr(hashlib, algorithm)))
Matej Stuchlik 2c1c983
             def _test_algorithm_via_hashlib_new(data=None, _alg=algorithm):
Matej Stuchlik 2c1c983
                 if data is None:
Matej Stuchlik 2c1c983
-                    return hashlib.new(_alg)
Matej Stuchlik 2c1c983
-                return hashlib.new(_alg, data)
Matej Stuchlik 2c1c983
+                    return suppress_fips(hashlib.new)(_alg)
Matej Stuchlik 2c1c983
+                return suppress_fips(hashlib.new)(_alg, data)
Matej Stuchlik 2c1c983
             constructors.add(_test_algorithm_via_hashlib_new)
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
         _hashlib = self._conditional_import_module('_hashlib')
Matej Stuchlik 2c1c983
@@ -82,26 +107,12 @@
Matej Stuchlik 2c1c983
             for algorithm, constructors in self.constructors_to_test.items():
Matej Stuchlik 2c1c983
                 constructor = getattr(_hashlib, 'openssl_'+algorithm, None)
Matej Stuchlik 2c1c983
                 if constructor:
Matej Stuchlik 2c1c983
-                    constructors.add(constructor)
Matej Stuchlik 2c1c983
+                    constructors.add(suppress_fips(constructor))
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
         def add_builtin_constructor(name):
Matej Stuchlik 2c1c983
             constructor = getattr(hashlib, "__get_builtin_constructor")(name)
Matej Stuchlik 2c1c983
             self.constructors_to_test[name].add(constructor)
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
-        _md5 = self._conditional_import_module('_md5')
Matej Stuchlik 2c1c983
-        if _md5:
Matej Stuchlik 2c1c983
-            add_builtin_constructor('md5')
Matej Stuchlik 2c1c983
-        _sha1 = self._conditional_import_module('_sha1')
Matej Stuchlik 2c1c983
-        if _sha1:
Matej Stuchlik 2c1c983
-            add_builtin_constructor('sha1')
Matej Stuchlik 2c1c983
-        _sha256 = self._conditional_import_module('_sha256')
Matej Stuchlik 2c1c983
-        if _sha256:
Matej Stuchlik 2c1c983
-            add_builtin_constructor('sha224')
Matej Stuchlik 2c1c983
-            add_builtin_constructor('sha256')
Matej Stuchlik 2c1c983
-        _sha512 = self._conditional_import_module('_sha512')
Matej Stuchlik 2c1c983
-        if _sha512:
Matej Stuchlik 2c1c983
-            add_builtin_constructor('sha384')
Matej Stuchlik 2c1c983
-            add_builtin_constructor('sha512')
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
         super(HashLibTestCase, self).__init__(*args, **kwargs)
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
@@ -157,9 +169,6 @@
Matej Stuchlik 2c1c983
             else:
Matej Stuchlik 2c1c983
                 del sys.modules['_md5']
Matej Stuchlik 2c1c983
         self.assertRaises(TypeError, get_builtin_constructor, 3)
Matej Stuchlik 2c1c983
-        constructor = get_builtin_constructor('md5')
Matej Stuchlik 2c1c983
-        self.assertIs(constructor, _md5.md5)
Matej Stuchlik 2c1c983
-        self.assertEqual(sorted(builtin_constructor_cache), ['MD5', 'md5'])
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
     def test_hexdigest(self):
Matej Stuchlik 2c1c983
         for cons in self.hash_constructors:
Matej Stuchlik 2c1c983
@@ -558,6 +567,65 @@
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
         self.assertEqual(expected_hash, hasher.hexdigest())
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
+    def test_issue9146(self):
Matej Stuchlik 2c1c983
+        # Ensure that various ways to use "MD5" from "hashlib" don't segfault:
Matej Stuchlik 2c1c983
+        m = hashlib.md5(usedforsecurity=False)
Matej Stuchlik 2c1c983
+        m.update(b'abc\n')
Matej Stuchlik 2c1c983
+        self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
Matej Stuchlik 2c1c983
+        
Matej Stuchlik 2c1c983
+        m = hashlib.new('md5', usedforsecurity=False)
Matej Stuchlik 2c1c983
+        m.update(b'abc\n')
Matej Stuchlik 2c1c983
+        self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
Matej Stuchlik 2c1c983
+        
Matej Stuchlik 2c1c983
+        m = hashlib.md5(b'abc\n', usedforsecurity=False)
Matej Stuchlik 2c1c983
+        self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
Matej Stuchlik 2c1c983
+        
Matej Stuchlik 2c1c983
+        m = hashlib.new('md5', b'abc\n', usedforsecurity=False)
Matej Stuchlik 2c1c983
+        self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+    @unittest.skipUnless(OPENSSL_ENFORCES_FIPS,
Matej Stuchlik 2c1c983
+                         'FIPS enforcement required for this test.')
Matej Stuchlik 2c1c983
+    def test_hashlib_fips_mode(self):        
Matej Stuchlik 2c1c983
+        # Ensure that we raise a ValueError on vanilla attempts to use MD5
Matej Stuchlik 2c1c983
+        # in hashlib in a FIPS-enforced setting:
Matej Stuchlik 2c1c983
+        with self.assertRaisesRegexp(ValueError, '.*unknown cipher'):
Matej Stuchlik 2c1c983
+            m = hashlib.md5()
Matej Stuchlik 2c1c983
+            
Matej Stuchlik 2c1c983
+        if not self._conditional_import_module('_md5'):
Matej Stuchlik 2c1c983
+            with self.assertRaisesRegexp(ValueError, '.*unknown cipher'):
Matej Stuchlik 2c1c983
+                m = hashlib.new('md5')
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+    @unittest.skipUnless(OPENSSL_ENFORCES_FIPS,
Matej Stuchlik 2c1c983
+                         'FIPS enforcement required for this test.')
Matej Stuchlik 2c1c983
+    def test_hashopenssl_fips_mode(self):
Matej Stuchlik 2c1c983
+        # Verify the _hashlib module's handling of md5:
Matej Stuchlik 2c1c983
+        _hashlib = self._conditional_import_module('_hashlib')
Matej Stuchlik 2c1c983
+        if _hashlib:
Matej Stuchlik 2c1c983
+            assert hasattr(_hashlib, 'openssl_md5')
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+            # Ensure that _hashlib raises a ValueError on vanilla attempts to
Matej Stuchlik 2c1c983
+            # use MD5 in a FIPS-enforced setting:
Matej Stuchlik 2c1c983
+            with self.assertRaisesRegexp(ValueError, '.*unknown cipher'):
Matej Stuchlik 2c1c983
+                m = _hashlib.openssl_md5()
Matej Stuchlik 2c1c983
+            with self.assertRaisesRegexp(ValueError, '.*unknown cipher'):
Matej Stuchlik 2c1c983
+                m = _hashlib.new('md5')
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+            # Ensure that in such a setting we can whitelist a callsite with
Matej Stuchlik 2c1c983
+            # usedforsecurity=False and have it succeed:
Matej Stuchlik 2c1c983
+            m = _hashlib.openssl_md5(usedforsecurity=False)
Matej Stuchlik 2c1c983
+            m.update(b'abc\n')
Matej Stuchlik 2c1c983
+            self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
Matej Stuchlik 2c1c983
+        
Matej Stuchlik 2c1c983
+            m = _hashlib.new('md5', usedforsecurity=False)
Matej Stuchlik 2c1c983
+            m.update(b'abc\n')
Matej Stuchlik 2c1c983
+            self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
Matej Stuchlik 2c1c983
+       
Matej Stuchlik 2c1c983
+            m = _hashlib.openssl_md5(b'abc\n', usedforsecurity=False)
Matej Stuchlik 2c1c983
+            self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
Matej Stuchlik 2c1c983
+        
Matej Stuchlik 2c1c983
+            m = _hashlib.new('md5', b'abc\n', usedforsecurity=False)
Matej Stuchlik 2c1c983
+            self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
 class KDFTests(unittest.TestCase):
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
@@ -639,6 +707,7 @@
Matej Stuchlik 2c1c983
         with self.assertRaisesRegex(ValueError, 'unsupported hash type'):
Matej Stuchlik 2c1c983
             pbkdf2('unknown', b'pass', b'salt', 1)
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
+    @unittest.skip('skipped on Fedora, as we always use OpenSSL pbkdf2_hmac')
Matej Stuchlik 2c1c983
     def test_pbkdf2_hmac_py(self):
Matej Stuchlik 2c1c983
         self._test_pbkdf2_hmac(py_hashlib.pbkdf2_hmac)
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
--- Python-3.4.0b1/Modules/_hashopenssl.c.hashlib-fips	2013-11-24 21:36:56.000000000 +0100
Matej Stuchlik 2c1c983
+++ Python-3.4.0b1/Modules/_hashopenssl.c	2013-11-27 12:01:57.443537463 +0100
Matej Stuchlik 2c1c983
@@ -19,6 +19,8 @@
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
 /* EVP is the preferred interface to hashing in OpenSSL */
Matej Stuchlik 2c1c983
+#include <openssl/ssl.h>
Matej Stuchlik 2c1c983
+#include <openssl/err.h>
Matej Stuchlik 2c1c983
 #include <openssl/evp.h>
Matej Stuchlik 2c1c983
 #include <openssl/hmac.h>
Matej Stuchlik 2c1c983
 /* We use the object interface to discover what hashes OpenSSL supports. */
Matej Stuchlik 2c1c983
@@ -48,11 +50,19 @@
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
 static PyTypeObject EVPtype;
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
+/* Struct to hold all the cached information we need on a specific algorithm.
Matej Stuchlik 2c1c983
+   We have one of these per algorithm */
Matej Stuchlik 2c1c983
+typedef struct {
Matej Stuchlik 2c1c983
+    PyObject *name_obj;
Matej Stuchlik 2c1c983
+    EVP_MD_CTX ctxs[2];
Matej Stuchlik 2c1c983
+    /* ctx_ptrs will point to ctxs unless an error occurred, when it will
Matej Stuchlik 2c1c983
+       be NULL: */
Matej Stuchlik 2c1c983
+    EVP_MD_CTX *ctx_ptrs[2];
Matej Stuchlik 2c1c983
+    PyObject *error_msgs[2];
Matej Stuchlik 2c1c983
+} EVPCachedInfo;
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
-#define DEFINE_CONSTS_FOR_NEW(Name)  \
Matej Stuchlik 2c1c983
-    static PyObject *CONST_ ## Name ## _name_obj = NULL; \
Matej Stuchlik 2c1c983
-    static EVP_MD_CTX CONST_new_ ## Name ## _ctx; \
Matej Stuchlik 2c1c983
-    static EVP_MD_CTX *CONST_new_ ## Name ## _ctx_p = NULL;
Matej Stuchlik 2c1c983
+#define DEFINE_CONSTS_FOR_NEW(Name) \
Matej Stuchlik 2c1c983
+    static EVPCachedInfo cached_info_ ##Name;
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
 DEFINE_CONSTS_FOR_NEW(md5)
Matej Stuchlik 2c1c983
 DEFINE_CONSTS_FOR_NEW(sha1)
Matej Stuchlik 2c1c983
@@ -97,6 +107,48 @@
Matej Stuchlik 2c1c983
     }
Matej Stuchlik 2c1c983
 }
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
+static void
Matej Stuchlik 2c1c983
+mc_ctx_init(EVP_MD_CTX *ctx, int usedforsecurity)
Matej Stuchlik 2c1c983
+{
Matej Stuchlik 2c1c983
+    EVP_MD_CTX_init(ctx);
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+    /*
Matej Stuchlik 2c1c983
+      If the user has declared that this digest is being used in a
Matej Stuchlik 2c1c983
+      non-security role (e.g. indexing into a data structure), set
Matej Stuchlik 2c1c983
+      the exception flag for openssl to allow it
Matej Stuchlik 2c1c983
+    */
Matej Stuchlik 2c1c983
+    if (!usedforsecurity) {
Matej Stuchlik 2c1c983
+#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
Matej Stuchlik 2c1c983
+        EVP_MD_CTX_set_flags(ctx,
Matej Stuchlik 2c1c983
+                             EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
Matej Stuchlik 2c1c983
+#endif
Matej Stuchlik 2c1c983
+    }
Matej Stuchlik 2c1c983
+}
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+/* Get an error msg for the last error as a PyObject */
Matej Stuchlik 2c1c983
+static PyObject *
Matej Stuchlik 2c1c983
+error_msg_for_last_error(void)
Matej Stuchlik 2c1c983
+{
Matej Stuchlik 2c1c983
+    char *errstr;
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+    errstr = ERR_error_string(ERR_peek_last_error(), NULL);
Matej Stuchlik 2c1c983
+    ERR_clear_error();
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+    return PyUnicode_FromString(errstr); /* Can be NULL */
Matej Stuchlik 2c1c983
+}
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+static void
Matej Stuchlik 2c1c983
+set_evp_exception(void)
Matej Stuchlik 2c1c983
+{
Matej Stuchlik 2c1c983
+    char *errstr;
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+    errstr = ERR_error_string(ERR_peek_last_error(), NULL);
Matej Stuchlik 2c1c983
+    ERR_clear_error();
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+    PyErr_SetString(PyExc_ValueError, errstr);
Matej Stuchlik 2c1c983
+}
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
 /* Internal methods for a hash object */
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
 static void
Matej Stuchlik 2c1c983
@@ -281,15 +333,16 @@
Matej Stuchlik 2c1c983
 static int
Matej Stuchlik 2c1c983
 EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
Matej Stuchlik 2c1c983
 {
Matej Stuchlik 2c1c983
-    static char *kwlist[] = {"name", "string", NULL};
Matej Stuchlik 2c1c983
+    static char *kwlist[] = {"name", "string", "usedforsecurity", NULL};
Matej Stuchlik 2c1c983
     PyObject *name_obj = NULL;
Matej Stuchlik 2c1c983
     PyObject *data_obj = NULL;
Matej Stuchlik 2c1c983
+    int usedforsecurity = 1;
Matej Stuchlik 2c1c983
     Py_buffer view;
Matej Stuchlik 2c1c983
     char *nameStr;
Matej Stuchlik 2c1c983
     const EVP_MD *digest;
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:HASH", kwlist,
Matej Stuchlik 2c1c983
-                                     &name_obj, &data_obj)) {
Matej Stuchlik 2c1c983
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oi:HASH", kwlist,
Matej Stuchlik 2c1c983
+                                     &name_obj, &data_obj, &usedforsecurity)) {
Matej Stuchlik 2c1c983
         return -1;
Matej Stuchlik 2c1c983
     }
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
@@ -310,7 +363,12 @@
Matej Stuchlik 2c1c983
             PyBuffer_Release(&view);
Matej Stuchlik 2c1c983
         return -1;
Matej Stuchlik 2c1c983
     }
Matej Stuchlik 2c1c983
-    EVP_DigestInit(&self->ctx, digest);
Matej Stuchlik 2c1c983
+    mc_ctx_init(&self->ctx, usedforsecurity);
Matej Stuchlik 2c1c983
+    if (!EVP_DigestInit_ex(&self->ctx, digest, NULL)) {
Matej Stuchlik 2c1c983
+        set_evp_exception();
Matej Stuchlik 2c1c983
+        PyBuffer_Release(&view);
Matej Stuchlik 2c1c983
+        return -1;
Matej Stuchlik 2c1c983
+    }
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
     self->name = name_obj;
Matej Stuchlik 2c1c983
     Py_INCREF(self->name);
Matej Stuchlik 2c1c983
@@ -394,7 +452,8 @@
Matej Stuchlik 2c1c983
 static PyObject *
Matej Stuchlik 2c1c983
 EVPnew(PyObject *name_obj,
Matej Stuchlik 2c1c983
        const EVP_MD *digest, const EVP_MD_CTX *initial_ctx,
Matej Stuchlik 2c1c983
-       const unsigned char *cp, Py_ssize_t len)
Matej Stuchlik 2c1c983
+       const unsigned char *cp, Py_ssize_t len,
Matej Stuchlik 2c1c983
+       int usedforsecurity)
Matej Stuchlik 2c1c983
 {
Matej Stuchlik 2c1c983
     EVPobject *self;
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
@@ -409,7 +468,12 @@
Matej Stuchlik 2c1c983
     if (initial_ctx) {
Matej Stuchlik 2c1c983
         EVP_MD_CTX_copy(&self->ctx, initial_ctx);
Matej Stuchlik 2c1c983
     } else {
Matej Stuchlik 2c1c983
-        EVP_DigestInit(&self->ctx, digest);
Matej Stuchlik 2c1c983
+        mc_ctx_init(&self->ctx, usedforsecurity);
Matej Stuchlik 2c1c983
+        if (!EVP_DigestInit_ex(&self->ctx, digest, NULL)) {
Matej Stuchlik 2c1c983
+            set_evp_exception();
Matej Stuchlik 2c1c983
+            Py_DECREF(self);
Matej Stuchlik 2c1c983
+            return NULL;
Matej Stuchlik 2c1c983
+        }
Matej Stuchlik 2c1c983
     }
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
     if (cp && len) {
Matej Stuchlik 2c1c983
@@ -433,21 +497,29 @@
Matej Stuchlik 2c1c983
 An optional string argument may be provided and will be\n\
Matej Stuchlik 2c1c983
 automatically hashed.\n\
Matej Stuchlik 2c1c983
 \n\
Matej Stuchlik 2c1c983
-The MD5 and SHA1 algorithms are always supported.\n");
Matej Stuchlik 2c1c983
+The MD5 and SHA1 algorithms are always supported.\n\
Matej Stuchlik 2c1c983
+\n\
Matej Stuchlik 2c1c983
+An optional \"usedforsecurity=True\" keyword argument is provided for use in\n\
Matej Stuchlik 2c1c983
+environments that enforce FIPS-based restrictions.  Some implementations of\n\
Matej Stuchlik 2c1c983
+OpenSSL can be configured to prevent the usage of non-secure algorithms (such\n\
Matej Stuchlik 2c1c983
+as MD5).  If you have a non-security use for these algorithms (e.g. a hash\n\
Matej Stuchlik 2c1c983
+table), you can override this argument by marking the callsite as\n\
Matej Stuchlik 2c1c983
+\"usedforsecurity=False\".");
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
 static PyObject *
Matej Stuchlik 2c1c983
 EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
Matej Stuchlik 2c1c983
 {
Matej Stuchlik 2c1c983
-    static char *kwlist[] = {"name", "string", NULL};
Matej Stuchlik 2c1c983
+    static char *kwlist[] = {"name", "string", "usedforsecurity", NULL};
Matej Stuchlik 2c1c983
     PyObject *name_obj = NULL;
Matej Stuchlik 2c1c983
     PyObject *data_obj = NULL;
Matej Stuchlik 2c1c983
+    int usedforsecurity = 1;
Matej Stuchlik 2c1c983
     Py_buffer view = { 0 };
Matej Stuchlik 2c1c983
     PyObject *ret_obj;
Matej Stuchlik 2c1c983
     char *name;
Matej Stuchlik 2c1c983
     const EVP_MD *digest;
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
-    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|O:new", kwlist,
Matej Stuchlik 2c1c983
-                                     &name_obj, &data_obj)) {
Matej Stuchlik 2c1c983
+    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|Oi:new", kwlist,
Matej Stuchlik 2c1c983
+                                     &name_obj, &data_obj, &usedforsecurity)) {
Matej Stuchlik 2c1c983
         return NULL;
Matej Stuchlik 2c1c983
     }
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
@@ -461,7 +533,8 @@
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
     digest = EVP_get_digestbyname(name);
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
-    ret_obj = EVPnew(name_obj, digest, NULL, (unsigned char*)view.buf, view.len);
Matej Stuchlik 2c1c983
+    ret_obj = EVPnew(name_obj, digest, NULL, (unsigned char*)view.buf, view.len,
Matej Stuchlik 2c1c983
+                     usedforsecurity);
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
     if (data_obj)
Matej Stuchlik 2c1c983
         PyBuffer_Release(&view);
Matej Stuchlik 2c1c983
@@ -742,57 +815,115 @@
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
 /*
Matej Stuchlik 2c1c983
- *  This macro generates constructor function definitions for specific
Matej Stuchlik 2c1c983
- *  hash algorithms.  These constructors are much faster than calling
Matej Stuchlik 2c1c983
- *  the generic one passing it a python string and are noticably
Matej Stuchlik 2c1c983
- *  faster than calling a python new() wrapper.  Thats important for
Matej Stuchlik 2c1c983
+ *  This macro and function generates a family of constructor function
Matej Stuchlik 2c1c983
+ *  definitions for specific hash algorithms.  These constructors are much
Matej Stuchlik 2c1c983
+ *  faster than calling the generic one passing it a python string and are
Matej Stuchlik 2c1c983
+ *  noticably faster than calling a python new() wrapper.  That's important for
Matej Stuchlik 2c1c983
  *  code that wants to make hashes of a bunch of small strings.
Matej Stuchlik 2c1c983
  */
Matej Stuchlik 2c1c983
 #define GEN_CONSTRUCTOR(NAME)  \
Matej Stuchlik 2c1c983
     static PyObject * \
Matej Stuchlik 2c1c983
-    EVP_new_ ## NAME (PyObject *self, PyObject *args) \
Matej Stuchlik 2c1c983
+    EVP_new_ ## NAME (PyObject *self, PyObject *args, PyObject *kwdict)        \
Matej Stuchlik 2c1c983
     { \
Matej Stuchlik 2c1c983
-        PyObject *data_obj = NULL; \
Matej Stuchlik 2c1c983
-        Py_buffer view = { 0 }; \
Matej Stuchlik 2c1c983
-        PyObject *ret_obj; \
Matej Stuchlik 2c1c983
-     \
Matej Stuchlik 2c1c983
-        if (!PyArg_ParseTuple(args, "|O:" #NAME , &data_obj)) { \
Matej Stuchlik 2c1c983
-            return NULL; \
Matej Stuchlik 2c1c983
-        } \
Matej Stuchlik 2c1c983
-     \
Matej Stuchlik 2c1c983
-        if (data_obj) \
Matej Stuchlik 2c1c983
-            GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view); \
Matej Stuchlik 2c1c983
-     \
Matej Stuchlik 2c1c983
-        ret_obj = EVPnew( \
Matej Stuchlik 2c1c983
-                    CONST_ ## NAME ## _name_obj, \
Matej Stuchlik 2c1c983
-                    NULL, \
Matej Stuchlik 2c1c983
-                    CONST_new_ ## NAME ## _ctx_p, \
Matej Stuchlik 2c1c983
-                    (unsigned char*)view.buf, \
Matej Stuchlik 2c1c983
-                    view.len); \
Matej Stuchlik 2c1c983
-     \
Matej Stuchlik 2c1c983
-        if (data_obj) \
Matej Stuchlik 2c1c983
-            PyBuffer_Release(&view); \
Matej Stuchlik 2c1c983
-        return ret_obj; \
Matej Stuchlik 2c1c983
+       return implement_specific_EVP_new(self, args, kwdict,      \
Matej Stuchlik 2c1c983
+                                         "|Oi:" #NAME,            \
Matej Stuchlik 2c1c983
+                                         &cached_info_ ## NAME ); \
Matej Stuchlik 2c1c983
+    }
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+static PyObject *
Matej Stuchlik 2c1c983
+implement_specific_EVP_new(PyObject *self, PyObject *args, PyObject *kwdict,
Matej Stuchlik 2c1c983
+                           const char *format,
Matej Stuchlik 2c1c983
+                           EVPCachedInfo *cached_info)
Matej Stuchlik 2c1c983
+{
Matej Stuchlik 2c1c983
+    static char *kwlist[] = {"string", "usedforsecurity", NULL}; 
Matej Stuchlik 2c1c983
+    PyObject *data_obj = NULL;
Matej Stuchlik 2c1c983
+    Py_buffer view = { 0 };
Matej Stuchlik 2c1c983
+    int usedforsecurity = 1;
Matej Stuchlik 2c1c983
+    int idx;
Matej Stuchlik 2c1c983
+    PyObject *ret_obj = NULL;
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+    assert(cached_info);
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+    if (!PyArg_ParseTupleAndKeywords(args, kwdict, format, kwlist,
Matej Stuchlik 2c1c983
+                                     &data_obj, &usedforsecurity)) {
Matej Stuchlik 2c1c983
+        return NULL;
Matej Stuchlik 2c1c983
+    }
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+    if (data_obj)
Matej Stuchlik 2c1c983
+       GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view);
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+    idx = usedforsecurity ? 1 : 0;
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+    /*
Matej Stuchlik 2c1c983
+     * If an error occurred during creation of the global content, the ctx_ptr
Matej Stuchlik 2c1c983
+     * will be NULL, and the error_msg will hopefully be non-NULL:
Matej Stuchlik 2c1c983
+     */
Matej Stuchlik 2c1c983
+    if (cached_info->ctx_ptrs[idx]) {
Matej Stuchlik 2c1c983
+        /* We successfully initialized this context; copy it: */
Matej Stuchlik 2c1c983
+        ret_obj = EVPnew(cached_info->name_obj,
Matej Stuchlik 2c1c983
+                         NULL,
Matej Stuchlik 2c1c983
+                         cached_info->ctx_ptrs[idx],
Matej Stuchlik 2c1c983
+                         (unsigned char*)view.buf, view.len,
Matej Stuchlik 2c1c983
+                         usedforsecurity);
Matej Stuchlik 2c1c983
+    } else {
Matej Stuchlik 2c1c983
+        /* Some kind of error happened initializing the global context for
Matej Stuchlik 2c1c983
+           this (digest, usedforsecurity) pair.
Matej Stuchlik 2c1c983
+           Raise an exception with the saved error message: */
Matej Stuchlik 2c1c983
+        if (cached_info->error_msgs[idx]) {
Matej Stuchlik 2c1c983
+            PyErr_SetObject(PyExc_ValueError, cached_info->error_msgs[idx]);
Matej Stuchlik 2c1c983
+        } else {
Matej Stuchlik 2c1c983
+            PyErr_SetString(PyExc_ValueError, "Error initializing hash");
Matej Stuchlik 2c1c983
+        }
Matej Stuchlik 2c1c983
     }
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
+    if (data_obj)
Matej Stuchlik 2c1c983
+        PyBuffer_Release(&view);
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+    return ret_obj;
Matej Stuchlik 2c1c983
+}
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
 /* a PyMethodDef structure for the constructor */
Matej Stuchlik 2c1c983
 #define CONSTRUCTOR_METH_DEF(NAME)  \
Matej Stuchlik 2c1c983
-    {"openssl_" #NAME, (PyCFunction)EVP_new_ ## NAME, METH_VARARGS, \
Matej Stuchlik 2c1c983
+    {"openssl_" #NAME, (PyCFunction)EVP_new_ ## NAME, \
Matej Stuchlik 2c1c983
+        METH_VARARGS|METH_KEYWORDS, \
Matej Stuchlik 2c1c983
         PyDoc_STR("Returns a " #NAME \
Matej Stuchlik 2c1c983
                   " hash object; optionally initialized with a string") \
Matej Stuchlik 2c1c983
     }
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
-/* used in the init function to setup a constructor: initialize OpenSSL
Matej Stuchlik 2c1c983
-   constructor constants if they haven't been initialized already.  */
Matej Stuchlik 2c1c983
-#define INIT_CONSTRUCTOR_CONSTANTS(NAME)  do { \
Matej Stuchlik 2c1c983
-    if (CONST_ ## NAME ## _name_obj == NULL) { \
Matej Stuchlik 2c1c983
-        CONST_ ## NAME ## _name_obj = PyUnicode_FromString(#NAME); \
Matej Stuchlik 2c1c983
-        if (EVP_get_digestbyname(#NAME)) { \
Matej Stuchlik 2c1c983
-            CONST_new_ ## NAME ## _ctx_p = &CONST_new_ ## NAME ## _ctx; \
Matej Stuchlik 2c1c983
-            EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \
Matej Stuchlik 2c1c983
-        } \
Matej Stuchlik 2c1c983
-    } \
Matej Stuchlik 2c1c983
+/*
Matej Stuchlik 2c1c983
+  Macro/function pair to set up the constructors.
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
+  Try to initialize a context for each hash twice, once with
Matej Stuchlik 2c1c983
+  EVP_MD_CTX_FLAG_NON_FIPS_ALLOW and once without.
Matej Stuchlik 2c1c983
+  
Matej Stuchlik 2c1c983
+  Any that have errors during initialization will end up with a NULL ctx_ptrs
Matej Stuchlik 2c1c983
+  entry, and err_msgs will be set (unless we're very low on memory)
Matej Stuchlik 2c1c983
+*/
Matej Stuchlik 2c1c983
+#define INIT_CONSTRUCTOR_CONSTANTS(NAME)  do {    \
Matej Stuchlik 2c1c983
+    init_constructor_constant(&cached_info_ ## NAME, #NAME); \
Matej Stuchlik 2c1c983
 } while (0);
Matej Stuchlik 2c1c983
+static void
Matej Stuchlik 2c1c983
+init_constructor_constant(EVPCachedInfo *cached_info, const char *name)
Matej Stuchlik 2c1c983
+{
Matej Stuchlik 2c1c983
+    assert(cached_info);
Matej Stuchlik 2c1c983
+    cached_info->name_obj = PyUnicode_FromString(name);
Matej Stuchlik 2c1c983
+    if (EVP_get_digestbyname(name)) {
Matej Stuchlik 2c1c983
+        int i;
Matej Stuchlik 2c1c983
+        for (i=0; i<2; i++) {
Matej Stuchlik 2c1c983
+            mc_ctx_init(&cached_info->ctxs[i], i);
Matej Stuchlik 2c1c983
+            if (EVP_DigestInit_ex(&cached_info->ctxs[i],
Matej Stuchlik 2c1c983
+                                  EVP_get_digestbyname(name), NULL)) {
Matej Stuchlik 2c1c983
+                /* Success: */
Matej Stuchlik 2c1c983
+                cached_info->ctx_ptrs[i] = &cached_info->ctxs[i];
Matej Stuchlik 2c1c983
+            } else {
Matej Stuchlik 2c1c983
+                /* Failure: */
Matej Stuchlik 2c1c983
+              cached_info->ctx_ptrs[i] = NULL;
Matej Stuchlik 2c1c983
+              cached_info->error_msgs[i] = error_msg_for_last_error();
Matej Stuchlik 2c1c983
+            }
Matej Stuchlik 2c1c983
+        }
Matej Stuchlik 2c1c983
+    }
Matej Stuchlik 2c1c983
+}
Matej Stuchlik 2c1c983
+
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
 GEN_CONSTRUCTOR(md5)
Matej Stuchlik 2c1c983
 GEN_CONSTRUCTOR(sha1)
Matej Stuchlik 2c1c983
@@ -843,13 +974,10 @@
Matej Stuchlik 2c1c983
 {
Matej Stuchlik 2c1c983
     PyObject *m, *openssl_md_meth_names;
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
-    OpenSSL_add_all_digests();
Matej Stuchlik 2c1c983
-    ERR_load_crypto_strings();
Matej Stuchlik 2c1c983
+    SSL_load_error_strings();
Matej Stuchlik 2c1c983
+    SSL_library_init();
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
-    /* TODO build EVP_functions openssl_* entries dynamically based
Matej Stuchlik 2c1c983
-     * on what hashes are supported rather than listing many
Matej Stuchlik 2c1c983
-     * but having some be unsupported.  Only init appropriate
Matej Stuchlik 2c1c983
-     * constants. */
Matej Stuchlik 2c1c983
+    OpenSSL_add_all_digests();
Matej Stuchlik 2c1c983
 
Matej Stuchlik 2c1c983
     Py_TYPE(&EVPtype) = &PyType_Type;
Matej Stuchlik 2c1c983
     if (PyType_Ready(&EVPtype) < 0)