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

时间:2017-02-09 23:41:58

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

我正在编写一个依赖OpenSSL的跨平台C ++库,我将其静态链接。捆绑我的图书馆,方便消费。我想为我的库提供一个#include目录,这显然包含一个" openssl"子目录。

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

仔细检查后,唯一的文件在所有平台上都很常见但有所不同。架构是" opensslconf.h",它通常只有几行,有时甚至是一行。

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

#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 #includes适用于所有体系结构&平台。我不希望每个档案/平台都包含所有这些文件的副本,特别是因为有很多变化。

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

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

3 个答案:

答案 0 :(得分:2)

作为一种变通方法,您可以生成多个版本的opensslconf.h(每个您计划支持的拱门一个版本),称之为opensslconf-win.hopensslconf-tvos.h等。 然后编写一个opensslconf,其中只包含基于platform的生成文件:

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

答案 1 :(得分:0)

  

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

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

平台配置信息的其他示例包括定义OPENSSL_NO_SSL2 if ./Configure no-ssl2;和OPENSSL_NO_SSL3 if ./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和Windows上存在不同程度的问题。机器人...

我在想“不是真的”。您无法在这些平台上构建胖库,因此问题并不存在。您仍需要为特定于平台的库指定特定路径,因此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"

答案 2 :(得分:0)

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__