如何为Python打包的libcrypto和libssl启用FIPS模式?

2024-02-07

我有一个 python 应用程序,它与 Python 和 Libcrypto 以及 LibSSL 共享对象一起打包。该应用程序是使用 Openssl Fips Module 2.0 构建的。这些共享对象由 Python 的 request 模块和 urllib3 在底层使用来发出 TLS 请求。

我启用了OPENSSL_FIPS在我构建应用程序的环境中标记。现在,如果我想检查共享对象是否启用了 fips 模式,当我将它们从开发环境中取出并放入另一台机器时,我该怎么做?

如何检查 fips 模式是否启用?如果不是,我如何为这些共享对象启用 fips 模式?

可能有帮助的其他详细信息:

OpenSSL 版本:1.0.2h(从源代码构建)

Fips 模块:2.0.12(从源代码构建)

蟒蛇:3.6

操作系统:Ubuntu 16.04 LTS

如果需要任何其他详细信息,请告诉我。

Thanks!


我已经建立了OpenSSL-FIPS使用常规标志的模块(例如:no-asm, shared,一些古老的密码被禁用):

[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049320993]> ~/sopr.sh
### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###

[064bit-prompt]> ls ssl/build/bin ssl/build/lib
ssl/build/bin:
c_rehash  openssl

ssl/build/lib:
engines  libcrypto.a  libcrypto.so  libcrypto.so.1.0.0  libssl.a  libssl.so  libssl.so.1.0.0  pkgconfig

并开始玩弄它:

[064bit-prompt]> ssl/build/bin/openssl version
OpenSSL 1.0.2h-fips  3 May 2016 (Library: OpenSSL 1.0.2g  1 Mar 2016)

请注意“(库:OpenSSL 1.0.2g 2016 年 3 月 1 日)”部分。(存在)表明openssl可执行文件正常(预期版本),但它使用wrong 加密库(这是系统默认安装的 - 在/lib- 通常情况下,它不是用FIPS支持)。
必须加载our库,这是通过设置完成的LD_LIBRARY_PATH(同样的行为也可以通过在构建时设置环境变量来实现OpenSSL这将设定rpath in the openssl可执行文件,但我忘记了,而且我不想再次构建它):

[064bit-prompt]> LD_LIBRARY_PATH=ssl/build/lib ssl/build/bin/openssl version
OpenSSL 1.0.2h-fips  3 May 2016

现在,设置成功了,让我们深入了解一下OPENSSL_FIPS env var:

[064bit-prompt]> LD_LIBRARY_PATH=ssl/build/lib ssl/build/bin/openssl md5 ./code00.py
MD5(./code00.py)= 47fb26ec5d1ca16d3537fe7fd12ea529
[064bit-prompt]> LD_LIBRARY_PATH=ssl/build/lib ssl/build/bin/openssl sha1 ./code00.py
SHA1(./code00.py)= 5188a221ba61309e78e70004285bc6fd148701b6
[064bit-prompt]> OPENSSL_FIPS=1 LD_LIBRARY_PATH=ssl/build/lib ssl/build/bin/openssl sha1 ./code00.py
SHA1(./code00.py)= 5188a221ba61309e78e70004285bc6fd148701b6
[064bit-prompt]> OPENSSL_FIPS=1 LD_LIBRARY_PATH=ssl/build/lib ssl/build/bin/openssl md5 ./code00.py
Error setting digest md5
139778679649944:error:060A80A3:digital envelope routines:FIPS_DIGESTINIT:disabled for fips:fips_md.c:180:

从上面可以看出,md5哈希行为受以下因素影响OPENSSL_FIPS env var (when FIPS模式已打开,不允许使用)。

Notes:

  • 最有可能的是,较新的OpenSSL-FIPS版本还将有sha1禁用,因为它被认为是弱的,所以不变量应该切换到其中之一sha2哈希函数系列(例如sha256)或者甚至更好,sha3 (older OpenSSL版本可能没有它)

  • From my PoV这有点太严格了,因为在某些情况下,可能需要哈希算法来实现不关心安全性的目的,并且仍然必须使用更复杂(并且也耗时)的允许算法

Since OPENSSL_FIPS env var处理于openssl可执行级别,这将被绕过(如加密库会直接使用),对于目前的情况来说没有用,所以我们必须深入。这些是控制的函数FIPS模式在一个loaded 加密库实例:

  • [OpenSSL.Wiki]:FIPS 模式() https://wiki.openssl.org/index.php/FIPS_mode()

  • [OpenSSL.Wiki]:FIPS 模式设置() https://wiki.openssl.org/index.php/FIPS_mode_set()

它们将用于读/写FIPS模式。为了测试是否FIPS模式确实已设置,md5将使用哈希(来自上面的示例)。

代码00.py:

#!/usr/bin/env python


import ctypes as cts
import ssl
import sys


libcrypto = cts.CDLL("libcrypto.so.1.0.0")

#ssleay = libcrypto.SSLeay
#ssleay.argtypes = ()
#ssleay.restype = cts.c_ulong

fips_mode = libcrypto.FIPS_mode
fips_mode.argtypes = ()
fips_mode.restype = cts.c_int

fips_mode_set = libcrypto.FIPS_mode_set
fips_mode_set.argtypes = (cts.c_int,)
fips_mode_set.restype = cts.c_int


def main(*argv):
    text = b""

    print("OPENSSL_VERSION: {:s}".format(ssl.OPENSSL_VERSION))
    enable_fips = len(sys.argv) > 1

    print("FIPS_mode(): {:d}".format(fips_mode()))
    if enable_fips:
        print("FIPS_mode_set(1): {:d}".format(fips_mode_set(1)))
    print("FIPS_mode(): {:d}".format(fips_mode()))
    #print("SSLeay: {:X}".format(ssleay()))

    import hashlib
    print("SHA1: {:s}".format(hashlib.sha1(text).hexdigest()))
    print("MD5: {:s}".format(hashlib.md5(text).hexdigest()))


if __name__ == "__main__":
    print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
                                                   64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print("\nDone.")
    sys.exit(rc)

Notes:

  • Set argtypes and restype对于 2 个函数。查看[SO]:通过 ctypes 从 Python 调用的 C 函数返回不正确的值(@CristiFati 的答案) https://stackoverflow.com/a/58611011/4788546更多细节

  • The md5哈希算法位于Python水平由[Python.Docs]:hashlib - 安全哈希和消息摘要 https://docs.python.org/library/hashlib.html#module-hashlib

  • 重要的: the import hashlib语句位于after设置FIPS模式(而不是在文件开头,因为它应该是),因为hashlib做一些缓存在导入时,所以它捕获了FIPS导入时的值,不关心之后是否改变

Output:

[064bit-prompt]> LD_LIBRARY_PATH=ssl/build/lib ./code00.py
Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 20160609] 064bit on linux

OPENSSL_VERSION: OpenSSL 1.0.2h-fips  3 May 2016
FIPS_mode(): 0
FIPS_mode(): 0
SHA1: da39a3ee5e6b4b0d3255bfef95601890afd80709
MD5: d41d8cd98f00b204e9800998ecf8427e

Done.
[064bit-prompt]> LD_LIBRARY_PATH=ssl/build/lib ./code00.py 1
Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 20160609] 064bit on linux

OPENSSL_VERSION: OpenSSL 1.0.2h-fips  3 May 2016
FIPS_mode(): 0
FIPS_mode_set(1): 1
FIPS_mode(): 1
SHA1: da39a3ee5e6b4b0d3255bfef95601890afd80709
fips_md.c(149): OpenSSL internal error, assertion failed: Digest Final previous FIPS forbidden algorithm error ignored
Aborted (core dumped)

如图所示,设置FIPS模式通过CTypes, really设置它。
我不知道为什么SegFaults,但是md5相关代码仅用于测试目的,因此在生产中不需要它。

我记得在一些Nix版本(可能是RH基于),FIPS还可以通过编辑某些条目(在系统全局范围内)来设置模式/proc?),但我不记得了。

A more elegant approach would be to expose Python wrappers for the 2 functions.
Check [Python.Bugs]: FIPS_mode() and FIPS_mode_set() functions in Python (ssl) https://bugs.python.org/issue27592, I've also submitted a patch for Python 3.4 (where they were exposed by the ssl module), but it was rejected based on the following arguments (out of which the 1st 2 are relevant):

  1. FIPS是一个糟糕的标准

  2. OpenSSL将放弃对其的支持

  3. 它打破了普遍性

您可以将其应用到Python 3.6(我认为这不会起作用OOTB,因为行号很可能发生变化),并且(显然)你必须构建Python从来源。

底线:

  • 有一个big之间的区别FIPS working and FIPS已验证,我确信您已经阅读过[OpenSSL]:OpenSSL FIPS 对象模块 v2.0 用户指南 https://www.openssl.org/docs/fips/UserGuide-2.0.pdf

  • [AskUbuntu]:在 ubuntu 中启用 FIPS 140-2 https://askubuntu.com/q/903127/452474可能还包含一些有用的信息

一些可能有用的参考文献(尽管最后的参考文献可能有点太“深”):

  • [SO]:如何使用 SSL 在 RHEL 上编译 python3? SSL无法导入(@CristiFati的回答) https://stackoverflow.com/a/69670925/4788546

  • [SO]:如何在Python 3.6的ssl模块中实现FIPS_mode()和FIPS_mode_set()? (@CristiFati 的回答) https://stackoverflow.com/a/49494549/4788546

  • [SO]:OpenSSL FIPS_mode_set 无法在 Python 加密库中工作(@CristiFati 的回答) https://stackoverflow.com/a/58311407/4788546

  • [SO]:OpenSSL 3.0.8:FIPS 功能无法与自定义路径中的 libcrypto 库一起使用(@CristiFati 的回答) https://stackoverflow.com/a/75917800/4788546



Update #0

你所遇到的行为让我震惊[SO]:无法使用 Python ctypes 调用 libcrypto.so 的 FIPS_mode_set() [重复] https://stackoverflow.com/q/49381134/4788546也可能与wrong 加密库正在加载(检查openssl version测试有/无LD_LIBRARY_PATH从一开始就)。
A non FIPS有能力的OpenSSL仍然会导出这 2 个函数,但它们都只是返回 0。

[064bit-prompt]> ./code00.py 1
Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 20160609] 064bit on linux

OPENSSL_VERSION: OpenSSL 1.0.2g  1 Mar 2016
FIPS_mode(): 0
FIPS_mode_set(1): 0
FIPS_mode(): 0
SHA1: da39a3ee5e6b4b0d3255bfef95601890afd80709
MD5: d41d8cd98f00b204e9800998ecf8427e

Done.

所以,请确保通过指定加载正确的库LD_LIBRARY_PATH! (还有其他方法,但这是最直接的方法)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何为Python打包的libcrypto和libssl启用FIPS模式? 的相关文章

随机推荐