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

发布于 2021-01-29 17:31:52

我有一个Python应用程序,该应用程序与Python和Libcrypto和LibSSL共享对象打包在一起。该应用程序是使用Openssl Fips
Module 2.0构建的。这些共享对象由Python的请求模块和urllib3用来进行TLS请求。

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

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

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

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

Fips模块:2.0.12(从源构建)

的Python:3.6

操作系统:Ubuntu 16.04 LTS

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

谢谢!

关注者
0
被浏览
44
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    我使用常规标志(例如, no-asmshared ,一些古老的密码被禁用)构建了 OpenSSL-fips 模块:

    [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
    可执行文件是可以的(预期版本),但是它使用了 错误的 libcrypto (这是默认情况下在系统上安装的 libcrypto-
    / lib下 -而且通常不是使用 FIPS 构建的)支持)。
    它必须加载 我们的 库,并且可以通过设置 LD_LIBRARY_PATH 来完成(在构建 OpenSSL 时也可以通过设置一个env
    var来实现相同的行为,而这会在 openssl中 设置 rpath __可执行文件,但我忘了,而且我不想再次构建它):

    [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
    

    ./code.py
    MD5(./code.py)= d41d8cd98f00b204e9800998ecf8427e
    [064bit-prompt]> LD_LIBRARY_PATH=ssl/build/lib ssl/build/bin/openssl
    sha1 ./code.py
    SHA1(./code.py)= da39a3ee5e6b4b0d3255bfef95601890afd80709
    [064bit-prompt]> OPENSSL_FIPS=1 LD_LIBRARY_PATH=ssl/build/lib
    ssl/build/bin/openssl sha1 ./code.py
    SHA1(./code.py)= da39a3ee5e6b4b0d3255bfef95601890afd80709
    [064bit-prompt]> OPENSSL_FIPS=1 LD_LIBRARY_PATH=ssl/build/lib
    ssl/build/bin/openssl md5 ./code.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的影响 (当启用 FIPS 模式时,不允许使用它)。

    注意事项

    • 最可能的是,较新的 openssl-fips 版本也将禁用 sha1, 因为它被认为是弱的,因此应将不变式切换到 sha2 哈希函数家族之一(例如 sha256 ),或者甚至更好的是 sha3 (旧的 OpenSSL 版本可能没有它)
    • 从我的 PoV角度 来看,这有点太严格了,因为在某些情况下,出于不关心安全性的目的而需要使用哈希算法,并且仍然必须使用更复杂(也很耗时)的允许算法

    由于 OPENSSL_FIPS env var 是在 openssl 可执行级别处理的,将被绕过(因为 libcrypto
    将直接使用),因此对于当前情况没有用,所以我们必须更深入。这些是在已 加载的* libcrypto 实例中控制 FIPS 模式的功能:
    *__

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

    code.py

    #!/usr/bin/env python3
    
    
    import sys
    import ssl
    import ctypes
    
    
    libcrypto = ctypes.CDLL("libcrypto.so.1.0.0")
    
    fips_mode = libcrypto.FIPS_mode
    fips_mode.argtypes = []
    fips_mode.restype = ctypes.c_int
    
    fips_mode_set = libcrypto.FIPS_mode_set
    fips_mode_set.argtypes = [ctypes.c_int]
    fips_mode_set.restype = ctypes.c_int
    
    text = b""
    
    
    if __name__ == "__main__":
        print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
        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()))
    
        import hashlib
        print("SHA1: {:s}".format(hashlib.sha1(text).hexdigest()))
        print("MD5: {:s}".format(hashlib.md5(text).hexdigest()))
    

    注意事项

    输出

    [064bit-prompt]> LD_LIBRARY_PATH=ssl/build/lib ./code.py
    Python 3.5.2 (default, Nov 23 2017, 16:37:01)
    [GCC 5.4.0 20160609] on linux
    
    OPENSSL_VERSION: OpenSSL 1.0.2h-fips  3 May 2016
    FIPS_mode(): 0
    FIPS_mode(): 0
    SHA1: da39a3ee5e6b4b0d3255bfef95601890afd80709
    MD5: d41d8cd98f00b204e9800998ecf8427e
    [064bit-prompt]> LD_LIBRARY_PATH=ssl/build/lib ./code.py 1
    Python 3.5.2 (default, Nov 23 2017, 16:37:01)
    [GCC 5.4.0 20160609] 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的真正 设置它。
    我不知道为什么会出现段错误,但是与 md5 相关的代码仅用于测试目的,因此在生产中不需要。

    我记得在某些 Lnx 版本(可能基于 RH )上,也可以通过编辑一些条目(在 / proc 下)来设置 FIPS
    模式(对于系统是全局的),但是我不记得了。 __

    一种 更优雅的方法 是为这两个函数公开 Python 包装器。
    检查
    [Python.Bugs]:Python(ssl)中的FIPS_mode()和FIPS_mode_set()函数
    ,我还提交了 Python 3.4 补丁( ssl 模块公开了它们),但由于以下原因而被拒绝参数(外面的1日2是相关的):

    1. FIPS 是一个不好的标准
    2. OpenSSL 将放弃对此的支持
    3. 它打破了普遍性

    您可以将其应用于 Python 3.6 (由于行号最有可能发生变化,我不认为它会适用于 OOTB ),并且(显然)您必须从源代码构建
    Python

    底线


    更新 #0

    这让我很感动,您在SO上遇到的行为[:无法使用Python
    ctypes duplicate]调用libcrypto.so的FIPS_mode_set()可能也与 错误的
    libcrypto 加载有关
    (请检查openssl version测试是否正确)。WO LD_LIBRARY_PATH 从一开始)。
    FIPS 能够 OpenSSL的 将仍然出口2层的功能,但他们都只是简单地返回0。

    [064bit-prompt]> ./code.py 1
    Python 3.5.2 (default, Nov 23 2017, 16:37:01)
    [GCC 5.4.0 20160609] 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
    

    因此,请确保 通过指定 LD_LIBRARY_PATH 加载正确的库 !(还有其他方法,但这是最简单的方法)。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看