Search
Rajeev Kallur

Enabling Python 3 with OpenSSL/FIPS on Microsoft Windows

December 21, 2020

Introduction

Federal Information Processing Standard (FIPS) are a set of encryption algorithms and is mandatory in all computer systems and software used by non-military American government agencies, government contractors and vendors who work with the agencies. When new software is developed, it needs to be FIPS-compliant. Thus, there is a need to enable Python with FIPS, but the default Python package comes without FIPS as shown in screenshot below.

This blog will explain, step-by-step, how to enable Python 3 with the OpenSSL/FIPS standard on a Microsoft Windows platform so that any new software compiled out of it, is FIPS-compliant.

Prerequisites

  • Cygwin environment
  • Python 3
  • Visual Studio 2017

STEPS

Step 1 Download the OpenSSL and FIPS source from http://www.openssl.org and the Python 3 source from http://www.python.org

Step 2 Convert all symlinks in the archive to regular files. This is done in Linux, Cygwin environment.

Untar

   $ tar -zxvf openssl-fips-2.0.16.tar.gz
   $ tar -zxvf openssl-1.0.2u.tar.gz
   $ tar -zxvf Python-3.8.6.tgz

Zip -9

   $ zip -9 -r openssl-fips-2.0.16.zip openssl-fips-2.0.16
   $ zip -9 -r openssl-1.0.2u.zip openssl-1.0.2u
   $ zip -9 -r Python-3.8.6.zip Python-3.8.6

Finally, unzip in Windows to the c:\work\ folder.

Step 3 Install NASM for x64 and copy the contents of C:\Program Files\NASM to the C:\work\openssl-1.0.2u\ folder.

Note: NASM is a netwide assembler program and can be downloaded from [https://www.nasm.us/pub/nasm/releasebuilds]

Step 4 Build the FIPS module using the VS 2015 Native Tools Command prompt.

   > cd openssl-fips-2.0.16
   > ms\do_fips

Rename the folder “out32dll” to “lib”.

Rename the folder “util” to “bin”.

Move “fipsstandalonesha1.exe” from “lib” to “bin”.

This is done so that OpenSSL can compile in the next steps.

Step 5 Build OpenSSL module using the VS 2015 Native Tools Command prompt.

   cd openssl-1.0.2u
   perl Configure VC-WIN64A no-zlib no-idea no-mdc2 no-rc5 no-ssl2 no-ssl3 fips --with-fipslibdir=C:\usr\local\ssl\fips-2.0
   ms\do_win64a
   nmake -f ms\nt.mak all
   nmake -f ms\nt.mak install

The openssl.exe and libeay32.dll and ssleay32.dll files are generated be in the C:\usr\local\ssl\bin\ folder.

Step 6 Unzip Python in Windows and create an 'externals' directory at the root (c:\work\Python-3.8.6) folder.

Under 'externals', create a directory for openssl-1.0.2u and copy all the contents of c:\usr\local\ssl\ to this directory.

Step 7 Under 'externals', create a directory for openssl-bin-1.0.2u/amd64 and copy all the files from c:\work\openssl-1.2.u\out32dll to this directory.

Also, copy all the files from c:\work\openssl-1.2.u\inc32 to the openssl-bin-1.0.2u/amd64/include directory.

Step 8 Patch/Add/Modify these codes to files as shown below under Python-3.8.6 source (c:\work\Python-3.8.6).

Lib\ssl.py:

   try:
       from _ssl import FIPS_mode, FIPS_mode_set
       print('successful import')
   except ImportError as e:
       print('error in importing')
       print(e)

Modules/_ssl.c:

   static PyObject *
   _ssl_FIPS_mode_impl(PyObject *module) {
       return PyLong_FromLong(FIPS_mode());
   }
   
   static PyObject *
   _ssl_FIPS_mode_set_impl(PyObject *module, int n) {
       if (FIPS_mode_set(n) == 0) {
           _setSSLError(ERR_error_string(ERR_get_error(), NULL) , 0, __FILE__, __LINE__);
           return NULL;
       }
       Py_RETURN_NONE;
   }
   
   static PyMethodDef PySSL_methods[] = {
       _SSL__TEST_DECODE_CERT_METHODDEF
       _SSL_RAND_ADD_METHODDEF
       _SSL_RAND_BYTES_METHODDEF
       _SSL_RAND_PSEUDO_BYTES_METHODDEF
       _SSL_RAND_EGD_METHODDEF
       _SSL_RAND_STATUS_METHODDEF
       _SSL_GET_DEFAULT_VERIFY_PATHS_METHODDEF
       _SSL_ENUM_CERTIFICATES_METHODDEF
       _SSL_ENUM_CRLS_METHODDEF
       _SSL_TXT2OBJ_METHODDEF
       _SSL_NID2OBJ_METHODDEF
       _SSL_FIPS_MODE_METHODDEF
       _SSL_FIPS_MODE_SET_METHODDEF
       {NULL,                  NULL}            /* Sentinel */
   };

Modules/clinic/_ssl.c.h:

   PyDoc_STRVAR(_ssl_FIPS_mode__doc__,
   "FIPS Mode");
   
   #define _SSL_FIPS_MODE_METHODDEF    \
       {"FIPS_mode", (PyCFunction)_ssl_FIPS_mode, METH_NOARGS, _ssl_FIPS_mode__doc__},    
   
   static PyObject *
   _ssl_FIPS_mode_impl(PyObject *module);
   
   static PyObject *
   _ssl_FIPS_mode(PyObject *module, PyObject *Py_UNUSED(ignored))
   {
       return _ssl_FIPS_mode_impl(module);
   }
   
   PyDoc_STRVAR(_ssl_FIPS_mode_set_doc__,
   "FIPS Mode Set");
   
   #define _SSL_FIPS_MODE_SET_METHODDEF    \
       {"FIPS_mode_set", (PyCFunction)_ssl_FIPS_mode_set, METH_O, _ssl_FIPS_mode_set_doc__},   
   
   static PyObject *
   _ssl_FIPS_mode_set_impl(PyObject *module, int n);
   
   static PyObject *
   _ssl_FIPS_mode_set(PyObject *module, PyObject *arg)
   {
       PyObject *return_value = NULL;
       int n;
   
       if (!PyArg_Parse(arg, "i:FIPS_mode_set", &n)) {
           goto exit;
       }
       return_value = _ssl_FIPS_mode_set_impl(module, n);
   
   exit:
       return return_value;
   }

The above code is used to enable functions ssl.FIPSmode() and ssl.FIPSmode_set().

Reference: https://stackoverflow.com/questions/49493537/how-to-implement-fips-mode-and-fips-mode-set-in-python-3-6s-ssl-module.

Step 9 Modify PCbuild/openssl.props as shown below:

Step 10 Open PCbuild/python.props and change entries as shown below:

Step 11 Open Python Solution under PCbuild/pcbuild.sln in VS 2017/2015.

Change the link settings of hashlib and ssl projects under Python as shown below:

Change compile settings hashlib and ssl projects as shown below:

Step 12 Now, build hashlib.pyd and ssl.pyd in VS 2017/2015.

Step 13 Copy these built pyd files to a Python binary installation directory c:\python38\DLLs folder.

Copy ssl.py to c:\python38\Lib folder.

Copy OpenSSL DLLs (libeay32.dll and ssleay32.DLL) to the c:\python38\DLLs folder.

Step 14 Start Python and use these commands to check the OpenSSL/FIPS version.

Voila...now Python 3.8 has OpenSSL with FIPS.

Summary

In this blog, I have covered the following steps in regards to enabling Python 3 with FIPS.

  • Download the required packages.
  • Compile both OpenSSL and FIPS and link them both.
  • Make the required changes to Python source before linking to the new OpenSSL and compile.
  • Copy the newly generated binaries to the installed Python location.
  • Test the version and check if FIPS is enabled.

I hope this blog is useful to the entire developer community!! Make sure you check out other blog posts on HPE DEV for more useful tutorials.

Related

bob.fraser@hpe.com

HPE OneView Python SDK v4.5.0 has been released

Mar 6, 2018
Christopher Pasek

HPE OneView Python SDK now available with support for HPE OneView 5.0

Jan 8, 2020
Anusha Y and Sijeesh Kattumunda

Introducing Python SDK for HPE GreenLake Data Services Cloud Console

Mar 29, 2023
Samarth Deyagond

Refactoring in Python

Jan 30, 2020
BalaSubramanian Vetrivel

Testing OpsRamp APIs with PyTest Fixtures

Jul 26, 2023
Samarth Deyagond

Understanding Concurrency in Python Part 1 - Threading

Feb 10, 2020

HPE Developer Newsletter

Stay in the loop.

Sign up for the HPE Developer Newsletter or visit the Newsletter Archive to see past content.

By clicking on “Subscribe Now”, I agree to HPE sending me personalized email communication about HPE and select HPE-Partner products, services, offers and events. I understand that my email address will be used in accordance with HPE Privacy Statement. You may unsubscribe from receiving HPE and HPE-Partner news and offers at any time by clicking on the Unsubscribe button at the bottom of the newsletter.

For more information on how HPE manages, uses, and protects your personal data please refer to HPE Privacy Statement.