title: How to implement FIPS_mode() and FIPS_mode_set() in Python 3.6's ssl module?
body: <p>I am trying to implement the FIPS_mode and FIPS_mode_set functions in Python's ssl module since those are not present by default. <a href="https://bugs.python.org/issue27592" rel="nofollow noreferrer">A patch</a> for Python 3.4 has already been submitted and rejected due to various using reasons. </p>
  
  <p>Using that patch as an inspiration, i made some modifications and added the following code in <strong>ssl.py</strong>:</p>
  
  <pre><code>try:
      from _ssl import FIPS_mode, FIPS_mode_set
  except ImportError:
      pass
  </code></pre>
  
  <p>And the following code in <strong>_ssl.c</strong>:</p>
  
  <pre><code>#define EXPORT_FIPSMODE_FUNCS
  
  #ifdef EXPORT_FIPSMODE_FUNCS
  
  
  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;
  }
  
  #endif  //EXPORT_FIPSMODE_FUNCS
  
  /* List of functions exported by this module. */
  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_SET_METHODDEF
      _SSL_FIPS_MODE_METHODDEF
      {NULL,                  NULL}            /* Sentinel */
  };
  </code></pre>
  
  <p>This however is throwing the following errors:</p>
  
  <pre><code>./Modules/_ssl.c:5060:5: error: '_SSL_FIPS_MODE_SET_METHODDEF' undeclared here (not in a function)
       _SSL_FIPS_MODE_SET_METHODDEF
  
  ./Modules/_ssl.c:5061:5: error: expected '}' before '_SSL_FIPS_MODE_METHODDEF'
       _SSL_FIPS_MODE_METHODDEF
  
  ./Modules/_ssl.c:4641:1: warning: '_ssl_FIPS_mode_impl' defined but not used [-Wunused-function]  _ssl_FIPS_mode_impl(PyObject
  *module) { 
  
  ./Modules/_ssl.c:4646:1: warning: '_ssl_FIPS_mode_set_impl' defined but not used [-Wunused-function] 
  _ssl_FIPS_mode_set_impl(PyObject *module, int n) {  ^
  </code></pre>
  
  <p>I am pretty sure i am missing something extremely trivial here but i cant seem to figure out what exactly. Any help would be appreciated! Thanks!</p>
  
  <p><strong>Update:</strong> </p>
  
  <p>A big shoutout to <strong>@CristiFati</strong> who pointed out that i was missing the macros which needed to be defined, I was able to solve this. In case someone else needs to implement FIPS Mode in Python 3.6, add the following code:</p>
  
  <p><strong>_ssl.c:</strong></p>
  
  <pre><code>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 */
  }; 
  </code></pre>
  
  <p><strong>_ssl.c.h:</strong></p>
  
  <pre><code>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", &amp;n)) {
          goto exit;
      }
      return_value = _ssl_FIPS_mode_set_impl(module, n);
  
  exit:
      return return_value;
  }
  </code></pre>
  
  <p><strong>ssl.py:</strong></p>
  
  <pre><code>try:
      from _ssl import FIPS_mode, FIPS_mode_set
      print('successful import')
  except ImportError as e:
      print('error in importing')
      print(e)   
  </code></pre>