Rebase the hashlib patch + adapt it to _sha3 being used from stdlib

This commit is contained in:
Bohuslav Kabrda 2013-11-07 15:59:40 +01:00
parent 0153564bb6
commit f0b0ffc86c
2 changed files with 102 additions and 97 deletions

View File

@ -1,7 +1,6 @@
diff -up Python-3.2.2/Lib/hashlib.py.hashlib-fips Python-3.2.2/Lib/hashlib.py --- Python-3.4.0a4/Lib/hashlib.py.hashlib-fips 2013-11-07 13:29:43.046881440 +0100
--- Python-3.2.2/Lib/hashlib.py.hashlib-fips 2011-09-03 12:16:41.000000000 -0400 +++ Python-3.4.0a4/Lib/hashlib.py 2013-11-07 13:42:04.438486289 +0100
+++ Python-3.2.2/Lib/hashlib.py 2011-09-14 01:55:48.090252006 -0400 @@ -23,6 +23,16 @@
@@ -23,6 +23,16 @@ the zlib module.
Choose your hash function wisely. Some have known collision weaknesses. Choose your hash function wisely. Some have known collision weaknesses.
sha384 and sha512 will be slow on 32 bit platforms. sha384 and sha512 will be slow on 32 bit platforms.
@ -18,7 +17,27 @@ diff -up Python-3.2.2/Lib/hashlib.py.hashlib-fips Python-3.2.2/Lib/hashlib.py
Hash objects have these methods: Hash objects have these methods:
- update(arg): Update the hash object with the bytes in arg. Repeated calls - update(arg): Update the hash object with the bytes in arg. Repeated calls
are equivalent to a single call with the concatenation of all are equivalent to a single call with the concatenation of all
@@ -96,33 +106,36 @@ def __get_openssl_constructor(name): @@ -64,6 +74,19 @@
'algorithms_available', 'pbkdf2_hmac')
+import functools
+def __ignore_usedforsecurity(func):
+ """Used for sha3_* functions. Until OpenSSL implements them, we want
+ to use them from Python _sha3 module, but we want them to accept
+ usedforsecurity argument too."""
+ # TODO: remove this function when OpenSSL implements sha3
+ @functools.wraps(func)
+ def inner(*args, **kwargs):
+ if 'usedforsecurity' in kwargs:
+ kwargs.pop('usedforsecurity')
+ return func(*args, **kwargs)
+ return inner
+
def __get_builtin_constructor(name):
try:
if name in ('SHA1', 'sha1'):
@@ -109,34 +132,41 @@
f = getattr(_hashlib, 'openssl_' + name) f = getattr(_hashlib, 'openssl_' + name)
# Allow the C module to raise ValueError. The function will be # Allow the C module to raise ValueError. The function will be
# defined but the hash not actually available thanks to OpenSSL. # defined but the hash not actually available thanks to OpenSSL.
@ -30,16 +49,17 @@ diff -up Python-3.2.2/Lib/hashlib.py.hashlib-fips Python-3.2.2/Lib/hashlib.py
# Use the C function directly (very fast) # Use the C function directly (very fast)
return f return f
except (AttributeError, ValueError): except (AttributeError, ValueError):
- return __get_builtin_constructor(name) + # TODO: We want to just raise here when OpenSSL implements sha3
+ raise + # because we want to make sure that Fedora uses everything from OpenSSL
return __get_builtin_constructor(name)
+def __py_new(name, data=b'', usedforsecurity=True):
+ """new(name, data=b'', usedforsecurity=True) - Return a new hashing object using
+ the named algorithm; optionally initialized with data (which must be bytes).
-def __py_new(name, data=b''): -def __py_new(name, data=b''):
- """new(name, data=b'') - Return a new hashing object using the named algorithm; - """new(name, data=b'') - Return a new hashing object using the named algorithm;
- optionally initialized with data (which must be bytes). - optionally initialized with data (which must be bytes).
+def __py_new(name, data=b'', usedforsecurity=True):
+ """new(name, data=b'', usedforsecurity=True) - Return a new hashing object using
+ the named algorithm; optionally initialized with data (which must be bytes).
+ The 'usedforsecurity' keyword argument does nothing, and is for compatibilty + The 'usedforsecurity' keyword argument does nothing, and is for compatibilty
+ with the OpenSSL implementation + with the OpenSSL implementation
""" """
@ -64,16 +84,34 @@ diff -up Python-3.2.2/Lib/hashlib.py.hashlib-fips Python-3.2.2/Lib/hashlib.py
- # hash, try using our builtin implementations. - # hash, try using our builtin implementations.
- # This allows for SHA224/256 and SHA384/512 support even though - # This allows for SHA224/256 and SHA384/512 support even though
- # the OpenSSL library prior to 0.9.8 doesn't provide them. - # the OpenSSL library prior to 0.9.8 doesn't provide them.
- return __get_builtin_constructor(name)(data) + # TODO: We want to just raise here when OpenSSL implements sha3
- + # because we want to make sure that Fedora uses everything from OpenSSL
+ raise return __get_builtin_constructor(name)(data)
-
try: try:
import _hashlib import _hashlib
diff -up Python-3.2.2/Lib/test/test_hashlib.py.hashlib-fips Python-3.2.2/Lib/test/test_hashlib.py new = __hash_new
--- Python-3.2.2/Lib/test/test_hashlib.py.hashlib-fips 2011-09-03 12:16:43.000000000 -0400 @@ -216,7 +246,10 @@
+++ Python-3.2.2/Lib/test/test_hashlib.py 2011-09-14 01:45:48.462251974 -0400 # try them all, some may not work due to the OpenSSL
@@ -22,6 +22,20 @@ from test.support import _4G, precisionb # version not supporting that algorithm.
try:
- globals()[__func_name] = __get_hash(__func_name)
+ func = __get_hash(__func_name)
+ if 'sha3_' in __func_name:
+ func = __ignore_usedforsecurity(func)
+ globals()[__func_name] = func
except ValueError:
import logging
logging.exception('code for hash %s was not found.', __func_name)
@@ -224,3 +257,4 @@
# Cleanup locals()
del __always_supported, __func_name, __get_hash
del __py_new, __hash_new, __get_openssl_constructor
+del __ignore_usedforsecurity
--- Python-3.4.0a4/Lib/test/test_hashlib.py.hashlib-fips 2013-11-07 13:43:08.763454594 +0100
+++ Python-3.4.0a4/Lib/test/test_hashlib.py 2013-11-07 13:55:23.233038101 +0100
@@ -26,6 +26,20 @@
c_hashlib = import_fresh_module('hashlib', fresh=['_hashlib']) c_hashlib = import_fresh_module('hashlib', fresh=['_hashlib'])
py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib']) py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib'])
@ -94,7 +132,7 @@ diff -up Python-3.2.2/Lib/test/test_hashlib.py.hashlib-fips Python-3.2.2/Lib/tes
def hexstr(s): def hexstr(s):
assert isinstance(s, bytes), repr(s) assert isinstance(s, bytes), repr(s)
h = "0123456789abcdef" h = "0123456789abcdef"
@@ -31,6 +44,16 @@ def hexstr(s): @@ -34,6 +48,16 @@
r += h[(i >> 4) & 0xF] + h[i & 0xF] r += h[(i >> 4) & 0xF] + h[i & 0xF]
return r return r
@ -111,7 +149,7 @@ diff -up Python-3.2.2/Lib/test/test_hashlib.py.hashlib-fips Python-3.2.2/Lib/tes
class HashLibTestCase(unittest.TestCase): class HashLibTestCase(unittest.TestCase):
supported_hash_names = ( 'md5', 'MD5', 'sha1', 'SHA1', supported_hash_names = ( 'md5', 'MD5', 'sha1', 'SHA1',
@@ -59,11 +82,11 @@ class HashLibTestCase(unittest.TestCase) @@ -66,11 +90,11 @@
# For each algorithm, test the direct constructor and the use # For each algorithm, test the direct constructor and the use
# of hashlib.new given the algorithm name. # of hashlib.new given the algorithm name.
for algorithm, constructors in self.constructors_to_test.items(): for algorithm, constructors in self.constructors_to_test.items():
@ -126,12 +164,13 @@ diff -up Python-3.2.2/Lib/test/test_hashlib.py.hashlib-fips Python-3.2.2/Lib/tes
constructors.add(_test_algorithm_via_hashlib_new) constructors.add(_test_algorithm_via_hashlib_new)
_hashlib = self._conditional_import_module('_hashlib') _hashlib = self._conditional_import_module('_hashlib')
@@ -75,22 +98,7 @@ class HashLibTestCase(unittest.TestCase) @@ -82,22 +106,9 @@
for algorithm, constructors in self.constructors_to_test.items(): for algorithm, constructors in self.constructors_to_test.items():
constructor = getattr(_hashlib, 'openssl_'+algorithm, None) constructor = getattr(_hashlib, 'openssl_'+algorithm, None)
if constructor: if constructor:
- constructors.add(constructor) - constructors.add(constructor)
- + constructors.add(suppress_fips(constructor))
- _md5 = self._conditional_import_module('_md5') - _md5 = self._conditional_import_module('_md5')
- if _md5: - if _md5:
- self.constructors_to_test['md5'].add(_md5.md5) - self.constructors_to_test['md5'].add(_md5.md5)
@ -146,51 +185,11 @@ diff -up Python-3.2.2/Lib/test/test_hashlib.py.hashlib-fips Python-3.2.2/Lib/tes
- if _sha512: - if _sha512:
- self.constructors_to_test['sha384'].add(_sha512.sha384) - self.constructors_to_test['sha384'].add(_sha512.sha384)
- self.constructors_to_test['sha512'].add(_sha512.sha512) - self.constructors_to_test['sha512'].add(_sha512.sha512)
+ constructors.add(suppress_fips(constructor)) + # TODO: remove this after sha3 is available through OpenSSL
_sha3 = self._conditional_import_module('_sha3') _sha3 = self._conditional_import_module('_sha3')
if _sha3: if _sha3:
self.constructors_to_test['sha3_224'].add(_sha3.sha3_224) self.constructors_to_test['sha3_224'].add(_sha3.sha3_224)
@@ -138,7 +146,7 @@ class HashLibTestCase(unittest.TestCase) @@ -547,6 +558,65 @@
def test_hexdigest(self):
for cons in self.hash_constructors:
- h = cons()
+ h = cons(usedforsecurity=False)
assert isinstance(h.digest(), bytes), name
self.assertEqual(hexstr(h.digest()), h.hexdigest())
@@ -149,12 +157,12 @@ class HashLibTestCase(unittest.TestCase)
cees = b'c' * 126
for name in self.supported_hash_names:
- m1 = cons()
+ m1 = cons(usedforsecurity=False)
m1.update(aas)
m1.update(bees)
m1.update(cees)
- m2 = cons()
+ m2 = cons(usedforsecurity=False)
m2.update(aas + bees + cees)
self.assertEqual(m1.digest(), m2.digest())
@@ -324,13 +332,13 @@ class HashLibTestCase(unittest.TestCase)
# for multithreaded operation (which is hardwired to 2048).
gil_minsize = 2048
- m = hashlib.md5()
+ m = hashlib.md5(usedforsecurity=False)
m.update(b'1')
m.update(b'#' * gil_minsize)
m.update(b'1')
self.assertEqual(m.hexdigest(), 'cb1e1a2cbc80be75e19935d621fb9b21')
- m = hashlib.md5(b'x' * gil_minsize)
+ m = hashlib.md5(b'x' * gil_minsize, usedforsecurity=False)
self.assertEqual(m.hexdigest(), 'cfb767f225d58469c5de3632a8803958')
@unittest.skipUnless(threading, 'Threading required for this test.')
@@ -370,6 +378,67 @@ class HashLibTestCase(unittest.TestCase)
self.assertEqual(expected_hash, hasher.hexdigest()) self.assertEqual(expected_hash, hasher.hexdigest())
@ -246,31 +245,36 @@ diff -up Python-3.2.2/Lib/test/test_hashlib.py.hashlib-fips Python-3.2.2/Lib/tes
+ m = _hashlib.new('md5', usedforsecurity=False) + m = _hashlib.new('md5', usedforsecurity=False)
+ m.update(b'abc\n') + m.update(b'abc\n')
+ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1") + self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
+ +
+ m = _hashlib.openssl_md5(b'abc\n', usedforsecurity=False) + m = _hashlib.openssl_md5(b'abc\n', usedforsecurity=False)
+ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1") + self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
+ +
+ m = _hashlib.new('md5', b'abc\n', usedforsecurity=False) + m = _hashlib.new('md5', b'abc\n', usedforsecurity=False)
+ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1") + self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
+
+ +
+
def test_main():
support.run_unittest(HashLibTestCase)
diff -up Python-3.2.2/Modules/_hashopenssl.c.hashlib-fips Python-3.2.2/Modules/_hashopenssl.c class KDFTests(unittest.TestCase):
--- Python-3.2.2/Modules/_hashopenssl.c.hashlib-fips 2011-09-03 12:16:46.000000000 -0400
+++ Python-3.2.2/Modules/_hashopenssl.c 2011-09-14 00:52:41.225252001 -0400 @@ -628,6 +698,7 @@
@@ -37,6 +37,8 @@ with self.assertRaisesRegex(ValueError, 'unsupported hash type'):
#endif pbkdf2('unknown', b'pass', b'salt', 1)
+ @unittest.skip('skipped on Fedora, as we always use OpenSSL pbkdf2_hmac')
def test_pbkdf2_hmac_py(self):
self._test_pbkdf2_hmac(py_hashlib.pbkdf2_hmac)
--- Python-3.4.0a4/Modules/_hashopenssl.c.hashlib-fips 2013-11-07 13:55:47.466025086 +0100
+++ Python-3.4.0a4/Modules/_hashopenssl.c 2013-11-07 14:14:32.745272791 +0100
@@ -19,6 +19,8 @@
/* EVP is the preferred interface to hashing in OpenSSL */ /* EVP is the preferred interface to hashing in OpenSSL */
+#include <openssl/ssl.h> +#include <openssl/ssl.h>
+#include <openssl/err.h> +#include <openssl/err.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/hmac.h>
/* We use the object interface to discover what hashes OpenSSL supports. */ /* We use the object interface to discover what hashes OpenSSL supports. */
#include <openssl/objects.h> @@ -48,11 +50,19 @@
@@ -68,11 +70,19 @@ typedef struct {
static PyTypeObject EVPtype; static PyTypeObject EVPtype;
@ -294,7 +298,7 @@ diff -up Python-3.2.2/Modules/_hashopenssl.c.hashlib-fips Python-3.2.2/Modules/_
DEFINE_CONSTS_FOR_NEW(md5) DEFINE_CONSTS_FOR_NEW(md5)
DEFINE_CONSTS_FOR_NEW(sha1) DEFINE_CONSTS_FOR_NEW(sha1)
@@ -117,6 +127,48 @@ EVP_hash(EVPobject *self, const void *vp @@ -125,6 +135,48 @@
} }
} }
@ -343,7 +347,7 @@ diff -up Python-3.2.2/Modules/_hashopenssl.c.hashlib-fips Python-3.2.2/Modules/_
/* Internal methods for a hash object */ /* Internal methods for a hash object */
static void static void
@@ -303,15 +355,16 @@ EVP_repr(EVPobject *self) @@ -309,15 +361,16 @@
static int static int
EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds) EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
{ {
@ -363,7 +367,7 @@ diff -up Python-3.2.2/Modules/_hashopenssl.c.hashlib-fips Python-3.2.2/Modules/_
return -1; return -1;
} }
@@ -332,7 +385,12 @@ EVP_tp_init(EVPobject *self, PyObject *a @@ -338,7 +391,12 @@
PyBuffer_Release(&view); PyBuffer_Release(&view);
return -1; return -1;
} }
@ -377,7 +381,7 @@ diff -up Python-3.2.2/Modules/_hashopenssl.c.hashlib-fips Python-3.2.2/Modules/_
self->name = name_obj; self->name = name_obj;
Py_INCREF(self->name); Py_INCREF(self->name);
@@ -416,7 +474,8 @@ static PyTypeObject EVPtype = { @@ -422,7 +480,8 @@
static PyObject * static PyObject *
EVPnew(PyObject *name_obj, EVPnew(PyObject *name_obj,
const EVP_MD *digest, const EVP_MD_CTX *initial_ctx, const EVP_MD *digest, const EVP_MD_CTX *initial_ctx,
@ -387,7 +391,7 @@ diff -up Python-3.2.2/Modules/_hashopenssl.c.hashlib-fips Python-3.2.2/Modules/_
{ {
EVPobject *self; EVPobject *self;
@@ -431,7 +490,12 @@ EVPnew(PyObject *name_obj, @@ -437,7 +495,12 @@
if (initial_ctx) { if (initial_ctx) {
EVP_MD_CTX_copy(&self->ctx, initial_ctx); EVP_MD_CTX_copy(&self->ctx, initial_ctx);
} else { } else {
@ -401,7 +405,7 @@ diff -up Python-3.2.2/Modules/_hashopenssl.c.hashlib-fips Python-3.2.2/Modules/_
} }
if (cp && len) { if (cp && len) {
@@ -455,21 +519,29 @@ PyDoc_STRVAR(EVP_new__doc__, @@ -461,21 +524,29 @@
An optional string argument may be provided and will be\n\ An optional string argument may be provided and will be\n\
automatically hashed.\n\ automatically hashed.\n\
\n\ \n\
@ -435,7 +439,7 @@ diff -up Python-3.2.2/Modules/_hashopenssl.c.hashlib-fips Python-3.2.2/Modules/_
return NULL; return NULL;
} }
@@ -483,7 +555,8 @@ EVP_new(PyObject *self, PyObject *args, @@ -489,7 +560,8 @@
digest = EVP_get_digestbyname(name); digest = EVP_get_digestbyname(name);
@ -445,7 +449,7 @@ diff -up Python-3.2.2/Modules/_hashopenssl.c.hashlib-fips Python-3.2.2/Modules/_
if (data_obj) if (data_obj)
PyBuffer_Release(&view); PyBuffer_Release(&view);
@@ -547,58 +620,115 @@ generate_hash_name_list(void) @@ -744,57 +816,115 @@
/* /*
@ -462,7 +466,7 @@ diff -up Python-3.2.2/Modules/_hashopenssl.c.hashlib-fips Python-3.2.2/Modules/_
#define GEN_CONSTRUCTOR(NAME) \ #define GEN_CONSTRUCTOR(NAME) \
static PyObject * \ static PyObject * \
- EVP_new_ ## NAME (PyObject *self, PyObject *args) \ - EVP_new_ ## NAME (PyObject *self, PyObject *args) \
+ EVP_new_ ## NAME (PyObject *self, PyObject *args, PyObject *kwdict) \ + EVP_new_ ## NAME (PyObject *self, PyObject *args, PyObject *kwdict) \
{ \ { \
- PyObject *data_obj = NULL; \ - PyObject *data_obj = NULL; \
- Py_buffer view = { 0 }; \ - Py_buffer view = { 0 }; \
@ -488,8 +492,8 @@ diff -up Python-3.2.2/Modules/_hashopenssl.c.hashlib-fips Python-3.2.2/Modules/_
+ return implement_specific_EVP_new(self, args, kwdict, \ + return implement_specific_EVP_new(self, args, kwdict, \
+ "|Oi:" #NAME, \ + "|Oi:" #NAME, \
+ &cached_info_ ## NAME ); \ + &cached_info_ ## NAME ); \
} + }
+
+static PyObject * +static PyObject *
+implement_specific_EVP_new(PyObject *self, PyObject *args, PyObject *kwdict, +implement_specific_EVP_new(PyObject *self, PyObject *args, PyObject *kwdict,
+ const char *format, + const char *format,
@ -534,8 +538,8 @@ diff -up Python-3.2.2/Modules/_hashopenssl.c.hashlib-fips Python-3.2.2/Modules/_
+ } else { + } else {
+ PyErr_SetString(PyExc_ValueError, "Error initializing hash"); + PyErr_SetString(PyExc_ValueError, "Error initializing hash");
+ } + }
+ } }
+
+ if (data_obj) + if (data_obj)
+ PyBuffer_Release(&view); + PyBuffer_Release(&view);
+ +
@ -561,10 +565,9 @@ diff -up Python-3.2.2/Modules/_hashopenssl.c.hashlib-fips Python-3.2.2/Modules/_
- EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \ - EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \
- } \ - } \
- } \ - } \
-} while (0);
+/* +/*
+ Macro/function pair to set up the constructors. + Macro/function pair to set up the constructors.
+
+ Try to initialize a context for each hash twice, once with + Try to initialize a context for each hash twice, once with
+ EVP_MD_CTX_FLAG_NON_FIPS_ALLOW and once without. + EVP_MD_CTX_FLAG_NON_FIPS_ALLOW and once without.
+ +
@ -573,7 +576,7 @@ diff -up Python-3.2.2/Modules/_hashopenssl.c.hashlib-fips Python-3.2.2/Modules/_
+*/ +*/
+#define INIT_CONSTRUCTOR_CONSTANTS(NAME) do { \ +#define INIT_CONSTRUCTOR_CONSTANTS(NAME) do { \
+ init_constructor_constant(&cached_info_ ## NAME, #NAME); \ + init_constructor_constant(&cached_info_ ## NAME, #NAME); \
+} while (0); } while (0);
+static void +static void
+init_constructor_constant(EVPCachedInfo *cached_info, const char *name) +init_constructor_constant(EVPCachedInfo *cached_info, const char *name)
+{ +{
@ -595,11 +598,11 @@ diff -up Python-3.2.2/Modules/_hashopenssl.c.hashlib-fips Python-3.2.2/Modules/_
+ } + }
+ } + }
+} +}
+ +
GEN_CONSTRUCTOR(md5) GEN_CONSTRUCTOR(md5)
GEN_CONSTRUCTOR(sha1) GEN_CONSTRUCTOR(sha1)
#ifdef _OPENSSL_SUPPORTS_SHA2 @@ -845,12 +974,10 @@
@@ -641,12 +774,10 @@ PyInit__hashlib(void)
{ {
PyObject *m, *openssl_md_meth_names; PyObject *m, *openssl_md_meth_names;

View File

@ -381,8 +381,10 @@ Patch143: 00143-tsc-on-ppc.patch
# - don't build the _md5 and _sha* modules; rely on the _hashlib implementation # - don't build the _md5 and _sha* modules; rely on the _hashlib implementation
# of hashlib # of hashlib
# (rhbz#563986) # (rhbz#563986)
# TODO: figure out how to update properly for sha3 # Note: for now we're using sha3 from Python tarball, not from OpenSSL, since
# Patch146: 00146-hashlib-fips.patch # OpenSSL didn't implement it yet. When OpenSSL implements it again,
# we will need to rm -rf Modules/_sha3 in prep and adapt the patch.
Patch146: 00146-hashlib-fips.patch
# 00147 # # 00147 #
# Add a sys._debugmallocstats() function # Add a sys._debugmallocstats() function
@ -841,7 +843,7 @@ done
%patch143 -p1 -b .tsc-on-ppc %patch143 -p1 -b .tsc-on-ppc
# 00144: not for python3 # 00144: not for python3
# 00145: not for python3 # 00145: not for python3
#patch146 -p1 %patch146 -p1
# 00147: upstream as of Python 3.3.0 # 00147: upstream as of Python 3.3.0
# 00148: upstream as of Python 3.2.3 # 00148: upstream as of Python 3.2.3
# 00149: upstream as of Python 3.2.3 # 00149: upstream as of Python 3.2.3