【问题标题】:Why is opensslconf.h different for each architecture?为什么每个架构的 opensslconf.h 都不同?
【发布时间】:2017-06-28 04:33:15
【问题描述】:

我正在编写一个依赖于 OpenSSL 的跨平台 C++ 库,我将其静态链接并与我的库捆绑以方便使用。我想为我的库创建一个 #include 目录,其中显然包含一个“openssl”子目录。

不幸的是,OpenSSL #include 目录的内容因架构和平台而异。因此,例如,iOS 有(至少)三个不同版本的 OpenSSL 头文件。为 TV-OS 支持和模拟器版本添加更多内容。同样的问题在 Windows 和 Android 上存在不同程度。

仔细研究后,唯一在所有平台和架构中通用但不同的文件是“opensslconf.h”,它通常仅相差几行,有时甚至只有一行。

例如,tvOS 版本的“opensslconf.h”包含:

#ifndef OPENSSL_NO_ASYNC
# define OPENSSL_NO_ASYNC
#endif

而 iOS 版本没有。

更常见的区别在于 RC4_INT 的定义:

// 64-bit architectures?
#define RC4_INT unsigned int

// 32-bit architectures?
#define RC4_INT unsigned char

我只想拥有一套适用于所有架构和平台的 OpenSSL #include。我不想为每个架构/平台都复制所有这些文件,尤其是因为有很多变化。

我的第一个问题是我是否可以只拥有一个 OpenSSL #include 目录?如果是这样,我应该选择哪个版本的“opensslconf.h”,我怎么知道它会起作用?

我的第二个问题是为什么这是一个问题。为什么OpenSSL不能封装这些平台差异?它不是已经在跟踪许多其他变量和类型,这些变量和类型会随着您为不同架构构建而发生变化吗?

【问题讨论】:

    标签: c++ ios openssl cross-platform xcode8


    【解决方案1】:

    作为一种解决方法,您可以生成多个版本的opensslconf.h(一个用于您计划支持的每个拱门),将它们称为opensslconf-win.hopensslconf-tvos.h 等。 然后编写一个opensslconf,它只包含基于平台生成的文件:

    #ifdef WIN32
    #include opensslconf-win.h
    #endif
    // and so for every arch
    

    【讨论】:

    • 这是个好主意。事实上,这是我在所有跨平台库中所做的事情。恕我直言,OpenSSL 代码应该已经做的事情。
    【解决方案2】:

    为什么每个架构的 opensslconf.h 都不同?

    opensslconf.h 保存平台特定的配置和安装信息。如您所述,平台配置数据的示例是RC4_INT

    平台配置信息的其他示例包括定义OPENSSL_NO_SSL2 if ./Configure no-ssl2;和OPENSSL_NO_SSL3 如果./Configure no-ssl3。安装信息的示例是 OPENSSLDIR,其中包含 OpenSSL's configuration file openssl.conf 的位置(以及其他位置信息)

    最后一个示例no-ssl2no-ssl3OPENSSLDIR 由用户指定。它们不是针对某个平台而固定的。

    (一个相关问题涉及OPENSSLDIR 在沙盒和围墙花园中的用处,但我从未见过答案。另请参阅 OpenSSL 邮件列表上的CONF-less OpenSSL configuration?)。


    不幸的是,OpenSSL #include 目录的内容因架构和平台而异...经过仔细研究,唯一在所有平台和架构中通用但不同的文件是“opensslconf.h”。

    这并不完全正确。 bn.h 也不同。


    我只想拥有一套适用于所有架构和平台的 OpenSSL #includes...我的第一个问题是是否可以像我想要的那样只拥有一个 OpenSSL #include 目录?如果是这样,我应该选择哪个版本的“opensslconf.h”,我怎么知道它会起作用?

    是的,有可能只有一个 opensslconf.h只有一个 bh.h。但是您必须手动构建它,如果您努力保护感兴趣的定义并准确无误地转录它们,它将起作用。您不能选择一个并期望它适用于所有架构和平台。

    我已使用以下技术在 OS X 和 iOS 上将它们组合为胖库。步骤在Build Multiarch OpenSSL on OS X 有详细说明,但我猜你看看它就知道发生了什么。

    $ cat $HOME/ssl/include/openssl/opensslconf.h
    #ifndef OPENSSL_MULTIARCH_CONF_HEADER
    #define OPENSSL_MULTIARCH_CONF_HEADER
    
    #if __i386 || __i386__
    # include "opensslconf-x86.h"
    #elif __x86_64 || __x86_64__ || __amd64 || __amd64__
    # include "opensslconf-x64.h"
    #else
    # error Unknown architecture
    #endif
    
    #endif /* OPENSSL_MULTIARCH_CONF_HEADER */
    

    和:

    $ cat $HOME/ssl/include/openssl/bn.h
    #ifndef OPENSSL_MULTIARCH_BN_HEADER
    #define OPENSSL_MULTIARCH_BN_HEADER
    
    #if __i386 || __i386__
    # include "bn-x86.h"
    #elif __x86_64 || __x86_64__ || __amd64 || __amd64__
    # include "bn-x64.h"
    #else
    # error Unknown architecture
    #endif
    
    #endif /* OPENSSL_MULTIARCH_BN_HEADER */
    

    我的第二个问题是为什么这是一个问题。为什么OpenSSL不能封装这些平台差异?它不是已经在跟踪许多其他变量和类型,这些变量和类型会随着您为不同架构构建而发生变化吗?

    我从未见过有关该主题的明确答案。也许您应该在 OpenSSL 邮件列表之一上询问,例如 openssl-dev。

    我的猜测是,有太多的平台和配置选项可以将它们全部塞入一个opensslconf.h(和一个bn.h)。这是内置目标的简短列表。 wc -l 告诉我们有 144 个。

    该列表不包括各种配置选项,例如某些处理器的enable-ec_nistp_64_gcc_128(它与 NIST 或 FIPS 无关)。另请参阅 OpenSSL wiki 上的 Compilation and Installation | Configure Options

    $ ./Configure LIST
    Configuring OpenSSL version 1.1.1-dev (0x10101000L)
    BS2000-OSD
    BSD-generic32
    BSD-generic64
    BSD-ia64
    BSD-sparc64
    BSD-sparcv8
    BSD-x86
    BSD-x86-elf
    BSD-x86_64
    Cygwin
    Cygwin-i386
    Cygwin-i486
    Cygwin-i586
    Cygwin-i686
    Cygwin-x86
    Cygwin-x86_64
    DJGPP
    MPE/iX-gcc
    OS390-Unix
    QNX6
    QNX6-i386
    UEFI
    UWIN
    VC-CE
    VC-WIN32
    VC-WIN64A
    VC-WIN64A-masm
    VC-WIN64I
    aix-cc
    aix-gcc
    aix64-cc
    aix64-gcc
    android
    android-armeabi
    android-mips
    android-x86
    android64
    android64-aarch64
    android64-mips64
    android64-x86_64
    bsdi-elf-gcc
    cc
    darwin-i386-cc
    darwin-ppc-cc
    darwin64-debug-test-64-clang
    darwin64-ppc-cc
    darwin64-x86_64-cc
    debug
    debug-erbridge
    debug-linux-ia32-aes
    debug-linux-pentium
    debug-linux-ppro
    debug-test-64-clang
    dist
    gcc
    haiku-x86
    haiku-x86_64
    hpux-ia64-cc
    hpux-ia64-gcc
    hpux-parisc-cc
    hpux-parisc-gcc
    hpux-parisc1_1-cc
    hpux-parisc1_1-gcc
    hpux64-ia64-cc
    hpux64-ia64-gcc
    hpux64-parisc2-cc
    hpux64-parisc2-gcc
    hurd-x86
    ios-cross
    ios64-cross
    iphoneos-cross
    irix-mips3-cc
    irix-mips3-gcc
    irix64-mips4-cc
    irix64-mips4-gcc
    linux-aarch64
    linux-alpha-gcc
    linux-aout
    linux-arm64ilp32
    linux-armv4
    linux-c64xplus
    linux-elf
    linux-generic32
    linux-generic64
    linux-ia64
    linux-mips32
    linux-mips64
    linux-ppc
    linux-ppc64
    linux-ppc64le
    linux-sparcv8
    linux-sparcv9
    linux-x32
    linux-x86
    linux-x86-clang
    linux-x86_64
    linux-x86_64-clang
    linux32-s390x
    linux64-mips64
    linux64-s390x
    linux64-sparcv9
    mingw
    mingw64
    nextstep
    nextstep3.3
    purify
    qnx4
    sco5-cc
    sco5-gcc
    solaris-sparcv7-cc
    solaris-sparcv7-gcc
    solaris-sparcv8-cc
    solaris-sparcv8-gcc
    solaris-sparcv9-cc
    solaris-sparcv9-gcc
    solaris-x86-gcc
    solaris64-sparcv9-cc
    solaris64-sparcv9-gcc
    solaris64-x86_64-cc
    solaris64-x86_64-gcc
    tru64-alpha-cc
    tru64-alpha-gcc
    uClinux-dist
    uClinux-dist64
    unixware-2.0
    unixware-2.1
    unixware-7
    unixware-7-gcc
    vms-alpha
    vms-alpha-p32
    vms-alpha-p64
    vms-ia64
    vms-ia64-p32
    vms-ia64-p64
    vos-gcc
    vxworks-mips
    vxworks-ppc405
    vxworks-ppc60x
    vxworks-ppc750
    vxworks-ppc750-debug
    vxworks-ppc860
    vxworks-ppcgen
    vxworks-simlinux
    

    同样的问题在 Windows 和 Android 上存在不同程度...

    我在想“不是真的”。您无法在这些平台上构建胖库,因此问题并不存在。您仍然需要为特定于平台的库指定特定路径,所以what's the problem with headers?

    我记得在 Linux 中看到过一些关于它的东西(我目前找不到参考资料),但 Android 没有它。


    相关,您可以通过以下方式查看平台和用户配置选项的完整列表:

    $ openssl version -a
    OpenSSL 1.0.2g  1 Mar 2016
    built on: reproducible build, date unspecified
    platform: debian-amd64
    options:  bn(64,64) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx)
    compiler: cc -I. -I.. -I../include  -fPIC -DOPENSSL_PIC -DOPENSSL_THREADS -D_REE
    NTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -m64 -DL_ENDIAN -g -O2 -fstack-protector-stron
    g -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -Wl,-Bsymboli
    c-functions -Wl,-z,relro -Wa,--noexecstack -Wall -DMD32_REG_T=int -DOPENSSL_IA32
    _SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_
    ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIR
    LPOOL_ASM -DGHASH_ASM -DECP_NISTZ256_ASM
    OPENSSLDIR: "/usr/lib/ssl"
    

    【讨论】:

    • 我没有在 'bn.h' 文件中看到跨平台的任何差异,尽管我没有针对所有平台进行编译。
    • @Bungle - 我最后一次检查(OpenSSL 1.0.1 或 1.0.2)时,bn.h 有一些取决于字长的结构。你知道你使用的是什么版本的 OpenSSL?
    • 我正在构建 1.1.0d
    【解决方案3】:

    Alien_AV 给出了答案,但我发布这个是为了跟进一些代码,这些代码只能在答案中正确显示。

    以下是对我有用的解决方案。我仍然认为它应该是 OpenSSL 构建过程的一个组成部分,而不是每个用户都可能需要做的事情。

    它应该很容易实现,因为此文件中没有特定于平台的内容——只需了解所有支持的平台即可。

    #ifndef __OPENSSLCONF_H__
    #define __OPENSSLCONF_H__
    
    // ************************************************ ANDROID
    #if defined(__ANDROID__)
        #if defined (__i386__)
            #include <openssl/opensslconf-android-x86.h>
        #elif defined (__arm__)
            #include <openssl/opensslconf-android-arm.h>
        #elif defined (_MIPS_ARCH)
            // Unsupported
        #endif
    
    // ************************************************ IOS
    // Reference:     http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system
    #elif defined(__APPLE__) && defined(__MACH__)
        #include <TargetConditionals.h>
        #ifdef TARGET_OS_WATCHOS
            // Unsupported
        #elif TARGET_OS_TV
            #if TARGET_OS_SIMULATOR
                #include <openssl/opensslconf-atv-sim64.h>
            #elif
                #include <openssl/opensslconf-atv-arm64.h>
            #endif
        #elif TARGET_OS_IOS
            #if TARGET_OS_SIMULATOR
                #include <openssl/opensslconf-ios-sim32.h>
                #include <openssl/opensslconf-ios-sim64.h>
            #else
                #include <openssl/opensslconf-ios-arm32.h>
                #include <openssl/opensslconf-ios-arm64.h>
            #endif
        #endif
    
    // ************************************************ WINDOWS
    // Reference: https://msdn.microsoft.com/en-us/library/b0084kay(v=vs.120).aspx
    #elif defined(_WIN32)
        #if defined(_M_X64)
            #include <openssl/opensslconf-win64.h>
        #else
            #include <openssl/opensslconf-win32.h>
        #endif
    #endif
    
    #endif // __OPENSSLCONF_H__
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-23
      • 2014-01-30
      • 2016-01-16
      相关资源
      最近更新 更多