Python-3 with Openssl-3 FIPS enabled

I am trying to build a version of Python which is FIPS compliant, i.e does not let a user use a cryptographic algorithm which has not been approved by FIPS like MD5.

For this, I built a version of Openssl-3 using the enable-fips flag which will ensure that the fips provider is generated and I have updated my openssl.cnf file to use the FIPS provider. Here is my openssl.cnf file:

openssl_conf = openssl_init
.include /usr/local/openssl/ssl/fipsmodule.cnf
[openssl_init]
providers = provider_sect
[provider_sect]
fips = fips_sect
base = base_sect
[base_sect]
activate = 1

This works like a charm and I am not able to calculate the MD5 digest using openssl binary whereas I am able to calculate SHA1 which is FIPS validated:

./openssl MD5 openssl
Error setting digest
C020A0E9FB7F0000:error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported:crypto/evp/evp_fetch.c:349:Global default library context, Algorithm (MD5 : 102), Properties ()
C020A0E9FB7F0000:error:03000086:digital envelope routines:evp_md_init_internal:initialization error:crypto/evp/digest.c:252:
./openssl SHA1 openssl
SHA1(openssl)= 2c9d99744d2fdc0ae12ca31829126d68f2792977

I built Python with this version of Openssl-3:

./python
Python 3.8.14 (default, Oct 19 2022, 18:13:27)
[GCC 7.3.1 20180712 (Red Hat 7.3.1-15)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
>>> ssl.OPENSSL_VERSION
'OpenSSL 3.0.5 5 Jul 2022'

I am reading the documentation for hashlib: hashlib — Secure hashes and message digests — Python 3.10.8 documentation and found this:

Constructors for hash algorithms that are always present in this module are sha1() , sha224() , sha256() , sha384() , sha512() , blake2b(). md5() is normally available as well, though it may be missing or blocked if you are using a rare “FIPS compliant” build of Python.

I assumed that building with Openssl-3 using the FIPS provider in the openss.cnf file is equivalent to using a FIPS compliant build of python where I will not be allowed to use algorithms that are not FIPS valdiated. But I am able to calculate the digest using MD5 algorithm:

>>> ssl.OPENSSL_VERSION
'OpenSSL 3.0.5 5 Jul 2022'
>>> import hashlib
>>> m = hashlib.md5()
>>> m.update(b"hello")
>>> m.digest()
b']A@*\xbcK*v\xb9q\x9d\x91\x10\x17\xc5\x92'

I tried searching online but cannot find the directions to building a FIPS compliant version of Python. Can I please get some help with this?

Please do not upload screenshots of text at all. Just copy the text directly. You did it correctly for openssl.cnf.

Updated. Added the text and removed screenshot, thanks!

The fix for gh-95231 was merged to main (3.12) and backported to 3.11 and 3.10. It might be the correct fix for you. Instead of building Python 3.8, which is almost EOL, try with 3.10 or 3.11 instead.

1 Like

Remember that docs are also versioned. You’re reading the docs for Python 3.10 but you are clearly using Python 3.8.

Thanks for the suggestion, I tried the same steps with Python-3.10 and it leads to the same result.

./python
Python 3.10.8 (main, Oct 25 2022, 17:24:02) [GCC 7.3.1 20180712 (Red Hat 7.3.1-15)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import hashlib
>>> m = hashlib.md5()
>>> m.update(b"hello")
>>> m.digest()
b']A@*\xbcK*v\xb9q\x9d\x91\x10\x17\xc5\x92'
>>> import ssl
>>> ssl.OPENSSL_VERSION
'OpenSSL 3.0.5 5 Jul 2022'

I have built this with the same Openssl-3 as Python-3.8 and the openssl.cnf is populated with only FIPS provider.

I tried strace to find out if Python is linking to the correct openssl directory and I did find references to the correct openssl dir and the correct fips.so module:

openat(AT_FDCWD, "/usr/local/openssl/ssl/openssl.cnf", O_RDONLY) = 3
openat(AT_FDCWD, "/usr/local/openssl/lib/ossl-modules/fips.so", O_RDONLY|O_CLOEXEC) = 3

Are there any other steps required to build FIPS compliant version of Python? For now, I have built Python with a FIPS enabled Openssl-3.

When I say FIPS enabled Openssl-3, its just a config file which is referring to the fips provider. This is different than the way Openssl-1.0.x FIPS was built and I am confused if the steps are different for Openssl-3.

Do you have any guidance/suggestion/ideas on this?

Could you be running into
FIPS usedforsecurity flag is no longer functional with OpenSSL 3.0.0 · Issue #90307 · python/cpython · GitHub here? Note that
OpenSSL 3.x support in Python still seems to be in progress (I can’t
even get make test to pass for some of the stdlib components on
OpenSSL v3 systems at the moment).

Yes, it is very much WIP, and currently on a halt.