diff options
-rw-r--r-- | Lib/test/pythoninfo.py | 20 | ||||
-rw-r--r-- | Lib/test/test_hashlib.py | 5 | ||||
-rw-r--r-- | Modules/_hashopenssl.c | 43 | ||||
-rw-r--r-- | Modules/clinic/_hashopenssl.c.h | 43 |
4 files changed, 110 insertions, 1 deletions
diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index cc0bbc5..cc228fb 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -720,6 +720,25 @@ def collect_windows(info_add): pass +def collect_fips(info_add): + try: + import _hashlib + except ImportError: + _hashlib = None + + if _hashlib is not None: + call_func(info_add, 'fips.openssl_fips_mode', _hashlib, 'get_fips_mode') + + try: + with open("/proc/sys/crypto/fips_enabled", encoding="utf-8") as fp: + line = fp.readline().rstrip() + + if line: + info_add('fips.linux_crypto_fips_enabled', line) + except OSError: + pass + + def collect_info(info): error = False info_add = info.add @@ -735,6 +754,7 @@ def collect_info(info): collect_datetime, collect_decimal, collect_expat, + collect_fips, collect_gdb, collect_gdbm, collect_get_config, diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index 33b687e..31d8e55 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -856,6 +856,11 @@ class HashLibTestCase(unittest.TestCase): self.assertEqual(expected_hash, hasher.hexdigest()) + @unittest.skipUnless(hasattr(c_hashlib, 'get_fips_mode'), + 'need _hashlib.get_fips_mode') + def test_get_fips_mode(self): + self.assertIsInstance(c_hashlib.get_fips_mode(), int) + class KDFTests(unittest.TestCase): diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 0919cd3..91834e5 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -25,6 +25,8 @@ #include <openssl/objects.h> #include "openssl/err.h" +#include <openssl/crypto.h> // FIPS_mode() + #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) /* OpenSSL < 1.1.0 */ #define EVP_MD_CTX_new EVP_MD_CTX_create @@ -1096,12 +1098,53 @@ generate_hash_name_list(void) return state.set; } +/* LibreSSL doesn't support FIPS: + https://marc.info/?l=openbsd-misc&m=139819485423701&w=2 + + Ted Unangst wrote: "I figured I should mention our current libressl policy + wrt FIPS mode. It's gone and it's not coming back." */ +#ifndef LIBRESSL_VERSION_NUMBER +/*[clinic input] +_hashlib.get_fips_mode -> int + +Determine the OpenSSL FIPS mode of operation. + +Effectively any non-zero return value indicates FIPS mode; +values other than 1 may have additional significance. + +See OpenSSL documentation for the FIPS_mode() function for details. +[clinic start generated code]*/ + +static int +_hashlib_get_fips_mode_impl(PyObject *module) +/*[clinic end generated code: output=87eece1bab4d3fa9 input=c2799c3132a36d6c]*/ + +{ + ERR_clear_error(); + int result = FIPS_mode(); + if (result == 0) { + // "If the library was built without support of the FIPS Object Module, + // then the function will return 0 with an error code of + // CRYPTO_R_FIPS_MODE_NOT_SUPPORTED (0x0f06d065)." + // But 0 is also a valid result value. + unsigned long errcode = ERR_peek_last_error(); + if (errcode) { + _setException(PyExc_ValueError); + return -1; + } + } + return result; +} +#endif // !LIBRESSL_VERSION_NUMBER + + /* List of functions exported by this module */ static struct PyMethodDef EVP_functions[] = { EVP_NEW_METHODDEF PBKDF2_HMAC_METHODDEF _HASHLIB_SCRYPT_METHODDEF + _HASHLIB_GET_FIPS_MODE_METHODDEF _HASHLIB_HMAC_DIGEST_METHODDEF _HASHLIB_OPENSSL_MD5_METHODDEF _HASHLIB_OPENSSL_SHA1_METHODDEF diff --git a/Modules/clinic/_hashopenssl.c.h b/Modules/clinic/_hashopenssl.c.h index de53e7e..275784d 100644 --- a/Modules/clinic/_hashopenssl.c.h +++ b/Modules/clinic/_hashopenssl.c.h @@ -725,7 +725,48 @@ exit: return return_value; } +#if !defined(LIBRESSL_VERSION_NUMBER) + +PyDoc_STRVAR(_hashlib_get_fips_mode__doc__, +"get_fips_mode($module, /)\n" +"--\n" +"\n" +"Determine the OpenSSL FIPS mode of operation.\n" +"\n" +"Effectively any non-zero return value indicates FIPS mode;\n" +"values other than 1 may have additional significance.\n" +"\n" +"See OpenSSL documentation for the FIPS_mode() function for details."); + +#define _HASHLIB_GET_FIPS_MODE_METHODDEF \ + {"get_fips_mode", (PyCFunction)_hashlib_get_fips_mode, METH_NOARGS, _hashlib_get_fips_mode__doc__}, + +static int +_hashlib_get_fips_mode_impl(PyObject *module); + +static PyObject * +_hashlib_get_fips_mode(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + int _return_value; + + _return_value = _hashlib_get_fips_mode_impl(module); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* !defined(LIBRESSL_VERSION_NUMBER) */ + #ifndef _HASHLIB_SCRYPT_METHODDEF #define _HASHLIB_SCRYPT_METHODDEF #endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */ -/*[clinic end generated code: output=acb22ccddb7043c7 input=a9049054013a1b77]*/ + +#ifndef _HASHLIB_GET_FIPS_MODE_METHODDEF + #define _HASHLIB_GET_FIPS_MODE_METHODDEF +#endif /* !defined(_HASHLIB_GET_FIPS_MODE_METHODDEF) */ +/*[clinic end generated code: output=b0703dd5a043394d input=a9049054013a1b77]*/ |