在 armv7 上使用现有的 openssl 版本交叉编译 mosquitto

Cross compile mosquitto with existing openssl version on armv7

我(到目前为止)未能使用 TLS 为嵌入式 armv7 设备成功交叉编译 mosquitto。没有 TLS,交叉编译工作正常。

嵌入式设备数据:

# cat /proc/cpuinfo
processor       : 0
model name      : ARMv7 Processor rev 2 (v7l)
BogoMIPS        : 548.86
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x3
CPU part        : 0xc08
CPU revision    : 2

Hardware        : Generic AM33XX (Flattened Device Tree)
Revision        : 0000
Serial          : 0000000000000000

# openssl version -a
OpenSSL 1.1.1i  8 Dec 2020
not available
platform: linux-armv4
options:  bn(64,32) rc4(char) des(long) idea(int) blowfish(ptr)
compiler: gcc -fPIC -pthread -Wa,--noexecstack -Wall -O3 -DOPENSSL_USE_NODELETE -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DAES_ASM -DBSAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DPOLY1305_ASM -DNDEBUG -DOPENSSL_TLS_SECURITY_LEVEL=0
OPENSSLDIR: "/usr/ssl"
ENGINESDIR: "/usr/lib/engines-1.1"
Seeding source: random-device ( "/dev/urandom" "/dev/random" "/dev/hwrng" "/dev/srandom" )

我从嵌入式设备经销商那里得到了交叉编译器,并安装在我的机器上:

$ mkdir /opt/advantech
$ cd /opt/advantech
$ git clone https://bitbucket.org/bbsmartworx/Toolchains.git
$ sudo dpkg -i Toolchains/deb/*.deb
### The cross compiler is saved under /opt/toolchain/gcc-conel-armv7-linux-gnueabi

接下来,下载与嵌入式设备 (1.1.1i) 中相同版本的 OpenSSL

$ wget https://www.openssl.org/source/openssl-1.1.1i.tar.gz
$ tar xfz openssl-1.1.1i.tar.gz
$ cd openssl-1.1.1i
$ ./Configure linux-armv4 --cross-compile-prefix=/opt/toolchain/gcc-conel-armv7-linux-gnueabi/bin/armv7-linux-gnueabi- --prefix=/opt/arm/v7/openssl/ --openssldir=/opt/arm/v7/openssl shared
### I have also tried using the options I got when doing "openssl version -a" on the embedded device,
### but the final result is the same..
### ./Configure linux-armv4 --cross-compile-prefix=/opt/toolchain/gcc-conel-armv7-linux-gnueabi/bin/armv7-linux-gnueabi- --prefix=/opt/arm/v7/openssl/ --openssldir=/opt/arm/v7/openssl shared -DOPENSSL_USE_NODELETE -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DAES_ASM -DBSAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DPOLY1305_ASM -DNDEBUG -DOPENSSL_TLS_SECURITY_LEVEL=0 -fPIC -pthread -Wa,--noexecstack -Wall -O3
$ make
$ make install
$ cd /opt/arm/v7/openssl/bin/
$ file openssl
openssl: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 3.12.10, stripped
$ ls -la openssl
-rwxr-xr-x 1 eh eh 554356 Feb 19 09:36 openssl
### The file size on my machine does NOT matches the one on the embedded device:
$ ssh root@embedded-device
# ls -la /usr/bin/openssl
-rwxr-xr-x    1 root     root        535796 Dec 17 10:36 /usr/bin/openssl
# exit
Connection to embedded-device closed.

在交叉编译器的 sysroot 中移动 OpenSSLs 包含和库:

$ cd /opt/toolchain/gcc-conel-armv7-linux-gnueabi/sysroot/usr/lib
$ sudo cp -P /opt/arm/v7/openssl/lib/libcrypto* .
$ sudo cp -P /opt/arm/v7/openssl/lib/libssl* .
$ cd /opt/toolchain/gcc-conel-armv7-linux-gnueabi/sysroot/usr/include
$ sudo cp -r /opt/arm/v7/openssl/include/openssl .

下载mosquitto并交叉编译

$ wget https://mosquitto.org/files/source/mosquitto-2.0.7.tar.gz
$ tar xvfz mosquitto-2.0.7.tar.gz
$ cd mosquitto-2.0.7
$ make CC=/opt/toolchain/gcc-conel-armv7-linux-gnueabi/bin/armv7-linux-gnueabi-gcc CXX=/opt/toolchain/gcc-conel-armv7-linux-gnueabi/bin/armv7-linux-gnueabi-g++ AR=/opt/toolchain/gcc-conel-armv7-linux-gnueabi/bin/armv7-linux-gnueabi-ar LD=/opt/toolchain/gcc-conel-armv7-linux-gnueabi/bin/armv7-linux-gnueabi-ld
$ file src/mosquitto
src/mosquitto: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 3.12.10, stripped
$ file lib/libmosquitto.so.1
lib/libmosquitto.so.1: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, stripped

将交叉编译的 mosquitto 和 lib 传输到嵌入式设备:

$ scp src/mosquitto root@embedded-device:/opt/mosquitto/bin/.
$ scp lib/libmosquitto.so.1 root@embedded-device:/usr/lib/.
$ ssh root@embedded-device
# cd /opt/mosquitto/bin/
# ./mosquitto
./mosquitto: symbol lookup error: ./mosquitto: undefined symbol: ENGINE_load_builtin_engines, version OPENSSL_1_1_0

如前所述,当我将 mosquitto 的 config.mk 修改为不使用 TLS 和 TLS_PSK 时,它在嵌入式设备上正常工作。

config.mk:

WITH_TLS:=yes        # when set to "no", no errors on embedded device
WITH_TLS_PSK:=yes    # when set to "no", no errors on embedded device
WITH_CJSON:=no       # is always set to no

我应该如何交叉编译 OpenSSL 以 100% 匹配嵌入式设备上安装的版本?

无法在嵌入式设备上更改 OpenSSL。

您的目标可能没有专用的加密硬件,因此您的平台上可能没有任何可用的 openssl 加密引擎实现,也没有编译支持加密的 openssl 版本-引擎。

您可以通过执行 ls: /usr/lib/engines-1.1 来检查,因为这是在您执行的 openssl version -a 命令的输出中指定的位置。如果不存在动态库,或者目录不存在,则可能是您的系统不支持当前可用的加密引擎。

在这种情况下,您必须使用 CFLAGS=-DOPENSSL_NO_ENGINE 选项重新构建 mosquitto,这样 mosquitto 就不会尝试加载任何(不存在的)openssl 启动时的加密引擎。