Skip to content

Commit

Permalink
bpo-9216: Expose OpenSSL FIPS_mode() as _hashlib.get_fips_mode() (GH-…
Browse files Browse the repository at this point in the history
…19703)

test.pythoninfo logs OpenSSL FIPS_mode() and Linux
/proc/sys/crypto/fips_enabled in a new "fips" section.

Co-Authored-By: Petr Viktorin <encukou@gmail.com>
  • Loading branch information
vstinner and encukou committed Apr 29, 2020
1 parent e5963ee commit e3dfb9b
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 1 deletion.
20 changes: 20 additions & 0 deletions Lib/test/pythoninfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -735,6 +754,7 @@ def collect_info(info):
collect_datetime,
collect_decimal,
collect_expat,
collect_fips,
collect_gdb,
collect_gdbm,
collect_get_config,
Expand Down
5 changes: 5 additions & 0 deletions Lib/test/test_hashlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,11 @@ def hash_in_chunks(chunk_size):

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):

Expand Down
43 changes: 43 additions & 0 deletions Modules/_hashopenssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
43 changes: 42 additions & 1 deletion Modules/clinic/_hashopenssl.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit e3dfb9b

Please sign in to comment.