OpenSSL 1.0.0s aarch64 cross-compilation

Words 2.6k
Views
Visitors

Timeline

Timeline

2026-07-16

init

This article describes the complete process of cross-compiling OpenSSL 1.0.0s using Arm GNU Toolchain 11.2 on an x86_64 host to generate aarch64 shared libraries (.so). It first explains environment preparation, including source selection and cross-toolchain configuration, and points out that OpenSSL 1.0.0 has no dedicated aarch64 target, so a generic 64-bit target must be used and the toolchain prefix specified via environment variables. It then analyzes the Configure parameters in detail, including disabling the IDEA, MD2, MDC2, RC5 algorithms and SSL 2.0/3.0 protocols, and explains the related security considerations. The article focuses on solving a key build problem: because the cross-toolchain ar creates thin archives by default when ARFLAGS is empty, and the AR argument order is wrong, linking fails, so the ARFLAGS and AR definitions in the top-level Makefile, Makefile, and Makefile.shared must all be modified. Finally, it summarizes the compilation, verification, and installation steps, and provides a common problem troubleshooting table. This article is for the ARM64 platform

Objective: On an x86_64 host, useaarch64-none-linux-gnu-the cross-toolchain to compilelibssl.soandlibcrypto.so(ARM aarch64 shared libraries).

1. Environment Preparation

1.1 Source Code

123456
cd ~/repositorywget https://github.com/openssl/openssl/releases/download/OpenSSL_1_0_0s/openssl-1.0.0s.tar.gztar xvf openssl-1.0.0s.tar.gz        # If not yet extractedcd openssl-1.0.0s

If you don’t have to use OpenSSL 1.0.0, OpenSSL 1.1.1 is more recommended, as the code is more robust and compilation is simpler.

123
./Configure linux-aarch64 --cross-compile-prefix=aarch64-none-linux- --prefix=$PWD/_install sharedmake -j$(nproc)

1.2 Cross Toolchain

This article uses Arm GNU Toolchain 11.2-2022.02aarch64-none-linux-gnu-triplet).

ARM has released 8 architectures in total: ARMv1, ARMv2, ARMv3, ARMv4, ARMv5, ARMv6, ARMv7, ARMv8.

For processors supporting the ARMv8 instruction set, you can use-march=armv8-aCompile code with the appropriate parameters; the ARM GNU compiler can be downloaded from the link below.

It is recommended to use the compiler from ARM’s official website. It is portable and can be used after extraction.

This article uses the 11.2 version of the cross-compiler.

You can add it to the environment variables.

123
# ~/.bashrc or ~/.bash_profileemacs ~/.bashrcexport PATH="$HOME/tools/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu/bin:$PATH"

Using version 11.2.1 ofaarch64-none-linux-gnu-gcc

aarch64-none-linux-gnu-gcc
aarch64-none-linux-gnu-gcc

If the toolchain triplet isaarch64-linux-gnu-(e.g., Ubuntu’sgcc-aarch64-linux-gnupackage), replace all the followingaarch64-none-linux-gnu-withaarch64-linux-gnu-That’s all.


2. Configuration (Configure)

OpenSSL 1.0.0 does notlinux-aarch64This target (even if it can be selected on the command line, it will fall back to the host’scc, and the output is x86_64).
The correct approach is to use the generic 64-bit targetlinux-generic64, andEnvironment variablesCROSS_COMPILEspecify the toolchain prefix.

1234567
export CROSS_COMPILE=aarch64-none-linux-gnu-./Configure linux-generic64 shared \  --prefix=$PWD/_install \  --openssldir=$PWD/_install/ssl \  no-idea no-md2 no-mdc2 no-rc5 no-ssl2 no-ssl3 \  -DOPENSSL_NO_HEARTBEATS

⚠️ ImportantCROSS_COMPILEmust use Environment variables pass in.
If written as./Configure ... CROSS_COMPILE=...command-line argument,
the OpenSSL 1.0.0 Configure script will report:
target already defined - linux-generic64 (offending arg: CROSS_COMPILE=...)

After configuration, checkMakefileto confirm cross-compilation is effective:

1
grep -E '^(CC|CROSS_COMPILE|AR)=' Makefile

Expected output:

123
CROSS_COMPILE= aarch64-none-linux-gnu-CC= $(CROSS_COMPILE)gccAR= $(CROSS_COMPILE)ar $(ARFLAGS) r

ifCC= cc(no prefix), indicating that cross-compilation did not take effect; you need to run Configure again.

2.1 Description of Configure parameters

./ConfigureThe full meanings of the parameters are:

ParametersTypeDescription
linux-generic64targetGeneric 64-bit Linux platform. OpenSSL 1.0.0 does not havelinux-aarch64target, so you must use this one
sharedOptionsAlso build shared libraries (.so). If not added, only static libraries are generated (.a
--prefix=$PWD/_installpathmake installthe installation root directory when specified (headers, libraries, certificates, etc.)
--openssldir=$PWD/_install/sslpathThe default directory where OpenSSL looks for certificates/config files at runtime
no-ideaDisable algorithmIDEA symmetric encryption.patented algorithm(patent has expired, but old versions of OpenSSL do not compile it by default); if not specified, it will reportidea.h: No such file
no-md2Disable algorithmMD2 hash. It has been provenextremely insecure(collision was found as early as 1998), so there is no need to keep it
no-mdc2Disable algorithmMDC2 hash. An old algorithm, rarely used.
no-rc5Disable algorithmRC5 symmetric encryption.patented algorithm(has expired), not compiled by default
no-ssl2Disabled protocolsSSL 2.0。Deprecated and insecure(Deprecated by RFC 6176 due to attacks such as POODLE)
no-ssl3Disabled protocolsSSL 3.0。Deprecated and insecure(Deprecated by RFC 7568 due to the POODLE attack)
-DOPENSSL_NO_HEARTBEATSCompile-time macroDisable the TLS Heartbeat extension.Heartbleed vulnerabilitythe root cause of (CVE-2014-0160)

Aboutno-xxx(Disabled algorithms/protocols)

OpenSSL’s./Configureacceptanceno-<feature>Beforecompile-time removalof unneeded algorithms, effect:

  • Reduce size: disabled algorithms will not be compiled into.so, the library file is smaller
  • Avoid patents: IDEA and RC5 were once patented algorithms (patents have expired, but older versions still require explicit enabling)
  • Eliminate security risks: MD2/SSL2/SSL3 have been proven insecure, no need to keep them

Recommendation: If you are not sure which algorithms are needed,adding all of them is the safest— can significantly reduce the compiled output size and eliminate known security-risk algorithms.

If your project really needs a certain algorithm (for example, legacy devices that must support SSL3), remove the correspondingno-xxxThat’s all.

About-DOPENSSL_NO_HEARTBEATS(compile macro)

OpenSSL 1.0.0 itself does not support Heartbeat(Heartbeat was introduced in 1.0.1), so this macro on 1.0.0 isredundant.
But including it is harmless, and if you ever switch to 1.0.1+ it will automatically protect against Heartbleed.

Minimal configuration (without disabling any algorithms)

If you don’t want to disable any algorithms, you can take this line:

12345
./Configure linux-generic64 shared \  --prefix=$PWD/_install \  --openssldir=$PWD/_install/ssl \  no-idea no-md2 no-mdc2 no-rc5 no-ssl2 no-ssl3 \  -DOPENSSL_NO_HEARTBEATS

simplify it to:

123
./Configure linux-generic64 shared \  --prefix=$PWD/_install \  --openssldir=$PWD/_install/ssl

Configure will automatically try to compile all algorithms and skip any that fail to compile. Only when youneed to reduce the sizeorexplicitly disable certain algorithmsshould you add itno-xxx


3. Modify the Makefile (critical fix)

ConfigureThe generatedMakefilein,ARFLAGSis empty by default, andARthe definition order has a problem:

12
ARFLAGS=                  # ← emptyAR= $(CROSS_COMPILE)ar $(ARFLAGS) r

The two problems together cause the build to fail

  1. Thin archive problem: of some versions of the cross toolchain (including the Arm GNU Toolchain 11.2 used in this article)arBeforeARFLAGSWhen empty, create by default.thin archive(thin archive) — the archive only stores the symbol table, without embedding.ofile contents. When linking,ldreading members will fail:
1
ld: libcrypto.a: member libcrypto.a(cryptlib.o) in archive is not an object
  1. AR argument order issuearthe syntax isar [-]X[MOPTS] archive [members], the operator (r) must be immediately adjacent toaror placed beforeMOPTSin front. Incorrect orderar c rARFLAGS=cbut when the order is not corrected) will causearholdrbe treated as the archive filename.

Fix: changeARFLAGStoc(create), andARin the definitionrandARFLAGSswap the order.

⚠️ Important: OpenSSL 1.0.0 has 3 Makefiles need to be changed (top-level,crypto/ssl/), becausecrypto/Makefileandssl/Makefileeach has its own independentARdefinition, and hardcodedar r(no$(CROSS_COMPILE)prefix). The top-level Makefile passesmake -ebiographyARenvironment variables, but in the sub-MakefileARthe definition has higher priority.

123456789
# top-level Makefilesed -i 's/^ARFLAGS= $/ARFLAGS=c/' Makefilesed -i 's/^AR= $(CROSS_COMPILE)ar $(ARFLAGS) r$/AR= $(CROSS_COMPILE)ar r$(ARFLAGS)/' Makefile# crypto/Makefile (note the line starts with a tab)sed -i 's|^AR=		ar r|AR=		$(CROSS_COMPILE)ar r$(ARFLAGS)|' crypto/Makefile# ssl/Makefile (note the line starts with a tab)sed -i 's|^AR=		ar r|AR=		$(CROSS_COMPILE)ar r$(ARFLAGS)|' ssl/Makefile

After making changes, verify:

1
grep -E '^ARFLAGS|^AR=' Makefile crypto/Makefile ssl/Makefile

Expected output:

1234
Makefile:      ARFLAGS=cMakefile:      AR= $(CROSS_COMPILE)ar r$(ARFLAGS)crypto/Makefile: AR=		$(CROSS_COMPILE)ar r$(ARFLAGS)ssl/Makefile:    AR=		$(CROSS_COMPILE)ar r$(ARFLAGS)

Actual call after expansion:aarch64-none-linux-gnu-ar rc ../../libcrypto.a *.o— the correct fat archive format.

Principle

  • arMeaning of the mode letters in the command:

    • r: replace/insert member (operation)

    • c: create archive (if it does not exist) (modifier)

    • s: write symbol index (equivalent to runningranlib

  • GNU ar syntax:ar [-]X[MOPTS] archive [members]

    • X = operation(r/d/m/p/q/t/x)

    • MOPTS = modifiers(c/v/w/…)

Incorrectar $(ARFLAGS) r(when ARFLAGS=c it becomesar c r) will makearholdras the archive name. The correct way isar r$(ARFLAGS)ar rc


4. Compile (directly make)

12
make depend   # Must run first, because ./Configure changed the algorithm switchesmake # Cannot make -j$(nproc)

After compilation completes, you will get:

1234
libcrypto.so -> libcrypto.so.1.0.0   (符号链接)libcrypto.so.1.0.0                  (2.1 MB, ELF aarch64)libssl.so -> libssl.so.1.0.0        (符号链接)libssl.so.1.0.0                     (387 KB, ELF aarch64)

5. Verify the artifacts

123456789101112131415161718
# File typefile libcrypto.so libssl.so# Expected: ELF 64-bit LSB shared object, ARM aarch64, ...# Size (libcrypto ≈ 2.1 MB, libssl ≈ 387 KB)ls -lh libcrypto.so libssl.so# Exported symbolsaarch64-none-linux-gnu-nm -D libcrypto.so | grep -E 'SSLeay|RAND_bytes|AES_set_encrypt_key'aarch64-none-linux-gnu-nm -D libssl.so    | grep -E 'SSL_library_init|TLSv1_method|DTLSv1_method'# ELF headeraarch64-none-linux-gnu-readelf -h libcrypto.so | grep -E 'Class|Machine|Type'# Expected: Class: ELF64 / Machine: AArch64 / Type: DYN (Shared object file)# libssl.so should depend on libcrypto.soaarch64-none-linux-gnu-readelf -d libssl.so | grep NEEDED# Expected: NEEDED  Shared library: [libcrypto.so.1.0.0]

6. Installation

12
export INSTALLDIR=$HOME/repository/openssl-1.0.0s/_installmake install

Final directory structure:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
_install├── bin│   ├── c_rehash│   └── openssl├── include│   └── openssl│       ├── aes.h│       ├── asn1.h│       ├── asn1_mac.h│       ├── asn1t.h│       ├── bio.h│       ├── blowfish.h│       ├── bn.h│       ├── buffer.h│       ├── camellia.h│       ├── cast.h│       ├── cms.h│       ├── comp.h│       ├── conf.h│       ├── conf_api.h│       ├── crypto.h│       ├── des.h│       ├── des_old.h│       ├── dh.h│       ├── dsa.h│       ├── dso.h│       ├── dtls1.h│       ├── e_os2.h│       ├── ebcdic.h│       ├── ec.h│       ├── ecdh.h│       ├── ecdsa.h│       ├── engine.h│       ├── err.h│       ├── evp.h│       ├── hmac.h│       ├── krb5_asn.h│       ├── kssl.h│       ├── lhash.h│       ├── md4.h│       ├── md5.h│       ├── modes.h│       ├── obj_mac.h│       ├── objects.h│       ├── ocsp.h│       ├── opensslconf.h│       ├── opensslv.h│       ├── ossl_typ.h│       ├── pem.h│       ├── pem2.h│       ├── pkcs12.h│       ├── pkcs7.h│       ├── pqueue.h│       ├── rand.h│       ├── rc2.h│       ├── rc4.h│       ├── ripemd.h│       ├── rsa.h│       ├── safestack.h│       ├── seed.h│       ├── sha.h│       ├── ssl.h│       ├── ssl2.h│       ├── ssl23.h│       ├── ssl3.h│       ├── stack.h│       ├── symhacks.h│       ├── tls1.h│       ├── ts.h│       ├── txt_db.h│       ├── ui.h│       ├── ui_compat.h│       ├── whrlpool.h│       ├── x509.h│       ├── x509_vfy.h│       └── x509v3.h├── lib│   ├── engines│   │   ├── lib4758cca.so│   │   ├── libaep.so│   │   ├── libatalla.so│   │   ├── libcapi.so│   │   ├── libchil.so│   │   ├── libcswift.so│   │   ├── libgmp.so│   │   ├── libgost.so│   │   ├── libnuron.so│   │   ├── libpadlock.so│   │   ├── libsureware.so│   │   └── libubsec.so│   ├── libcrypto.a│   ├── libcrypto.so -> libcrypto.so.1.0.0│   ├── libcrypto.so.1.0.0│   ├── libssl.a│   ├── libssl.so -> libssl.so.1.0.0│   ├── libssl.so.1.0.0│   └── pkgconfig│       ├── libcrypto.pc│       ├── libssl.pc│       └── openssl.pc│...............................

7. One-click script

Save the following content asbuild-openssl-aarch64.sh, and place it inopenssl-1.0.0s/the same directory as:

123456789101112131415161718192021222324252627282930313233343536373839
#!/usr/bin/env bashset -euo pipefail# ============ Configuration ============# Toolchain path (modify according to your environment)CROSS=${CROSS:-/home/zhaohang/tools/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu/bin}CROSS_COMPILE=${CROSS_COMPILE:-aarch64-none-linux-gnu-}# ==============================SRCDIR=$(cd "$(dirname "$0")/openssl-1.0.0s" && pwd)INSTALLDIR="$SRCDIR/_install"export PATH="$CROSS:$PATH"export CROSS_COMPILEcd "$SRCDIR"# Configuration./Configure linux-generic64 shared \  --prefix="$INSTALLDIR" \  --openssldir="$INSTALLDIR/ssl" \  no-idea no-md2 no-mdc2 no-rc5 no-ssl2 no-ssl3 \  -DOPENSSL_NO_HEARTBEATS# ★ Key fix: force ar to generate a fat archive (fixes two issues: thin archive + AR argument order)#    Need to modify 3 Makefiles: top-level, crypto/, ssl/sed -i 's/^ARFLAGS= $/ARFLAGS=c/' Makefilesed -i 's/^AR= $(CROSS_COMPILE)ar $(ARFLAGS) r$/AR= $(CROSS_COMPILE)ar r$(ARFLAGS)/' Makefilesed -i 's|^AR=		ar r|AR=		$(CROSS_COMPILE)ar r$(ARFLAGS)|' crypto/Makefilesed -i 's|^AR=		ar r|AR=		$(CROSS_COMPILE)ar r$(ARFLAGS)|' ssl/Makefile# Compilationmake dependmake -j1 # Can only compile with make -j1# Installmake installecho "=== 构建完成 ==="
12
chmod +x build-openssl-aarch64.sh./build-openssl-aarch64.sh

8. Troubleshooting common issues

SymptomReasonFix
Configure: target already definedCROSS_COMPILEWritten as command-line argumentsUse insteadexport CROSS_COMPILE=...Environment variables
CC= cc(no prefix)usedlinux-aarch64nonexistent targets, etc.Use insteadlinux-generic64
ld: member ... in archive is not an objectcross ar to generate thin archivesModify ARFLAGS/AR in the 3 Makefiles (see Section 3)
ar: two different operation options specifiedARFLAGS containsr(with the one in the AR definitionrduplicate)ARFLAGS should only bec, cannot berc
ar: creating rorar: r: No such fileAR argument order error (ar $(ARFLAGS) rsed -i 's/AR=...ar $(ARFLAGS) r$/AR=...ar r$(ARFLAGS)/' Makefile
Changed the top-level Makefile but the archive is still thincrypto/Makefileandssl/Makefilehas a separate AR definitionModify the 3 Makefiles simultaneously
.soonly a few KBmissing at link time--whole-archive(very rare, built into the Makefile)Check Makefile.shared’sALLSYMSFLAGS
compilation reportsopenssl/idea.h: No such filedid not addno-ideaadd during Configureno-idea no-mdc2 no-rc5
make cleanreportsrm -f install/libinstall/directory already exists and is non-emptymanuallyrm -rf installor ignore this error

9. Summary: Four steps to produce .so

12345678910111213141516171819202122
# 1. Configurationexport PATH=/home/zhaohang/tools/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu/bin:$PATHexport CROSS_COMPILE=aarch64-none-linux-gnu-# 2. Configure./Configure linux-generic64 shared --prefix=$PWD/_install \  no-idea no-md2 no-mdc2 no-rc5 no-ssl2 no-ssl3 -DOPENSSL_NO_HEARTBEATS# 3. Modify AR definitions in 3 Makefiles (fix thin archive + AR argument order)sed -i 's/^ARFLAGS= $/ARFLAGS=c/' Makefilesed -i 's/^AR= $(CROSS_COMPILE)ar $(ARFLAGS) r$/AR= $(CROSS_COMPILE)ar r$(ARFLAGS)/' Makefilesed -i 's|^AR=		ar r|AR=		$(CROSS_COMPILE)ar r$(ARFLAGS)|' crypto/Makefilesed -i 's|^AR=		ar r|AR=		$(CROSS_COMPILE)ar r$(ARFLAGS)|' ssl/Makefile# 4. Compilemake depend && make -j1# 5. Installmake install# 6. Verifyfile libcrypto.so libssl.so
Loading comments…