mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	 0a97427ee5
			
		
	
	
		0a97427ee5
		
			
		
	
	
	
	
		
			
			A new extension module, `_hmac`, now exposes the HACL* HMAC (formally verified) implementation. The HACL* implementation is used as a fallback implementation when the OpenSSL implementation of HMAC is not available or disabled. For now, only named hash algorithms are recognized and SIMD support provided by HACL* for the BLAKE2 hash functions is not yet used.
		
			
				
	
	
		
			102 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			102 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import functools
 | |
| import hashlib
 | |
| import unittest
 | |
| from test.support.import_helper import import_module
 | |
| 
 | |
| try:
 | |
|     import _hashlib
 | |
| except ImportError:
 | |
|     _hashlib = None
 | |
| 
 | |
| try:
 | |
|     import _hmac
 | |
| except ImportError:
 | |
|     _hmac = None
 | |
| 
 | |
| 
 | |
| def requires_hashlib():
 | |
|     return unittest.skipIf(_hashlib is None, "requires _hashlib")
 | |
| 
 | |
| 
 | |
| def requires_builtin_hmac():
 | |
|     return unittest.skipIf(_hmac is None, "requires _hmac")
 | |
| 
 | |
| 
 | |
| def _decorate_func_or_class(func_or_class, decorator_func):
 | |
|     if not isinstance(func_or_class, type):
 | |
|         return decorator_func(func_or_class)
 | |
| 
 | |
|     decorated_class = func_or_class
 | |
|     setUpClass = decorated_class.__dict__.get('setUpClass')
 | |
|     if setUpClass is None:
 | |
|         def setUpClass(cls):
 | |
|             super(decorated_class, cls).setUpClass()
 | |
|         setUpClass.__qualname__ = decorated_class.__qualname__ + '.setUpClass'
 | |
|         setUpClass.__module__ = decorated_class.__module__
 | |
|     else:
 | |
|         setUpClass = setUpClass.__func__
 | |
|     setUpClass = classmethod(decorator_func(setUpClass))
 | |
|     decorated_class.setUpClass = setUpClass
 | |
|     return decorated_class
 | |
| 
 | |
| 
 | |
| def requires_hashdigest(digestname, openssl=None, usedforsecurity=True):
 | |
|     """Decorator raising SkipTest if a hashing algorithm is not available.
 | |
| 
 | |
|     The hashing algorithm may be missing, blocked by a strict crypto policy,
 | |
|     or Python may be configured with `--with-builtin-hashlib-hashes=no`.
 | |
| 
 | |
|     If 'openssl' is True, then the decorator checks that OpenSSL provides
 | |
|     the algorithm. Otherwise the check falls back to (optional) built-in
 | |
|     HACL* implementations.
 | |
| 
 | |
|     The usedforsecurity flag is passed to the constructor but has no effect
 | |
|     on HACL* implementations.
 | |
| 
 | |
|     Examples of exceptions being suppressed:
 | |
|     ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS
 | |
|     ValueError: unsupported hash type md4
 | |
|     """
 | |
|     if openssl and _hashlib is not None:
 | |
|         def test_availability():
 | |
|             _hashlib.new(digestname, usedforsecurity=usedforsecurity)
 | |
|     else:
 | |
|         def test_availability():
 | |
|             hashlib.new(digestname, usedforsecurity=usedforsecurity)
 | |
| 
 | |
|     def decorator_func(func):
 | |
|         @functools.wraps(func)
 | |
|         def wrapper(*args, **kwargs):
 | |
|             try:
 | |
|                 test_availability()
 | |
|             except ValueError as exc:
 | |
|                 msg = f"missing hash algorithm: {digestname!r}"
 | |
|                 raise unittest.SkipTest(msg) from exc
 | |
|             return func(*args, **kwargs)
 | |
|         return wrapper
 | |
| 
 | |
|     def decorator(func_or_class):
 | |
|         return _decorate_func_or_class(func_or_class, decorator_func)
 | |
|     return decorator
 | |
| 
 | |
| 
 | |
| def requires_openssl_hashdigest(digestname, *, usedforsecurity=True):
 | |
|     """Decorator raising SkipTest if an OpenSSL hashing algorithm is missing.
 | |
| 
 | |
|     The hashing algorithm may be missing or blocked by a strict crypto policy.
 | |
|     """
 | |
|     def decorator_func(func):
 | |
|         @requires_hashlib()
 | |
|         @functools.wraps(func)
 | |
|         def wrapper(*args, **kwargs):
 | |
|             try:
 | |
|                 _hashlib.new(digestname, usedforsecurity=usedforsecurity)
 | |
|             except ValueError:
 | |
|                 msg = f"missing OpenSSL hash algorithm: {digestname!r}"
 | |
|                 raise unittest.SkipTest(msg)
 | |
|             return func(*args, **kwargs)
 | |
|         return wrapper
 | |
| 
 | |
|     def decorator(func_or_class):
 | |
|         return _decorate_func_or_class(func_or_class, decorator_func)
 | |
|     return decorator
 |