My Avatar

Shilong ZHAO

Libcurl and OpenSSL for Android

2015-07-25 00:00:00 +0200

In case you have any questions or suggestions, you can leave comments HERE . Thanks!

In the previous post Start Android Build Environment we have talked about how to configure the Android build system. If you have not read it and you are not sure what it is, then it’s better that you skim through it before continuing this one.

Background

Suppose there is a project that uses libcurl and OpenSSL to implement protocols based on SSL/TLS, or whatever you can imagine or create. It works well on Linux, and the project now needs to be ported from Linux to Android. Since SSL/TLS is an application layer protocols, those applications/protocols based on it can definitely be implemented in Java:

URL url = new URL("https://www.example.it");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
InputStream stream  = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));

String input;
while((input = reader.readLine()) != null) {
    System.out.println(input);
}

stream.close();

However, this means some part of the project needs to be rewritten in Java, and then integrate with the other components, which is annoying and not so geek.

The alternative is to modify C code and compile them into shared or static libraries and then load these object files by Java Native Interface. And this means that the libraries that your codes are linked against have also to be ported to Android.

Libcurl and OpenSSL

This is what Wikipedia said about libcurl, > libcurl is a free client-side URL transfer library, supporting FTP, FTPS, Gopher, HTTP, HTTPS, SCP, SFTP, TFTP, Telnet, DICT, the file URI scheme, LDAP, LDAPS, IMAP, POP3, SMTP and RTSP.

It is also possible to perform HTTPS GET request with libcurl (example form cURL website ):

#include <stdio.h>
#include <curl/curl.h>

int main(void)
{
  CURL *curl;
  CURLcode res;

  curl_global_init(CURL_GLOBAL_DEFAULT);

  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");

#ifdef SKIP_PEER_VERIFICATION
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
#endif

#ifdef SKIP_HOSTNAME_VERIFICATION
       curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
#endif

    /* Perform the request, res will get the return code */
    res = curl_easy_perform(curl);
    /* Check for errors */
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));

    /* always cleanup */
    curl_easy_cleanup(curl);
  }

  curl_global_cleanup();

  return 0;
}

OpenSSL or other SSL implementations will be needed for libcurl to perform HTTPS properly. This is because libcrypto and libssl must be linked when one builds libcurl with SSL/TLS support.

In computer networking, OpenSSL is an open-source implementation of the SSL and TLS protocols. The core library, written in the C programming language, implements basic cryptographic functions and provides various utility functions.

There is a strong competitive to libcurl named libsoup. However, since libsoup is under the GNOME project, it uses GNOME-related libraries like GLib and GnuTLS, which makes it less portable than libcurl.

There are also other implementations of SSL/TLS other than OpenSSL, like GnuTLS, LibreSSL, BoringSSL. Although OpenSSL is notorious for its mess code and security bugs ( I guess you must have heard of Heartbleed?), it is still the de facto dominant implementation in networking. So we will use it instead of others.

Libcurl and OpenSSL for Android

Go to the Android source root directory and run envsetup.sh:

$ cd path/to/aosp
$ source build/envsetup.sh
$ lunch

Now, the environment is set up. If this is the first time you configure the build environment, it’s also required to run m -j16.

The go to subdirectory external where all third party library modules are located. If there is no directory curl or openssl then download them with git:

$ cd external
$ git clone https://android.googlesource.com/platform/external/curl
$ git clone https://android.googlesource.com/platform/external/openssl

Open openssl/openssl.version and find out which version is supported. For now, it is 1.0.1l. Download the corresponding source archive from official site. And follow the instructions in README.android:

$ cd openssl
$ ./import_openssl.sh import openssl-*.tar.gz
$ ./import_openssl.sh regenerate patches/*.patch
$ m -j16 clean-libcrypto clean-libssl clean-openssl clean-ssltest

Make sure you have an Android phone connected by USB or an emulator running before running the following command from external/openssl directory to make the module and synchronize the compiled object files to directory /system/lib on the device.

$ mm -j16 snod && adb remount && adb sync system

You can check if libssl is correctly installed on the device by using adb

$ adb shell
# ls /system/lib | grep libssl

Modify make file curl\Android.mk to use OpenSSL instead of the default BoringSSL.

$ cd curl
$ vi Android.mk

Find the variable curl_includes which defines the header file paths and change its value as following:

    curl_includes := \
    $(LOCAL_PATH)/include/ \
    $(LOCAL_PATH)/lib \
    external/openssl/include \
    external/zlib/src

Now build the module and upload the object file to the device

$ mm -j16 && adb remount && adb sync

After that, you will be able to to link liburl in your applications by adding into the Android.mk file the following instructions

LOCAL_LDLIBS += -lcurl