Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to build OpenSSL as unversioned shared lib for Android?

I am trying to build the latest OpenSSL for Android following Compiling the latest OpenSSL for Android. I manage to build the static libs.

However I try to compile the shared libs. To do so I run:

./Configure android-armv7 shared

This compiles. Problem is that this creates a versioned lib like libssl.so.1.0.0, which is not supported by Android. Just rename does not do because of SONAME is still pointing to the versioned filename.

Different problem I have is when trying to the create the libs for old armeabi platform. When I run:

./Configure android shared

it creates the static libs for the old armeabi plattform, the shared libs however are arm-v7 architecture.

like image 851
tmanthey Avatar asked Jun 13 '14 11:06

tmanthey


2 Answers

How to build OpenSSL as unversioned shared lib (for Android)?

There's a lot to it because its a cross compile. You should probably start here (its the OpenSSL wiki): OpenSSL and Android.


However I try to compile the shared libs. To do so I run:

./Configure android-armv7 shared

Ok, so you are missing a few things. At minimum, you should be using the Android NDK. This is a requirement from AOSP. I've seen a number of little problems over the years due to using non-NDK tools.

And I believe you need the following environmental variables set. This is an OpenSSL requirement.

  • x86:

    • export MACHINE=i686
    • export RELEASE=2.6.37
    • export SYSTEM=android
    • export ARCH=x86
    • export CROSS_COMPILE="i686-linux-android-"
  • ARM:

    • export MACHINE=armv7
    • export RELEASE=2.6.37
    • export SYSTEM=android
    • export ARCH=arm
  • Both:

    • export ANDROID_DEV="$ANDROID_NDK_ROOT/platforms/$_ANDROID_API/$_ANDROID_ARCH/usr"
    • export HOSTCC=gcc

ANDROID_DEV will evaluate to something like /opt/android-ndk-r9/platforms/android-14/arch-arm/usr.

You need to provide the output of compiling at least one file. But I expect you are missing --sysroot too. The argument to --sysroot will be something like /opt/android-ndk-r9/platforms/android-14/arch-arm.

I would recommend following the instructions at OpenSSL and Android. The first thing the instructions tell you to do is run setenv-android.sh to set the proper variables.


Here's what my run looks like using OpenSSL and Android.

$ cd openssl-1.0.1h
$ . ./setenv-android.sh 
Error: FIPS_SIG does not specify incore module. Please edit this script.
ANDROID_NDK_ROOT: /opt/android-ndk-r9
ANDROID_EABI: arm-linux-androideabi-4.6
ANDROID_API: android-14
ANDROID_SYSROOT: /opt/android-ndk-r9/platforms/android-14/arch-arm
ANDROID_TOOLCHAIN: /opt/android-ndk-r9/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin
FIPS_SIG: 
CROSS_COMPILE: arm-linux-androideabi-
ANDROID_DEV: /opt/android-ndk-r9/platforms/android-14/arch-arm/usr

$ ./config shared no-ssl2 no-ssl3 no-comp no-engines no-hw no-psk no-srp
Operating system: armv7-whatever-android
Configuring for android-armv7
Configuring for android-armv7
    no-comp         [option]   OPENSSL_NO_COMP (skip dir)
    no-ec_nistp_64_gcc_128 [default]  OPENSSL_NO_EC_NISTP_64_GCC_128 (skip dir)
    no-engines      [option]   OPENSSL_NO_ENGINES (skip dir)
    ...
    no-srp          [option]   OPENSSL_NO_SRP (skip dir)
    no-ssl2         [option]   OPENSSL_NO_SSL2 (skip dir)
    no-ssl3         [option]   OPENSSL_NO_SSL3 (skip dir)
    no-store        [experimental] OPENSSL_NO_STORE (skip dir)
    no-zlib         [default] 
    no-zlib-dynamic [default] 
IsMK1MF=0
CC            =gcc
...

$ make
...
arm-linux-androideabi-gcc -I. -I.. -I../include  -fPIC -DOPENSSL_PIC -DOPENSSL_THREADS
-D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -Wa,--noexecstack -march=armv7-a -mandroid
-mfloat-abi=softfp -I/opt/android-ndk-r9/platforms/android-14/arch-arm/usr/include
-B/opt/android-ndk-r9/platforms/android-14/arch-arm/usr/lib -Os -fomit-frame-pointer
-Wall -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM
-DAES_ASM -DGHASH_ASM   -c -o cryptlib.o cryptlib.c
...

You can ignore Error: FIPS_SIG does not specify incore module... because you are not building a FIPS Capable library.


... unversioned shared lib (for Android)?

This will probably get you in trouble. I believe the way to do it is to provide a wrapper around the static lib, and use your wrapper as a surrogate. So you never use the OpenSSL shared object, and versioning does not matter.

The problem is your process will fork from Zygote. Zygote already has OpenSSL 0.9.8 mapped into its space. So when Zygote forks for your process, your process will already have 0.9.8 and the shared object in your APK will not be mapped in. You will simply use the existing OpenSSL. That will lead to obscure problems.


I also believe there are bugs in OpenSSL's Configure. First, the configuration is missing -mfloat-abi=softfp. That's an AOSP requirement. Second, -O3 is used rather than -Os. That's a mobile requirement on resource constrained devices.

You might want to open Makefile and make the changes after you configure. I do the same before I build the library.

like image 30
jww Avatar answered Nov 13 '22 07:11

jww


As to build a version-less libcrypto, overwriting CALC_VERSIONS does the trick (at least for 1.0.2d):

make CALC_VERSIONS="SHLIB_COMPAT=; SHLIB_SOVER=" all

Then, the sub-target link-shared of the target install_sw must be disabled (otherwise broken symlinks overwrite the libraries), which can be done by creating a dummy file of the same name at the suitable place (furthermore, SHLIB_EXT must also be set for the version-less files to be copied).

The complete bash-script I used:

ORIG_PATH=$PATH
SCRIPT_PATH=$(dirname $(readlink -f $0))

tar -zxf $SCRIPT_PATH/openssl-fips-2.0.10.tar.gz
tar -zxf $SCRIPT_PATH/openssl-1.0.2d.tar.gz

ANDROID_NDK_PATH=<system-specific-path>/android-ndk-r10e-linux
ANDROID_API=android-14
ANDROID_SYSROOT=$ANDROID_NDK_PATH/platforms/$ANDROID_API/arch-arm
export OPENSSLDIR=$SCRIPT_PATH/ssl/android/arm
export FIPSDIR=$OPENSSLDIR/fips-2.0
export HOSTCC=gcc
export FIPS_SIG=$SCRIPT_PATH/openssl-fips-2.0.10/util/incore
export ANDROID_DEV=$ANDROID_SYSROOT/usr
export PATH=$ANDROID_NDK_PATH/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$ORIG_PATH
export MACHINE=armv7
export RELEASE=2.6.37
export SYSTEM=android
export ARCH=arm
export CROSS_COMPILE=arm-linux-androideabi-

cd $SCRIPT_PATH/openssl-fips-2.0.10
./config shared
make clean
make
make install_sw

cd $SCRIPT_PATH/openssl-1.0.2d
./config fips shared -no-sslv2 -no-sslv3 -no-comp -no-hw -no-engines --openssldir=$OPENSSLDIR --with-fipsdir=$FIPSDIR --with-fipslibdir=$FIPSDIR/lib/
make clean
make depend
make CALC_VERSIONS="SHLIB_COMPAT=; SHLIB_SOVER=" MAKE="make -e" all
mkdir -p $OPENSSLDIR/lib
echo "place-holder make target for avoiding symlinks" >> $OPENSSLDIR/lib/link-shared
make SHLIB_EXT=.so install_sw
rm $OPENSSLDIR/lib/link-shared

Then no generated object file should have or reference a versioned so-name:

$ readelf -d ssl/android/arm/lib/libcrypto.so | grep 'SONAME\|NEEDED'
 0x00000001 (NEEDED)                     Shared library: [libdl.so]
 0x00000001 (NEEDED)                     Shared library: [libc.so]
 0x0000000e (SONAME)                     Library soname: [libcrypto.so]
$ readelf -d ssl/android/arm/lib/libssl.so | grep 'SONAME\|NEEDED'
 0x00000001 (NEEDED)                     Shared library: [libcrypto.so]
 0x00000001 (NEEDED)                     Shared library: [libdl.so]
 0x00000001 (NEEDED)                     Shared library: [libc.so]
 0x0000000e (SONAME)                     Library soname: [libssl.so]
$ readelf -d ssl/android/arm/bin/openssl | grep 'SONAME\|NEEDED'
 0x00000001 (NEEDED)                     Shared library: [libssl.so]
 0x00000001 (NEEDED)                     Shared library: [libcrypto.so]
 0x00000001 (NEEDED)                     Shared library: [libdl.so]
 0x00000001 (NEEDED)                     Shared library: [libc.so]
like image 124
Loic Avatar answered Nov 13 '22 07:11

Loic