【问题标题】:Calling FINGERPRINT_premain on more c++ compiler/platforms在更多 c++ 编译器/平台上调用 FINGERPRINT_premain
【发布时间】:2015-09-11 00:19:28
【问题描述】:

我正在尝试在 IBM PLinux 上以 FIPS 模式使用静态链接 OpenSSL,并使用 xlC_r 作为编译器/链接器。 fipsld 或 fips_premain.c 不支持此组合。 fipld 将添加链接器选项以在 {OSF1、IRIX、HP-UX、AIX、Darwin} 中的 uname -s 上调用 FINGERPRINT_premain,fips_premain.c 将为 gcc、cl(Microsoft)、cc(SUN) 和一些编译器提供特定的解决方案其他我不熟悉的。不幸的是,IBM PLinux 上的 xlC_r 不在其中任何一个范围内,所以我想知道是否可以将以下代码添加到我的一个 cpp 文件中以进行 FIPS 验证,或者我是否需要将编译器/链接器更改为 gcc 或者是否有另一个方式(链接器选项?)保留 xlC_r。请提供一些理由。

#if defined(PREMAIN_NOT_COVERED)
extern "C" void FINGERPRINT_premain(void);

class FIPSInitializer
{
public:
    FIPSInitializer()
    {
        FINGERPRINT_premain();
    }
    virtual ~FIPSInitializer()
    {
    }
};
extern FIPSInitializer fips_initializer;
FIPSInitializer fips_initializer;
#endif

我也尝试在链接时使用 -Wl,init,FINGERPRINT_premain,但是在使用我们的共享库时我们的测试会出现段错误。

OpenSSL 用户指南: http://www.openssl.org/docs/fips/UserGuide-1.1.1.pdf

OpenSSL 安全策略: http://www.openssl.org/docs/fips/SecurityPolicy-2.0.pdf

【问题讨论】:

    标签: c++ openssl fips


    【解决方案1】:

    所以我想知道是否将以下代码添加到 我的一个 cpp 文件可用于 FIPS 验证

    class FIPSInitializer
    {
    public:
        FIPSInitializer()
        {
            FINGERPRINT_premain();
        }
        virtual ~FIPSInitializer()
        {
        }
    };
    

    嗯……这听起来很奇怪。进入 FIPS 模式的唯一方法是 FIPS_mode_set。如果您调用 FIPS_mode_set 并且它返回非零值,那么您使用的是经过验证的密码术。如果您调用 FIPS_mode_set 并且它失败了,那么您仍然可以加密和解密(认为是“可插拔”架构),但您将不会使用经过验证的加密。详情请见FIPS mode set

    只是推测:如果FIPS_mode_set失败并且FINGERPRINT_premain没有被调用,那么你可能偏离了OpenSSL FIPS 140-2 Security Policy所要求的程序。


    fips_premain.c 将为 gcc、cl(Microsoft)、 cl(Microsoft)、cc(SUN),还有一些我不熟悉的...

    你没有编译fips_premain.c。它是在您构建 FIPS 对象模块或链接到 FIPS 对象模块时编译的。甚至有人说要完全删除它。

    除以下之外的任何内容都会使 FIPS 构建过程无效,并且您将不会使用经过验证的加密。

    $ export OPENSSL_INSTALLDIR=/usr/local/ssl/darwin
    $ cd openssl-fips-2.0.5/
    $ ./config
    $ make
    $ sudo make install
    

    上面的结果是fipscanister.o和朋友。您可以在$OPENSSL_INSTALLDIR\lib 中找到它们(其中有四个):

    $ ls /usr/local/ssl/darwin/lib/
    fipscanister.o              fips_premain.c
    fipscanister.o.sha1         fips_premain.c.sha1
    

    构建并安装 FIPS 对象模块后,您将构建 FIPS 功能库。您可以随意转动 FIPS 功能库的旋钮,只要它不会危及神圣的 fipscanister.o 和朋友。注意使用 fipsconfig

    $ cd openssl-1.0.1e/
    $ ./config fips shared -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine \
      --openssldir=$OPENSSL_INSTALLDIR \
      --with-fipsdir=$OPENSSL_INSTALLDIR \
      --with-fipslibdir=$OPENSSL_INSTALLDIR/lib/
    
    $ make depend
    $ make all
    $ sudo -E make install
    

    您必须使用-E,因为install 也可以构建组件(OpenSSL 可耻)。在安装过程中,我相信共享对象将链接到神圣的fipscanister.o。链接后,模块签名将通过fipsld 嵌入生成的可执行文件中。 fipsld 由 OpenSSL 构建过程使用,并在内部调用一个名为 incore 的程序。 incore 写入实际签名。


    在构建 FIPS 验证的可执行文件或共享对象时,您将执行以下操作:

    $ export CC=`find $OPENSSL_INSTALLDIR -name fipsld`
    $ echo $CC 
    /usr/local/ssl/darwin/bin/fipsld
    $ export FIPSLD_CC=`find /usr/bin -iname gcc`
    $ echo $FIPSLD_CC 
    /usr/bin/gcc
    
    # Now build your project via make (or though the command line):
    $ make
    ...
    

    当您的 makefile 调用 LD 时,它实际上是在调用 OpenSSL 的 fipsldfipsld 将确保您的程序链接到 fipspremain.o,并在内部调用一个名为 incore 的程序。 incore 将实际签名写入您的可执行文件或共享对象。以下来自openssl-fips-2.0.5makefile:

    fips_premain_dso$(EXE_EXT): fips_premain.c
        $(CC) $(CFLAGS) -DFINGERPRINT_PREMAIN_DSO_LOAD -o $@ fips_premain.c \
            $(FIPSLIBDIR)fipscanister.o ../libcrypto.a $(EX_LIBS)
    

    如果您没有安装fipsld,您可以在例如openssl-fips-2.0.5 中找到它。只需将其复制到$OPENSSL_INSTALLDIR\bin。我不记得make install 是否复制了它(我似乎记得提交过关于它的错误报告)。

    您不能在静态库中嵌入签名。 OpenSSL 在构建libcrypto.a 时无法做到,而在构建libmycoolness.a 时则无法做到。如果您将libmycoolness.a 分发给您的客户,他们将不得不跳过CCFIPSLD_CC 箍。


    如果您不想跳过 CCFIPSLD_CC 箍,那么您应该链接到 fipscanister.o 并在构建可执行文件或共享对象后手动运行 incore。然而,OpenSSL 的人不推荐这样做。他们建议使用CCFIPSLD_CC

    注意:你不要自己编译fips_premain.c


    如果fips_premain.c 在尝试构建 FIPS 对象模块时出错,则说明您的平台不受支持。您应该联系 OpenSSL 基金会的 Steve Marquess 并安排一次有关验证平台的讨论。请参阅OpenSSL and FIPS 140-2OpenSSL FIPS 140-2 Security Policy


    相关,如果您因为 C++ 名称修饰而得到未定义的符号,请查看 OpenSSL wiki 上的 Fipsld and C++

    解决办法是修改fipsld。它不是隔离的来源,因此您可以在合理范围内对其进行修改。在这种情况下,fipsld++ 在为您编译 fips_premain.c 时有效地执行以下操作:

    ${CC}  ${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \
        -x c "${PREMAIN_C}" -x none \
        ${_WL_PREMAIN} "$@"
    

    更改实际上是在编译fips_premain.c时添加了${CC} -x c fips_premain.c -x none ...

    【讨论】:

    • 看来你是说我需要使用 gcc 来编译 my_library_with_static_140_2_openssl.so。您能否提供一个指向说明这一点的 FIPS 或 OpenSSL 文档的链接?我知道使用 gcc 会起作用,但我不能以此作为切换编译器的理由。
    • 泰勒 - 我的错。你不需要使用 GCC 来编译你的库。那是您可以转动旋钮的区域。 (我将不得不与 Steve Marquess if 交谈,问题是“我是否必须使用 GCC 编译 OpenSSL FIPS 对象模块”。这个问题在上下文中属于“什么是平台”的灰色区域FIPS 140-2 和软件模块)。
    猜你喜欢
    • 2011-08-24
    • 1970-01-01
    • 2014-09-28
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    相关资源
    最近更新 更多