diff --git a/src/frontends/android/openssl/Dockerfile b/src/frontends/android/openssl/Dockerfile new file mode 100644 index 000000000..4b88928c1 --- /dev/null +++ b/src/frontends/android/openssl/Dockerfile @@ -0,0 +1,26 @@ +# Container for building OpenSSL's libcrypto for use in strongSwan's Android app +# +# Use the script to simplify the process of building the image and running +# the compilation in the container, e.g.: +# +# ANDROID_NDK_ROOT=~/android-ndk OPENSSL_SRC=~/openssl ./build.sh + +FROM debian:bullseye + +ARG packages="jq make perl" + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -qq -y \ + --no-install-recommends \ + $packages \ + && rm -rf /var/lib/apt/lists/* + +COPY compile.sh / +RUN chmod +x /compile.sh + +ENV ANDROID_NDK_ROOT /ndk +ENV OUT_DIR /out + +WORKDIR /src + +ENTRYPOINT ["/compile.sh"] diff --git a/src/frontends/android/openssl/build.sh b/src/frontends/android/openssl/build.sh new file mode 100755 index 000000000..fc541efb9 --- /dev/null +++ b/src/frontends/android/openssl/build.sh @@ -0,0 +1,65 @@ +#!/bin/bash +# +# Build OpenSSL's libcrypto for use in strongSwan's Android app. Requires +# passing the path to the Android NDK as well as that to the OpenSSL sources, +# for instance: +# +# ANDROID_NDK_ROOT=~/android-ndk OPENSSL_SRC=~/openssl ./build.sh +# +# The files are written to the jni/openssl directory of the app, by default, but +# that can be changed via $OUT variable. +# +# Setting $NO_DOCKER disables the use of Docker (requires the necessary build +# tools on the system), otherwise, setting $TAG allows using a custom tag for +# the Docker image. +# + +set -e + +if [ -z "${ANDROID_NDK_ROOT}" ]; then + echo "ANDROID_NDK_ROOT is not set" + exit 1 +elif [ ! -d "${ANDROID_NDK_ROOT}" ]; then + echo "ANDROID_NDK_ROOT=${ANDROID_NDK_ROOT} is not a directory" + exit 1 +fi + +if [ -z "${OPENSSL_SRC}" ]; then + echo "OPENSSL_SRC is not set" + exit 1 +elif [ ! -d "${OPENSSL_SRC}" ]; then + echo "OPENSSL_SRC=${OPENSSL_SRC} is not a directory" + exit 1 +fi + +: ${TAG=strongswan-android-openssl-builder} + +DIR=$(dirname `readlink -f $0`) +: ${OUT=$DIR/../app/src/main/jni/openssl} +mkdir -p $OUT + +if [ -z "${NO_DOCKER}" ]; then + docker build -t ${TAG} ${DIR} + docker run --rm -ti \ + -u $(id -u ${USER}):$(id -g ${USER}) \ + -v ${ANDROID_NDK_ROOT}:/ndk \ + -v ${OPENSSL_SRC}:/src \ + -v ${OUT}:/out \ + ${TAG} +else + pushd $OPENSSL_SRC + OUT_DIR=${OUT} $DIR/compile.sh + popd +fi + +if [ ! -f "${OUT}/Android.mk" ]; then + echo "## Creating Android.mk for OpenSSL's libcrypto" + cat << EOF > ${OUT}/Android.mk +LOCAL_PATH := \$(call my-dir) +include \$(CLEAR_VARS) +LOCAL_MODULE := libcrypto_static +LOCAL_SRC_FILES := \$(TARGET_ARCH_ABI)/libcrypto.a +LOCAL_EXPORT_C_INCLUDES := \$(LOCAL_PATH)/include +include \$(PREBUILT_STATIC_LIBRARY) +EOF +fi diff --git a/src/frontends/android/openssl/compile.sh b/src/frontends/android/openssl/compile.sh new file mode 100755 index 000000000..81463b903 --- /dev/null +++ b/src/frontends/android/openssl/compile.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# +# Compile static versions of OpenSSL's libcrypto for use with strongSwan's +# Android app. +# +# Copies archives and header files to $OUT_DIR. + +set -e + +export PATH=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH +# necessary for OpenSSL 1.1.1 +export ANDROID_NDK_HOME=${ANDROID_NDK_ROOT} + +# automatically determine the ABIs supported by the NDK +: ${ABIS=$(jq -r 'keys | join(" ")' ${ANDROID_NDK_ROOT}/meta/abis.json)} + +# this should match APP_PLATFORM +: ${MIN_SDK=21} + +for ABI in ${ABIS} +do + +echo "## Building OpenSSL's libcrypto for ${ABI}" + +case ${ABI} in +armeabi-v7a) + OPTIONS="android-arm" + ;; +arm64-v8a) + OPTIONS="android-arm64" + ;; +x86) + OPTIONS="android-x86" + ;; +x86_64) + OPTIONS="android-x86_64" + ;; +esac + +OPTIONS="${OPTIONS} \ + no-shared no-ct no-cast no-comp no-dgram no-dsa no-gost no-idea \ + no-rmd160 no-seed no-sm2 no-sm3 no-sm4 no-sock no-srp no-srtp \ + no-asm no-err no-engine no-dso no-hw no-stdio no-ui-console \ + -fPIC -DOPENSSL_PIC \ + -ffast-math -O3 -funroll-loops -Wno-macro-redefined \ + -D__ANDROID_API__=${MIN_SDK} \ + " + +make distclean >/dev/null || true + +./Configure ${OPTIONS} +make -j $(nproc) build_generated >/dev/null +make -j $(nproc) libcrypto.a >/dev/null + +mkdir -p ${OUT_DIR}/${ABI} +cp libcrypto.a ${OUT_DIR}/${ABI} + +done + +# The only difference between ABIs is the config header (e.g. configuration.h +# for OpenSSL 3.0), which does define the size of BN_ULONG in bn.h. +# However, the only function we use that depends on it is BN_set_word() when +# generating RSA private keys, which isn't used in the Android app. +cp -R include/ ${OUT_DIR}