5

I would like to setup the OpenSSL lib. for my Qt project. Under Linux it is working fine with the built-in OpenSSL. I added this to my .pro file:

LIBS+=-lcrypto PKGCONFIG += openssl 

But if I use it in Android, it gives error. I followed this instructions:

$ . ./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

4 Answers 4

5

The solution is:

1a) proper 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 application APK (warning: outdated libs ==> security threat) if you need quick and dirty solution. Look for libssl.so and libcrypto.so inside APK arm directory.

THEN

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

or

2b) in your .pro makefile, 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/.. is your path inside your project where you put these libs). ANDROID_PACKAGE_SOURCE_DIR looks like optional for this case.

THEN

3) Add them for loading into AndroidManifest (valid at least for Qt 5.9.2): carefully add them here in your existing meta-data of main activity 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, it refers on-device directory layout, not your project structure.

THEN

4) build your apk. Verify your libs are in proper place:

$ 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 answer and anything without ANDROID_EXTRA_LIBS did not work for me.

NB

Why it's so problematic? Because androids up to 6.0 may contain their own libssl/libcrypto and linking via "-l" will add auto-load entry in your main binary (not Qt-managed), and system libs may be of wrong version, or load SILENTLY INSTEAD OF YOUR shipped binaries thus masking bug with Android 7. Android 7 definitely does not contain libssl and "-l" will fail and symbols will not be resolved at runtime.

By not using "-l" and by using Qt's "android.app.load_local_libs" instead, you force QtLoader to use your version of libs. Remember, openssl 1.0.2 is working with default android Qt build, and 1.1.* will NOT work because of different symbols. (SSL_init_library is 1.0.2, OPENSSL_init_library is 1.1.*)

Interesting that because of these complexities, method "1b)" may not work. APK you chose may contain libssl.so, but its author built it incorrectly and loads it incorrectly, so his libssl.so may be incorrect versioned shared library which are generally no-go on android, but author used -l and never loaded own lib (used system instead) and never knew his library will not load on android.

Sign up to request clarification or add additional context in comments.

Comments

1

LIBS+=-lcrypto

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

Second, QT is probably using the host's OpenSSL (i.e., i386 or x86_64 in /usr/lib), and not the target's OpenSSL (i.e., libssl and libcrypto in /usr/local/ssl/android/lib`). To fix it, the easiest way I have found is to specify the full path to the library:

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

You have to avoid using just -lssl -lcrypto, which links to a shared object if available. Android carries around OpenSSL 0.9.8. So you will compile against 1.0.1h at compile time, but link against Androids 0.9.8 at runtime. That will cause a bunch of unexplained errors.

The behavior happens because Android's master process - Zygote - loads version 0.9.8 of OpenSSL after it starts. After Zygote forks into your process, 0.9.8 is already loaded. They operating system will not load your version of 1.0.1 because the link dependency is already satisfied.

2 Comments

I get this error message(openssl-1.0.1h): Cannot load library: link_image[1892]: 312 could not load needed library 'libcrypto.so.1.0.0' for 'libOpenSSLGUI.so' (load_library[1094]: Library 'libcrypto.so.1.0.0' not found)
@bastlaca - Your libOpenSSLGUI.so should link against the archive libcrypto.a; and not the shared object libcrypto.so.
0

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

  • Only openssl 0.9.8za working 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" 

The building 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 

Comments

0

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

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

with

-soname=$$SHLIB 

That way the library internal name is changed do libcrypto.so and libssl.so instead of libcrypto.so.1.0.0

Clean and recompile openssl and your app.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.