Use the following commands to build and install the OpenSSL library for Android. Before running the commands download openssl-1.0.1g.tar.gz and setenv-android.sh; place the files in the same directory (the 'root' directory mentioned below); ensure ANDROID_NDK_ROOT is set; and verify setenv-android.sh suites your taste. ANDROID_API and ANDROID_TOOLCHAIN will be set by the setenv-android.sh script. The files can be obtained from http://www.openssl.org/source/, http://openssl.com/fips/2.0/platforms/android/, and below (see Downloads section).

While the Executive Summary provided the whirlwind instructions for building and installing the OpenSSL library, this sections provides detailed instructions. There are six steps to building the OpenSSL Library for use in various projects, and they are listed below. Projects range from simple NDK based command line programs to Android activities using the JNI bridge.

setenv-android.sh is used to set the cross-compilation environment. Open the script an ensure the following match your needs. If you are using android-ndk-r8e, android-14, and ANDROID_NDK_ROOT is set, then the script should be ready to use as-is.

_ANDROID_NDK – the version of the NDK. For example, android-ndk-r8e

_ANDROID_ARCH – the architecture. For example, arch-arm or arch-x86

_ANDROID_EABI – the version of the EABI tools. For example, arm-linux-androideabi-4.6, arm-linux-androideabi-4.8, x86-4.6 or x86-4.8

_ANDROID_API – the API level. For example, android-14 or android-18

You should also set ANDROID_SDK_ROOT and ANDROID_NDK_ROOT. The environmental variables are used internally by the Android platform tools and scripts. For details, see Recommended NDK Directory?.

Additional environmental variables which are set by setenv-android.sh and used by Configure and config include the following. You should not need to change them.

MACHINE – set to armv7

RELEASE – set to 2.6.37

SYSTEM – set to android

ARCH – set to arm

CROSS_COMPILE – set to arm-linux-androideabi-

ANDROID_DEV – set to $ANDROID_NDK_ROOT/platforms/$_ANDROID_API/arch-arm/usr

This section of the document will guide you through the creation of the the OpenSSL Library. The OpenSSL Library (and Makefile.org) needs its install rule modified. The install rule includes the all target, which causes items to be built during install. A bug in the process when running as root results in an empty signature for the shared object (the signature is a string of zeros).

To build the OpenSSL Library, you must issue config, but other options are up to you. Some suggested options for configure include: shared, no-ssl2, no-ssl3, no-comp, no-hw, and no-engine. shared will build and install both the shared object and static archive. You should specify --openssldir to ensure the build system installs the android version of the library in a distinct location (other than /usr/local/ssl).

Begin building the OpenSSL library by setting the cross-compilation environment. Note the leading '.' when running the setenv-android.sh script. If you have any errors from the script, then you should fix them before proceeding.

$ . ./setenv-android.sh
$ cd openssl-1.0.1g/

If you receive a meesage "Error: FIPS_SIG does not specify incore module, please edit this script, then its safe to ignore it. setenv-android.sh is used to build both the FIPS Capable OpenSSL library and the non-FIPS version of the library. FIPS_SIG is not needed in this configuration.

Next, fix the makefile and run configure. A user on Stack Overflow reports this fails under OpenSSL 1.1.0. If so skip it because its not essential to the cross-compile.

Finally, install the library. The makefile's install rule uses both CC and RANLIB, so you will need to fully specify the command variables on the command line (during install, sudo drops the user's path). You must also use sudo's -E option; otherwise ANDROID_TOOLCHAIN will be empty and tools such as arm-linux-androideabi-gcc and arm-linux-androideabi-ranlib will not be found.

Testing the installation consists of building a sample program, installing it with adb, and then running the program using a remote shell. Both the static and dynamic version of the OpenSSL library can be tested. Instructions for testing the OpenSSL library are given at FIPS Library and Android. The same basic steps apply.

Using OpenSSL on Android often involves JNI and the platform's version of OpenSSL or BoringSSL. The platform likely loaded the system's version of libssl.so and libcrypto.so at boot during Zygote initialization. Due to issues with the loader and symbol resolution, customary LD_LIBRARY_PATH tricks do not work for most applications. And changing the build to output different library names, like libmyssl.so and libmycrypto.so, to avoid clashes does not work either.

The solution to the namespace and symbol resolution problems is to wrap the static version of the OpenSSL library in a separate dynamic library or shared object provided by you. To do so, write a small C wrapper library with references to functions you need from the OpenSSL library. You don't need to wrap all the functions.

-fvisibility=hidden works as you expect, and -Wl,--exclude-libs,ALL means your library does not re-export other linked library symbols. Only the functions marked with DLL_PUBLIC will be exported and callable through JNI.

The -Wl,-Bstatic tells the linker to use the static version of the OpenSSL library for the Library. After it and the -Wl,-Bdynamic tells the linker to use dynamic linking for anything else it might need, like libc.

The NDK supplies headers for each major platform - for example, API 18, API 14, API 9, API 8, and API 5. If you are building for Android 4.2 (API 17), Android 4.1 (API 16) and Android 4.0 (API 14), then you would use the NDK's API 14 (android-14 platform).

Specify the full library name when calling Java's System.load. That is, call System.load(“libcrypto.so.1.0.0”). Also note that some Android routines expect the prefix of “lib” and suffix of “so”, so you might have to rename the library.

Some versions of the Android Java system loader will load the system's version of the OpenSSL library, even though you built and included a copy with your application. In this case, you might need to write a wrapper shared object and link to the static version of the OpenSSL library. See, for example, "Unable to find native library" error in Native Activity app.

If you compile with -fPIE and -pie, then you will core dump unless using Android 4.1 and above. Logcat shows the linker (/system/bin/linker) is the problem.

When building the OpenSSL library for Android, take care to specify -mfloat-abi=softfp. If you specify -mfloat-abi=hard or -mhard-float (even if the hardware support a floating point unit), then the entropy estimate passed through the Java VM to RAND_add will always be 0.0f. See Hard-float and JNI for details.

Using -Bstatic and -Bshared can cause link problems on occasion. For example, see Android: error when trying to compile wrapper for openssl library libcrypto.a. To avoid the problem with the linker, specify the full path to the static archive (for example, /usr/local/ssl/android-14/lib/libcrypto.a). If you suspect the wrong OpenSSL library is being linked, then use the fully qualified archive path.