Search code examples
androidandroid-ndkopensslandroid-ndk-r7

openSSL using Android's NDK problems


I have the following situation, I am porting a piece of an app using OpenSSL for AES encryption, I have everything compile, but the linker fails. The situation is the following: 1. I wrote a JNI wrapper that simply does :

private native String cipherString(String plainData, int datasize, String password, int passSize);
private native String decipherString(String cipheredData, int datasize, String password, int passSize);

next I have a c++ file which I call that has the proper JNI sintax which translates jstring to char * and all other needed transformations, and makes a call to another cpp file which actually imports openssl headers (present and accounted for) and calls openssl methods for ciphering and deciphering.

So when I call ndk-build, it builds all thumbs, so the compiler compiles them correctly. next i needed to port openssl for android, and I used this OpenSSL for Android which works like a char with a simple ndk-build (in the root of the project, ofcourse) and builds the libssl.so and libcrypto.so

So I need to connect the two.. I find it a challenge to connect the build scripts, so that one ndk-build compiles and linkes everything (I would appreciate a simple example project if someone has the time for it)

so I copied the compiled libssl and libcrypto .so files in jni/includes/prebuilt and want to include them in the project for the linker to be able to finally create the lib which I will use at the end.

I have the following Android.mk file

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/includes/build/common.mk
include $(LOCAL_PATH)/includes/build/common_includes.mk
APP_STL := gnustl_static

LOCAL_MODULE    := packer
LOCAL_SRC_FILES := modules/cipher/wrapper.cpp \
                    ... #rest of the cpp code

LOCAL_C_INCLUDES += $(LOCAL_PATH)/includes/openssl 
LOCAL_SHARED_LIBRARIES := $(LOCAL_PATH)/includes/precompiled/libssl.so \
            $(LOCAL_PATH)/includes/precompiled/libcrypto.so 
LOCAL_SHARED_MODULES := sslx cryptox
include $(BUILD_SHARED_LIBRARY)

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sslx
LOCAL_SRC_FILES := $(LOCAL_PATH)/includes/precompiled/libssh.so
include $(PREBUILT_SHARED_LIBRARY)

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cryptox
LOCAL_SRC_FILES := $(LOCAL_PATH)/includes/precompiled/libssh.so
include $(PREBUILT_SHARED_LIBRARY)

And when calling ndk-build I get a dissapointing

sslx: LOCAL_SRC_FILES points to a missing file. Check that /home/user/Development/Tools/sdk/android/ndk/build/core//home/user/Development/Tools/sdk/android/ndk/build/core/includes/precompiled/libssh.so exists  or that its path is correct. Aborting    .  Stop.

as you can already guess the path is totally wrong, and what confuses me is that ${LOCAL_PATH} returns correct path for the first batch of includes and a completely wrong one for the .so files ... Any help would be really appreciated!


Solution

  • Here is the solution, updated to NDK8c

    step zero: download and fix the Android NDK I dunno how but the ndk has a very interesting flaw, which (in my oppinion) doesn't allow you to compile lot's of stuff, so to be able to compile OpenSSL you need to make a small fix, extract the ndk8c whereever you keep your tools, and then edit the file : android-ndk-r8c/build/gmsl/__gmsl line 512 : change line

    int_encode = $(__gmsl_tr1)$(wordlist 1,$1,$(__gmsl_input_int))
    

    with line

    int_encode = $(__gmsl_tr1)$(wordlist 1,$(words $1),$(__gmsl_input_int))
    

    And you're good to go!

    step one : Download OpenSSL and compile for Android : either compile a ported version found here or Download the official 1.0.0c version of OpenSSL and then compile it for android using the manual provided in the github I linked for the Android compatible version

    So the next step is to get the libssl.so and libcrypto.so and put the them in the NDK folder for easy access, so copy them from

    openssl-folder/libs/armeabi/
    

    to

    android-ndk-r8c/platforms/android-8/arch-arm/usr/lib
    

    this way when compiling you can include the libs using a simple linker switch -lssl -lcrypto

    Step two : get Curl's latest source for here

    Open the file in Docs/INSTALL and follow the steps needed to make the standalone toolchain and put in your desired folder, and then the tricky part, I needed to have android's source code for the config to continue, even though I have a standalone compiled openssl you can include the header files from there too, in anycase this is the more complicated version so you choose what you do, I did not choose to evade them so you can go to Google AOSP site and go trough the steps to build and initialize the environment.

    so it would be something like :

    1.download,

    1. go to root of the source code and run :

      ~: build/envsetup.sh; lunch 1; make;

    So finally we need to compile curl with SSL support, so,

    Step three

    extract curl to the desired folder (I have a specific desire of disabling everything except http/s to keep the library as small as possible meaning about ~300k, if you want more protocols in your lib, remove the --disable-protocol for the desired protocol) run the following :

    make clean
    
    export PATH=/opt/arm-linux-androideabi-4.4.3/bin:$PATH
    
    export LDFLAGS="\
    -lssl \
    -lcrypto \
    -L/home/user/Development/Tools/sdk/android/ndk/platforms/android-8/arch-arm/usr/lib"
    
    export CFLAGS="\
    -I/home/user/Development/AOSP/2.3.7/system/core/include \
    -I/home/user/Development/Tools/sdk/android/ndk/platforms/android-8/arch-arm/usr/include"
    
    ./configure --host=arm-linux-androideabi \
    --with-ssl=/home/user/Development/Projects/portingLibs/openssl-android-master \
    --disable-ftp \
    --disable-gopher \
    --disable-file \
    --disable-imap \
    --disable-ldap \
    --disable-ldaps \
    --disable-pop3 \
    --disable-proxy \
    --disable-rtsp \
    --disable-smtp \
    --disable-telnet \
    --disable-tftp \
    --without-gnutls \
    --without-libidn \
    --without-librtmp \
    --disable-dict
    
    
    make
    
    
    
    Note that in the block above, if you don't want to use the AOSP source, you could switch 
    
    -I/home/user/Development/AOSP/2.3.7/system/core/include \
    
    with the include folder for your ssl distribution.
    

    So finally you have : static :

    curl-7.28.1/lib/.libs/libcurl.a
    

    and shared :

    curl-7.28.1/lib/.libs/libcurl.so.5.3
    

    So that's it.. take the file, and compile away :)