QT + OpenSSL + Android

I would like to customize the OpenSSL lib. for my QT project. Works fine on linux with built-in openssl. I added this to my .pro file:

LIBS+=-lcrypto
PKGCONFIG += openssl

      

But if I would like to use in android you get an error. I followed the instructions below:

$ . ./setenv-android.sh
$ cd openssl-1.0.1h/
$ perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org
$ ./config shared -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine --openssldir=/usr/local/ssl/$ANDROID_API
$ make depend
$ ./Configure shared android-armv7
$ make build_libs
$ export CC=/home/laci/android-ndk-r10/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc
$ export AR=/home/laci/android-ndk-r10/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar
$ export ANDROID_DEV=/home/laci/android-ndk-r10/platforms/android-14/arch-arm/usr/
$ make all
$ sudo -E make install CC=$ANDROID_TOOLCHAIN/arm-linux-androideabi-gcc RANLIB=$ANDROID_TOOLCHAIN/arm-linux-androideabi-ranlib

      

These websites were my sources:

What am I doing wrong?

Thanks in advance for your answers

+3


source to share


4 answers


LIES + = - lcrypto

I see two potential problems here. First, you will probably need LIBS += -lssl -lcrypto

.

Secondly, QT, probably uses host OpenSSL (i.e. in the i386 or x86_64 /usr/lib

) rather than the target OpenSSL (i.e., libssl

and libcrypto

in the / usr / local / ssl / android / lib `). To fix this, the easiest way I've found is to provide the full path to the library:



LIBS += /usr/local/ssl/android/lib/libssl.a /usr/local/ssl/android/lib/libcrypto.a

      

You need to avoid using only -lssl -lcrypto

one that refers to a shared object, if available. Android supports OpenSSL 0.9.8. This way you will compile against 1.0.1h at compile time, but link against Androids 0.9.8 at runtime. This will cause a bunch of unexplained errors.

The behavior occurs because the main Android process - Zygote - downloads version 0.9.8 of OpenSSL after it starts. After Zygote turns into your process, 0.9.8 is already downloaded. They won't load your 1.0.1 version because the link dependency is already done.

+1


source


Decision:

1a) correct way: compile openssl libraries for android (use 1.0.2+, don't use 1.1. * - at least for Qt 5.9.2)

or

1b) quick and dirty way: GET THEM FROM any existing APK application (warning: deprecated libs ==> security risk) if you need a quick and dirty solution. Search for libssl.so and libcrypto.so inside the arm APK directory.

THEN



2a) open Qt Creator, Projects -> [project] -> Build and Run -> Android for armeabi-> v7a -> Build -> Build Android APK -> Android -> Additional Libraries -> Add .. (add libssl.so, libcrypto.so is there)

or

2b) in make. make add the following:

ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
     ANDROID_EXTRA_LIBS = \
        $$PWD/android/libs/arm/libcrypto.so \
        $$PWD/android/libs/arm/libssl.so
}

      

($$ PWD / android / .. this is your path inside your project where you put these libraries). ANDROID_PACKAGE_SOURCE_DIR looks like optional for this case.

THEN



3) Add them to load in AndroidManifest (valid at least for Qt 5.9.2): carefully add them here to the existing main activity metadata and out-of-process services, if any.

        <meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --:lib/libssl.so:lib/libcrypto.so"/>

      

"lib" MUST be "lib" here, this refers to the layout of the device directory, not your project structure.

THEN



4) build your apk. Check that your libraries are in the correct location:

$ jar tvf ./android-build/build/outputs/apk/android-build-debug.apk| grep libssl
344388 Tue Apr 11 12:35:36 EEST 2017 lib/armeabi-v7a/libssl.so

      

I put this instruction here because I spent too much time looking for an answer and everything without ANDROID_EXTRA_LIBS did not work for me.

N.B.

Why is this so problematic? As androids up to 6.0 may contain their own libssl / libcrypto, and linking via "-l" will add an autoload entry to your main binary (not Qt-managed), and system libraries may be of the wrong version or load SILENTLY INSTEAD OF YOUR shipped binaries thus masking the bug with Android 7. Android 7 definitely does not contain libssl, and "-l" will fail and characters will not be resolved at runtime.

By not using "-l" and using Qt "android.app.load_local_libs" instead, you force QtLoader to use your lib version. Remember openssl 1.0.2 works with the default android Qt installation and 1.1. * Will NOT work due to different characters. (SSL_init_library - 1.0.2, OPENSSL_init_library - 1.1. *)

Interestingly, due to these complexities, the "1b" "method might not work. The APK you selected might contain libssl.so, but its author built it incorrectly and loaded it incorrectly, so its libssl.so might be the wrong version of the generic a library that generally doesn't work on android, but the author used -l and never loaded a native lib (the system was used instead) and never knew his library would not load on Android.

+3


source


I would like to summarize the solution (this is my subjective opinion):

  • Only openssl 0.9.8za works with Android.
  • Must add libcrypto.a (thankx @jww)

My setenv-android.sh "editable" variables:

_ANDROID_NDK="android-ndk-r10"
_ANDROID_EABI="arm-linux-androideabi-4.8"
_ANDROID_ARCH=arch-arm
_ANDROID_API="android-14"

      

Build process:

$ . ./setenv-android.sh
$ tar xzf openssl-0.9.8za.tar.gz
$ cd openssl-0.9.8za/
$ ./config
$ make

      

.pro file:

# FORMS, SOURCES, TARGET, etc...

unix:!macx: LIBS += -L$$PWD/../SSL/openssl-0.9.8za/ -lcrypto

INCLUDEPATH += $$PWD/../SSL/openssl-0.9.8za/include
DEPENDPATH += $$PWD/../SSL/openssl-0.9.8za/include

unix:!macx: PRE_TARGETDEPS += $$PWD/../SSL/openssl-0.9.8za/libcrypto.a

      

0


source


What worked for me was: edit the openssl Makefile.shared and replace

-soname=$$SHLIB$$SHLIB_SOVER$$SHLIB_SUFFIX

      

from

-soname=$$SHLIB

      

So the internal name of the library will be changed to libcrypto.so and libssl.so instead of libcrypto.so.1.0.0

Clean and recompile openssl and your application.

0


source







All Articles