An interpreted, interactive, object-oriented programming language
CentOS Sources
2017-08-01 71084d584ff953f5463757ec6536406320560b4d
commit | author | age
6e8c2f 1 diff -up Python-2.7.2/Lib/hashlib.py.hashlib-fips Python-2.7.2/Lib/hashlib.py
CB 2 --- Python-2.7.2/Lib/hashlib.py.hashlib-fips    2011-06-11 11:46:24.000000000 -0400
3 +++ Python-2.7.2/Lib/hashlib.py    2011-09-14 00:21:26.194252001 -0400
4 @@ -6,9 +6,12 @@
5  
6  __doc__ = """hashlib module - A common interface to many hash functions.
7  
8 -new(name, string='') - returns a new hash object implementing the
9 -                       given hash function; initializing the hash
10 -                       using the given string data.
11 +new(name, string='', usedforsecurity=True)
12 +     - returns a new hash object implementing the given hash function;
13 +       initializing the hash using the given string data.
14 +
15 +       "usedforsecurity" is a non-standard extension for better supporting
16 +       FIPS-compliant environments (see below)
17  
18  Named constructor functions are also available, these are much faster
19  than using new():
20 @@ -24,6 +27,20 @@ the zlib module.
21  Choose your hash function wisely.  Some have known collision weaknesses.
22  sha384 and sha512 will be slow on 32 bit platforms.
23  
24 +Our implementation of hashlib uses OpenSSL.
25 +
26 +OpenSSL has a "FIPS mode", which, if enabled, may restrict the available hashes
27 +to only those that are compliant with FIPS regulations.  For example, it may
28 +deny the use of MD5, on the grounds that this is not secure for uses such as
29 +authentication, system integrity checking, or digital signatures.   
30 +
31 +If you need to use such a hash for non-security purposes (such as indexing into
32 +a data structure for speed), you can override the keyword argument
33 +"usedforsecurity" from True to False to signify that your code is not relying
34 +on the hash for security purposes, and this will allow the hash to be usable
35 +even in FIPS mode.  This is not a standard feature of Python 2.7's hashlib, and
36 +is included here to better support FIPS mode.
37 +
38  Hash objects have these methods:
39   - update(arg): Update the hash object with the string arg. Repeated calls
40                  are equivalent to a single call with the concatenation of all
41 @@ -63,74 +80,39 @@ algorithms = __always_supported
42  __all__ = __always_supported + ('new', 'algorithms')
43  
44  
45 -def __get_builtin_constructor(name):
46 -    try:
47 -        if name in ('SHA1', 'sha1'):
48 -            import _sha
49 -            return _sha.new
50 -        elif name in ('MD5', 'md5'):
51 -            import _md5
52 -            return _md5.new
53 -        elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'):
54 -            import _sha256
55 -            bs = name[3:]
56 -            if bs == '256':
57 -                return _sha256.sha256
58 -            elif bs == '224':
59 -                return _sha256.sha224
60 -        elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'):
61 -            import _sha512
62 -            bs = name[3:]
63 -            if bs == '512':
64 -                return _sha512.sha512
65 -            elif bs == '384':
66 -                return _sha512.sha384
67 -    except ImportError:
68 -        pass  # no extension module, this hash is unsupported.
69 -
70 -    raise ValueError('unsupported hash type ' + name)
71 -
72 -
73  def __get_openssl_constructor(name):
74      try:
75          f = getattr(_hashlib, 'openssl_' + name)
76          # Allow the C module to raise ValueError.  The function will be
77          # defined but the hash not actually available thanks to OpenSSL.
78 -        f()
79 +        #
80 +        # We pass "usedforsecurity=False" to disable FIPS-based restrictions:
81 +        # at this stage we're merely seeing if the function is callable,
82 +        # rather than using it for actual work.
83 +        f(usedforsecurity=False)
84          # Use the C function directly (very fast)
85          return f
86      except (AttributeError, ValueError):
87 -        return __get_builtin_constructor(name)
88 +        raise
89  
90 -
91 -def __py_new(name, string=''):
92 -    """new(name, string='') - Return a new hashing object using the named algorithm;
93 -    optionally initialized with a string.
94 -    """
95 -    return __get_builtin_constructor(name)(string)
96 -
97 -
98 -def __hash_new(name, string=''):
99 +def __hash_new(name, string='', usedforsecurity=True):
100      """new(name, string='') - Return a new hashing object using the named algorithm;
101      optionally initialized with a string.
102 +    Override 'usedforsecurity' to False when using for non-security purposes in
103 +    a FIPS environment
104      """
105      try:
106 -        return _hashlib.new(name, string)
107 +        return _hashlib.new(name, string, usedforsecurity)
108      except ValueError:
109 -        # If the _hashlib module (OpenSSL) doesn't support the named
110 -        # hash, try using our builtin implementations.
111 -        # This allows for SHA224/256 and SHA384/512 support even though
112 -        # the OpenSSL library prior to 0.9.8 doesn't provide them.
113 -        return __get_builtin_constructor(name)(string)
114 -
115 +        raise
116  
117  try:
118      import _hashlib
119      new = __hash_new
120      __get_hash = __get_openssl_constructor
121  except ImportError:
122 -    new = __py_new
123 -    __get_hash = __get_builtin_constructor
124 +    # We don't build the legacy modules
125 +    raise
126  
127  for __func_name in __always_supported:
128      # try them all, some may not work due to the OpenSSL
129 @@ -143,4 +125,4 @@ for __func_name in __always_supported:
130  
131  # Cleanup locals()
132  del __always_supported, __func_name, __get_hash
133 -del __py_new, __hash_new, __get_openssl_constructor
134 +del __hash_new, __get_openssl_constructor
135 diff -up Python-2.7.2/Lib/test/test_hashlib.py.hashlib-fips Python-2.7.2/Lib/test/test_hashlib.py
136 --- Python-2.7.2/Lib/test/test_hashlib.py.hashlib-fips    2011-06-11 11:46:25.000000000 -0400
137 +++ Python-2.7.2/Lib/test/test_hashlib.py    2011-09-14 01:08:55.525254195 -0400
138 @@ -32,6 +32,19 @@ def hexstr(s):
139          r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
140      return r
141  
142 +def openssl_enforces_fips():
143 +    # Use the "openssl" command (if present) to try to determine if the local
144 +    # OpenSSL is configured to enforce FIPS
145 +    from subprocess import Popen, PIPE
146 +    try:
147 +        p = Popen(['openssl', 'md5'],
148 +                  stdin=PIPE, stdout=PIPE, stderr=PIPE)
149 +    except OSError:
150 +        # "openssl" command not found
151 +        return False
152 +    stdout, stderr = p.communicate(input=b'abc')
153 +    return b'unknown cipher' in stderr
154 +OPENSSL_ENFORCES_FIPS = openssl_enforces_fips()
155  
156  class HashLibTestCase(unittest.TestCase):
157      supported_hash_names = ( 'md5', 'MD5', 'sha1', 'SHA1',
158 @@ -61,10 +74,10 @@ class HashLibTestCase(unittest.TestCase)
159          # of hashlib.new given the algorithm name.
160          for algorithm, constructors in self.constructors_to_test.items():
161              constructors.add(getattr(hashlib, algorithm))
162 -            def _test_algorithm_via_hashlib_new(data=None, _alg=algorithm):
163 +            def _test_algorithm_via_hashlib_new(data=None, _alg=algorithm, usedforsecurity=True):
164                  if data is None:
165 -                    return hashlib.new(_alg)
166 -                return hashlib.new(_alg, data)
167 +                    return hashlib.new(_alg, usedforsecurity=usedforsecurity)
168 +                return hashlib.new(_alg, data, usedforsecurity=usedforsecurity)
169              constructors.add(_test_algorithm_via_hashlib_new)
170  
171          _hashlib = self._conditional_import_module('_hashlib')
172 @@ -78,28 +91,13 @@ class HashLibTestCase(unittest.TestCase)
173                  if constructor:
174                      constructors.add(constructor)
175  
176 -        _md5 = self._conditional_import_module('_md5')
177 -        if _md5:
178 -            self.constructors_to_test['md5'].add(_md5.new)
179 -        _sha = self._conditional_import_module('_sha')
180 -        if _sha:
181 -            self.constructors_to_test['sha1'].add(_sha.new)
182 -        _sha256 = self._conditional_import_module('_sha256')
183 -        if _sha256:
184 -            self.constructors_to_test['sha224'].add(_sha256.sha224)
185 -            self.constructors_to_test['sha256'].add(_sha256.sha256)
186 -        _sha512 = self._conditional_import_module('_sha512')
187 -        if _sha512:
188 -            self.constructors_to_test['sha384'].add(_sha512.sha384)
189 -            self.constructors_to_test['sha512'].add(_sha512.sha512)
190 -
191          super(HashLibTestCase, self).__init__(*args, **kwargs)
192  
193      def test_hash_array(self):
194          a = array.array("b", range(10))
195          constructors = self.constructors_to_test.itervalues()
196          for cons in itertools.chain.from_iterable(constructors):
197 -            c = cons(a)
198 +            c = cons(a, usedforsecurity=False)
199              c.hexdigest()
200  
201      def test_algorithms_attribute(self):
202 @@ -115,28 +113,9 @@ class HashLibTestCase(unittest.TestCase)
203          self.assertRaises(ValueError, hashlib.new, 'spam spam spam spam spam')
204          self.assertRaises(TypeError, hashlib.new, 1)
205  
206 -    def test_get_builtin_constructor(self):
207 -        get_builtin_constructor = hashlib.__dict__[
208 -                '__get_builtin_constructor']
209 -        self.assertRaises(ValueError, get_builtin_constructor, 'test')
210 -        try:
211 -            import _md5
212 -        except ImportError:
213 -            pass
214 -        # This forces an ImportError for "import _md5" statements
215 -        sys.modules['_md5'] = None
216 -        try:
217 -            self.assertRaises(ValueError, get_builtin_constructor, 'md5')
218 -        finally:
219 -            if '_md5' in locals():
220 -                sys.modules['_md5'] = _md5
221 -            else:
222 -                del sys.modules['_md5']
223 -        self.assertRaises(TypeError, get_builtin_constructor, 3)
224 -
225      def test_hexdigest(self):
226          for name in self.supported_hash_names:
227 -            h = hashlib.new(name)
228 +            h = hashlib.new(name, usedforsecurity=False)
229              self.assertTrue(hexstr(h.digest()) == h.hexdigest())
230  
231      def test_large_update(self):
232 @@ -145,16 +125,16 @@ class HashLibTestCase(unittest.TestCase)
233          abcs = aas + bees + cees
234  
235          for name in self.supported_hash_names:
236 -            m1 = hashlib.new(name)
237 +            m1 = hashlib.new(name, usedforsecurity=False)
238              m1.update(aas)
239              m1.update(bees)
240              m1.update(cees)
241  
242 -            m2 = hashlib.new(name)
243 +            m2 = hashlib.new(name, usedforsecurity=False)
244              m2.update(abcs)
245              self.assertEqual(m1.digest(), m2.digest(), name+' update problem.')
246  
247 -            m3 = hashlib.new(name, abcs)
248 +            m3 = hashlib.new(name, abcs, usedforsecurity=False)
249              self.assertEqual(m1.digest(), m3.digest(), name+' new problem.')
250  
251      def check(self, name, data, digest):
252 @@ -162,7 +142,7 @@ class HashLibTestCase(unittest.TestCase)
253          # 2 is for hashlib.name(...) and hashlib.new(name, ...)
254          self.assertGreaterEqual(len(constructors), 2)
255          for hash_object_constructor in constructors:
256 -            computed = hash_object_constructor(data).hexdigest()
257 +            computed = hash_object_constructor(data, usedforsecurity=False).hexdigest()
258              self.assertEqual(
259                      computed, digest,
260                      "Hash algorithm %s constructed using %s returned hexdigest"
261 @@ -172,7 +152,8 @@ class HashLibTestCase(unittest.TestCase)
262  
263      def check_unicode(self, algorithm_name):
264          # Unicode objects are not allowed as input.
265 -        expected = hashlib.new(algorithm_name, str(u'spam')).hexdigest()
266 +        expected = hashlib.new(algorithm_name, str(u'spam'),
267 +                               usedforsecurity=False).hexdigest()
268          self.check(algorithm_name, u'spam', expected)
269  
270      def test_unicode(self):
271 @@ -354,6 +335,70 @@ class HashLibTestCase(unittest.TestCase)
272  
273          self.assertEqual(expected_hash, hasher.hexdigest())
274  
275 +    def test_issue9146(self):
276 +        # Ensure that various ways to use "MD5" from "hashlib" don't segfault:
277 +        m = hashlib.md5(usedforsecurity=False)
278 +        m.update(b'abc\n')
279 +        self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
280 +        
281 +        m = hashlib.new('md5', usedforsecurity=False)
282 +        m.update(b'abc\n')
283 +        self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
284 +        
285 +        m = hashlib.md5(b'abc\n', usedforsecurity=False)
286 +        self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
287 +        
288 +        m = hashlib.new('md5', b'abc\n', usedforsecurity=False)
289 +        self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
290 +
291 +    def assertRaisesUnknownCipher(self, callable_obj=None, *args, **kwargs):
292 +        try:
293 +            callable_obj(*args, **kwargs)
294 +        except ValueError, e:
295 +            if not e.args[0].endswith('unknown cipher'):
296 +                self.fail('Incorrect exception raised')
297 +        else:
298 +            self.fail('Exception was not raised')
299 +
300 +    @unittest.skipUnless(OPENSSL_ENFORCES_FIPS,
301 +                         'FIPS enforcement required for this test.')
302 +    def test_hashlib_fips_mode(self):        
303 +        # Ensure that we raise a ValueError on vanilla attempts to use MD5
304 +        # in hashlib in a FIPS-enforced setting:
305 +        self.assertRaisesUnknownCipher(hashlib.md5)
306 +        self.assertRaisesUnknownCipher(hashlib.new, 'md5')
307 +
308 +    @unittest.skipUnless(OPENSSL_ENFORCES_FIPS,
309 +                         'FIPS enforcement required for this test.')
310 +    def test_hashopenssl_fips_mode(self):
311 +        # Verify the _hashlib module's handling of md5:
312 +        import _hashlib
313 +
314 +        assert hasattr(_hashlib, 'openssl_md5')
315 +
316 +        # Ensure that _hashlib raises a ValueError on vanilla attempts to
317 +        # use MD5 in a FIPS-enforced setting:
318 +        self.assertRaisesUnknownCipher(_hashlib.openssl_md5)
319 +        self.assertRaisesUnknownCipher(_hashlib.new, 'md5')
320 +
321 +        # Ensure that in such a setting we can whitelist a callsite with
322 +        # usedforsecurity=False and have it succeed:
323 +        m = _hashlib.openssl_md5(usedforsecurity=False)
324 +        m.update('abc\n')
325 +        self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
326 +        
327 +        m = _hashlib.new('md5', usedforsecurity=False)
328 +        m.update('abc\n')
329 +        self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
330 +        
331 +        m = _hashlib.openssl_md5('abc\n', usedforsecurity=False)
332 +        self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
333 +        
334 +        m = _hashlib.new('md5', 'abc\n', usedforsecurity=False)
335 +        self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
336 +        
337 +
338 +
339  def test_main():
340      test_support.run_unittest(HashLibTestCase)
341  
342 diff -up Python-2.7.2/Modules/_hashopenssl.c.hashlib-fips Python-2.7.2/Modules/_hashopenssl.c
343 --- Python-2.7.2/Modules/_hashopenssl.c.hashlib-fips    2011-06-11 11:46:26.000000000 -0400
344 +++ Python-2.7.2/Modules/_hashopenssl.c    2011-09-14 00:21:26.199252001 -0400
345 @@ -36,6 +36,8 @@
346  #endif
347  
348  /* EVP is the preferred interface to hashing in OpenSSL */
349 +#include <openssl/ssl.h>
350 +#include <openssl/err.h>
351  #include <openssl/evp.h>
352  
353  #define MUNCH_SIZE INT_MAX
354 @@ -65,11 +67,19 @@ typedef struct {
355  
356  static PyTypeObject EVPtype;
357  
358 +/* Struct to hold all the cached information we need on a specific algorithm.
359 +   We have one of these per algorithm */
360 +typedef struct {
361 +    PyObject *name_obj;
362 +    EVP_MD_CTX ctxs[2];
363 +    /* ctx_ptrs will point to ctxs unless an error occurred, when it will
364 +       be NULL: */
365 +    EVP_MD_CTX *ctx_ptrs[2];
366 +    PyObject *error_msgs[2];
367 +} EVPCachedInfo;
368  
369 -#define DEFINE_CONSTS_FOR_NEW(Name)  \
370 -    static PyObject *CONST_ ## Name ## _name_obj = NULL; \
371 -    static EVP_MD_CTX CONST_new_ ## Name ## _ctx; \
372 -    static EVP_MD_CTX *CONST_new_ ## Name ## _ctx_p = NULL;
373 +#define DEFINE_CONSTS_FOR_NEW(Name) \
374 +    static EVPCachedInfo cached_info_ ##Name;
375  
376  DEFINE_CONSTS_FOR_NEW(md5)
377  DEFINE_CONSTS_FOR_NEW(sha1)
378 @@ -115,6 +125,48 @@ EVP_hash(EVPobject *self, const void *vp
379      }
380  }
381  
382 +static void
383 +mc_ctx_init(EVP_MD_CTX *ctx, int usedforsecurity)
384 +{
385 +    EVP_MD_CTX_init(ctx);
386 +
387 +    /*
388 +      If the user has declared that this digest is being used in a
389 +      non-security role (e.g. indexing into a data structure), set
390 +      the exception flag for openssl to allow it
391 +    */
392 +    if (!usedforsecurity) {
393 +#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
394 +        EVP_MD_CTX_set_flags(ctx,
395 +                             EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
396 +#endif
397 +    }
398 +}
399 +
400 +/* Get an error msg for the last error as a PyObject */
401 +static PyObject *
402 +error_msg_for_last_error(void)
403 +{
404 +    char *errstr;
405 +
406 +    errstr = ERR_error_string(ERR_peek_last_error(), NULL);
407 +    ERR_clear_error();
408 +
409 +    return PyString_FromString(errstr); /* Can be NULL */
410 +}
411 +
412 +static void
413 +set_evp_exception(void)
414 +{
415 +    char *errstr;
416 +
417 +    errstr = ERR_error_string(ERR_peek_last_error(), NULL);
418 +    ERR_clear_error();
419 +
420 +    PyErr_SetString(PyExc_ValueError, errstr);
421 +}
422 +
423 +
424  /* Internal methods for a hash object */
425  
426  static void
427 @@ -313,14 +365,15 @@ EVP_repr(PyObject *self)
428  static int
429  EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
430  {
431 -    static char *kwlist[] = {"name", "string", NULL};
432 +    static char *kwlist[] = {"name", "string", "usedforsecurity", NULL};
433      PyObject *name_obj = NULL;
434 +    int usedforsecurity = 1;
435      Py_buffer view = { 0 };
436      char *nameStr;
437      const EVP_MD *digest;
438  
439 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s*:HASH", kwlist,
440 -                                     &name_obj, &view)) {
441 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s*i:HASH", kwlist,
442 +                                     &name_obj, &view, &usedforsecurity)) {
443          return -1;
444      }
445  
446 @@ -336,7 +389,12 @@ EVP_tp_init(EVPobject *self, PyObject *a
447          PyBuffer_Release(&view);
448          return -1;
449      }
450 -    EVP_DigestInit(&self->ctx, digest);
451 +    mc_ctx_init(&self->ctx, usedforsecurity);
452 +    if (!EVP_DigestInit_ex(&self->ctx, digest, NULL)) {
453 +        set_evp_exception();
454 +        PyBuffer_Release(&view);
455 +        return -1;
456 +    }
457  
458      self->name = name_obj;
459      Py_INCREF(self->name);
460 @@ -420,7 +478,8 @@ static PyTypeObject EVPtype = {
461  static PyObject *
462  EVPnew(PyObject *name_obj,
463         const EVP_MD *digest, const EVP_MD_CTX *initial_ctx,
464 -       const unsigned char *cp, Py_ssize_t len)
465 +       const unsigned char *cp, Py_ssize_t len,
466 +       int usedforsecurity)
467  {
468      EVPobject *self;
469  
470 @@ -435,7 +494,12 @@ EVPnew(PyObject *name_obj,
471      if (initial_ctx) {
472          EVP_MD_CTX_copy(&self->ctx, initial_ctx);
473      } else {
474 -        EVP_DigestInit(&self->ctx, digest);
475 +        mc_ctx_init(&self->ctx, usedforsecurity);
476 +        if (!EVP_DigestInit_ex(&self->ctx, digest, NULL)) {
477 +            set_evp_exception();
478 +            Py_DECREF(self);
479 +            return NULL;
480 +        }
481      }
482  
483      if (cp && len) {
484 @@ -459,20 +523,28 @@ PyDoc_STRVAR(EVP_new__doc__,
485  An optional string argument may be provided and will be\n\
486  automatically hashed.\n\
487  \n\
488 -The MD5 and SHA1 algorithms are always supported.\n");
489 +The MD5 and SHA1 algorithms are always supported.\n\
490 +\n\
491 +An optional \"usedforsecurity=True\" keyword argument is provided for use in\n\
492 +environments that enforce FIPS-based restrictions.  Some implementations of\n\
493 +OpenSSL can be configured to prevent the usage of non-secure algorithms (such\n\
494 +as MD5).  If you have a non-security use for these algorithms (e.g. a hash\n\
495 +table), you can override this argument by marking the callsite as\n\
496 +\"usedforsecurity=False\".");
497  
498  static PyObject *
499  EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
500  {
501 -    static char *kwlist[] = {"name", "string", NULL};
502 +    static char *kwlist[] = {"name", "string", "usedforsecurity", NULL};
503      PyObject *name_obj = NULL;
504      Py_buffer view = { 0 };
505      PyObject *ret_obj;
506      char *name;
507      const EVP_MD *digest;
508 +    int usedforsecurity = 1;
509  
510 -    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|s*:new", kwlist,
511 -                                     &name_obj, &view)) {
512 +    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|s*i:new", kwlist,
513 +                                     &name_obj, &view, &usedforsecurity)) {
514          return NULL;
515      }
516  
517 @@ -484,58 +556,118 @@ EVP_new(PyObject *self, PyObject *args,
518      digest = EVP_get_digestbyname(name);
519  
520      ret_obj = EVPnew(name_obj, digest, NULL, (unsigned char*)view.buf,
521 -                     view.len);
522 +                     view.len, usedforsecurity);
523      PyBuffer_Release(&view);
524  
525      return ret_obj;
526  }
527  
528  /*
529 - *  This macro generates constructor function definitions for specific
530 - *  hash algorithms.  These constructors are much faster than calling
531 - *  the generic one passing it a python string and are noticably
532 - *  faster than calling a python new() wrapper.  Thats important for
533 + *  This macro and function generates a family of constructor function
534 + *  definitions for specific hash algorithms.  These constructors are much
535 + *  faster than calling the generic one passing it a python string and are
536 + *  noticably faster than calling a python new() wrapper.  That's important for
537   *  code that wants to make hashes of a bunch of small strings.
538   */
539  #define GEN_CONSTRUCTOR(NAME)  \
540      static PyObject * \
541 -    EVP_new_ ## NAME (PyObject *self, PyObject *args) \
542 +    EVP_new_ ## NAME (PyObject *self, PyObject *args, PyObject *kwdict)  \
543      { \
544 -        Py_buffer view = { 0 }; \
545 -        PyObject *ret_obj; \
546 -     \
547 -        if (!PyArg_ParseTuple(args, "|s*:" #NAME , &view)) { \
548 -            return NULL; \
549 -        } \
550 -     \
551 -        ret_obj = EVPnew( \
552 -                    CONST_ ## NAME ## _name_obj, \
553 -                    NULL, \
554 -                    CONST_new_ ## NAME ## _ctx_p, \
555 -                    (unsigned char*)view.buf, view.len); \
556 -        PyBuffer_Release(&view); \
557 -        return ret_obj; \
558 +        return implement_specific_EVP_new(self, args, kwdict,      \
559 +                                          "|s*i:" #NAME,           \
560 +                                          &cached_info_ ## NAME ); \
561      }
562  
563 +static PyObject *
564 +implement_specific_EVP_new(PyObject *self, PyObject *args, PyObject *kwdict,
565 +                           const char *format,
566 +                           EVPCachedInfo *cached_info)
567 +{
568 +    static char *kwlist[] = {"string", "usedforsecurity", NULL}; 
569 +    Py_buffer view = { 0 };
570 +    int usedforsecurity = 1;
571 +    int idx;
572 +    PyObject *ret_obj = NULL;
573 +
574 +    assert(cached_info);
575 +
576 +    if (!PyArg_ParseTupleAndKeywords(args, kwdict, format, kwlist,
577 +                                     &view, &usedforsecurity)) {
578 +        return NULL;
579 +    }
580 +
581 +    idx = usedforsecurity ? 1 : 0;
582 +
583 +    /*
584 +     * If an error occurred during creation of the global content, the ctx_ptr
585 +     * will be NULL, and the error_msg will hopefully be non-NULL:
586 +     */
587 +    if (cached_info->ctx_ptrs[idx]) {
588 +        /* We successfully initialized this context; copy it: */
589 +        ret_obj = EVPnew(cached_info->name_obj,
590 +                         NULL,
591 +                         cached_info->ctx_ptrs[idx],
592 +                         (unsigned char*)view.buf, view.len,
593 +                         usedforsecurity);
594 +    } else {
595 +        /* Some kind of error happened initializing the global context for
596 +           this (digest, usedforsecurity) pair.
597 +           Raise an exception with the saved error message: */
598 +        if (cached_info->error_msgs[idx]) {
599 +            PyErr_SetObject(PyExc_ValueError, cached_info->error_msgs[idx]);
600 +        } else {
601 +            PyErr_SetString(PyExc_ValueError, "Error initializing hash");
602 +        }
603 +    }
604 +
605 +    PyBuffer_Release(&view);
606 +
607 +    return ret_obj;
608 +}
609 +
610  /* a PyMethodDef structure for the constructor */
611  #define CONSTRUCTOR_METH_DEF(NAME)  \
612 -    {"openssl_" #NAME, (PyCFunction)EVP_new_ ## NAME, METH_VARARGS, \
613 +    {"openssl_" #NAME, (PyCFunction)EVP_new_ ## NAME, \
614 +        METH_VARARGS |METH_KEYWORDS, \
615          PyDoc_STR("Returns a " #NAME \
616                    " hash object; optionally initialized with a string") \
617      }
618  
619 -/* used in the init function to setup a constructor: initialize OpenSSL
620 -   constructor constants if they haven't been initialized already.  */
621 -#define INIT_CONSTRUCTOR_CONSTANTS(NAME)  do { \
622 -    if (CONST_ ## NAME ## _name_obj == NULL) { \
623 -    CONST_ ## NAME ## _name_obj = PyString_FromString(#NAME); \
624 -        if (EVP_get_digestbyname(#NAME)) { \
625 -            CONST_new_ ## NAME ## _ctx_p = &CONST_new_ ## NAME ## _ctx; \
626 -            EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \
627 -        } \
628 -    } \
629 +/*
630 +  Macro/function pair to set up the constructors.
631 +
632 +  Try to initialize a context for each hash twice, once with
633 +  EVP_MD_CTX_FLAG_NON_FIPS_ALLOW and once without.
634 +  
635 +  Any that have errors during initialization will end up wit a NULL ctx_ptrs
636 +  entry, and err_msgs will be set (unless we're very low on memory)
637 +*/
638 +#define INIT_CONSTRUCTOR_CONSTANTS(NAME)  do {    \
639 +    init_constructor_constant(&cached_info_ ## NAME, #NAME); \
640  } while (0);
641  
642 +static void
643 +init_constructor_constant(EVPCachedInfo *cached_info, const char *name)
644 +{
645 +    assert(cached_info);
646 +    cached_info->name_obj = PyString_FromString(name);
647 +    if (EVP_get_digestbyname(name)) {
648 +        int i;
649 +        for (i=0; i<2; i++) {
650 +            mc_ctx_init(&cached_info->ctxs[i], i);
651 +            if (EVP_DigestInit_ex(&cached_info->ctxs[i],
652 +                                  EVP_get_digestbyname(name), NULL)) {
653 +                /* Success: */
654 +                cached_info->ctx_ptrs[i] = &cached_info->ctxs[i];
655 +            } else {
656 +                /* Failure: */
657 +                cached_info->ctx_ptrs[i] = NULL;
658 +                cached_info->error_msgs[i] = error_msg_for_last_error();
659 +            }
660 +        }
661 +    }
662 +}
663 +
664  GEN_CONSTRUCTOR(md5)
665  GEN_CONSTRUCTOR(sha1)
666  #ifdef _OPENSSL_SUPPORTS_SHA2
667 @@ -565,13 +700,10 @@ init_hashlib(void)
668  {
669      PyObject *m;
670  
671 +    SSL_load_error_strings();
672 +    SSL_library_init();
673      OpenSSL_add_all_digests();
674  
675 -    /* TODO build EVP_functions openssl_* entries dynamically based
676 -     * on what hashes are supported rather than listing many
677 -     * but having some be unsupported.  Only init appropriate
678 -     * constants. */
679 -
680      Py_TYPE(&EVPtype) = &PyType_Type;
681      if (PyType_Ready(&EVPtype) < 0)
682          return;
683 diff -up Python-2.7.2/Modules/Setup.dist.hashlib-fips Python-2.7.2/Modules/Setup.dist
684 --- Python-2.7.2/Modules/Setup.dist.hashlib-fips    2011-09-14 00:21:26.163252001 -0400
685 +++ Python-2.7.2/Modules/Setup.dist    2011-09-14 00:21:26.201252001 -0400
686 @@ -248,14 +248,14 @@ imageop imageop.c    # Operations on images
687  # Message-Digest Algorithm, described in RFC 1321.  The necessary files
688  # md5.c and md5.h are included here.
689  
690 -_md5 md5module.c md5.c
691 +#_md5 md5module.c md5.c
692  
693  
694  # The _sha module implements the SHA checksum algorithms.
695  # (NIST's Secure Hash Algorithms.)
696 -_sha shamodule.c
697 -_sha256 sha256module.c
698 -_sha512 sha512module.c
699 +#_sha shamodule.c
700 +#_sha256 sha256module.c
701 +#_sha512 sha512module.c
702  
703  
704  # SGI IRIX specific modules -- off by default.
705 diff -up Python-2.7.2/setup.py.hashlib-fips Python-2.7.2/setup.py
706 --- Python-2.7.2/setup.py.hashlib-fips    2011-09-14 00:21:25.722252001 -0400
707 +++ Python-2.7.2/setup.py    2011-09-14 00:21:26.203252001 -0400
708 @@ -768,21 +768,6 @@ class PyBuildExt(build_ext):
709                  print ("warning: openssl 0x%08x is too old for _hashlib" %
710                         openssl_ver)
711                  missing.append('_hashlib')
712 -        if COMPILED_WITH_PYDEBUG or not have_usable_openssl:
713 -            # The _sha module implements the SHA1 hash algorithm.
714 -            exts.append( Extension('_sha', ['shamodule.c']) )
715 -            # The _md5 module implements the RSA Data Security, Inc. MD5
716 -            # Message-Digest Algorithm, described in RFC 1321.  The
717 -            # necessary files md5.c and md5.h are included here.
718 -            exts.append( Extension('_md5',
719 -                            sources = ['md5module.c', 'md5.c'],
720 -                            depends = ['md5.h']) )
721 -
722 -        min_sha2_openssl_ver = 0x00908000
723 -        if COMPILED_WITH_PYDEBUG or openssl_ver < min_sha2_openssl_ver:
724 -            # OpenSSL doesn't do these until 0.9.8 so we'll bring our own hash
725 -            exts.append( Extension('_sha256', ['sha256module.c']) )
726 -            exts.append( Extension('_sha512', ['sha512module.c']) )
727  
728          # Modules that provide persistent dictionary-like semantics.  You will
729          # probably want to arrange for at least one of them to be available on