diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 8100a346..b5913f20 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -21,7 +21,6 @@ concurrency: env: NDK_VERSION: r27d - OPENSSL_VERSION: "3.0.15" # native and assemble are the two required checks. Never give either a job-level `if:`, # because a skipped check run counts as success and auto-merge would land on a build that never ran. @@ -51,12 +50,14 @@ jobs: uses: actions/cache@v6 with: path: /tmp/openssl-android - key: openssl-${{ env.OPENSSL_VERSION }}-ndk-${{ env.NDK_VERSION }}-${{ env.ABIS }} + # Key on the recipe itself. Keying on the version alone served a stale + # cache whenever a build flag changed but the version did not. + key: openssl-${{ hashFiles('docker/build-openssl.sh') }}-ndk-${{ env.NDK_VERSION }}-${{ env.ABIS }} - name: Build OpenSSL (cache miss) if: steps.ssl-cache.outputs.cache-hit != 'true' env: ANDROID_NDK_ROOT: ${{ steps.ndk.outputs.ndk-path }} - run: OUT=/tmp/openssl-android OPENSSL_VERSION="${OPENSSL_VERSION}" bash docker/build-openssl.sh + run: OUT=/tmp/openssl-android bash docker/build-openssl.sh - name: Vendor libiconv run: tools/ci/vendor-libiconv.sh - name: Stage OpenSSL statics into prebuild/ diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 5833acdf..f1c667ba 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -23,7 +23,6 @@ concurrency: env: NDK_VERSION: r27d - OPENSSL_VERSION: "3.0.15" jobs: analyze: @@ -62,7 +61,7 @@ jobs: env: ANDROID_NDK_ROOT: ${{ steps.ndk.outputs.ndk-path }} run: | - OUT=/tmp/openssl-android ABIS=arm64-v8a OPENSSL_VERSION="${OPENSSL_VERSION}" bash docker/build-openssl.sh + OUT=/tmp/openssl-android ABIS=arm64-v8a bash docker/build-openssl.sh tools/ci/vendor-libiconv.sh OPENSSL_ANDROID_ROOT=/tmp/openssl-android ABIS=arm64-v8a tools/ci/fetch-openssl-statics.sh ( cd app/src/main && "${ANDROID_NDK_ROOT}/ndk-build" APP_ABI=arm64-v8a APP_PLATFORM=android-24 -j"$(nproc)" ) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 6517a3ed..c0cc1525 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -8,6 +8,10 @@ on: push: branches: [master] paths: ['docker/**', '.github/workflows/docker-image.yml'] + # Build (without publishing) when a PR touches the recipe, so a broken OpenSSL + # build fails the PR instead of the next master push. + pull_request: + paths: ['docker/**', '.github/workflows/docker-image.yml'] schedule: - cron: "23 5 * * 1" # weekly: pick up OpenSSL patch releases workflow_dispatch: @@ -26,6 +30,7 @@ jobs: steps: - uses: actions/checkout@v7 - uses: docker/login-action@v4 + if: github.event_name != 'pull_request' with: registry: ghcr.io username: ${{ github.actor }} @@ -33,16 +38,18 @@ jobs: - uses: docker/build-push-action@v7 with: context: docker - push: true + push: ${{ github.event_name != 'pull_request' }} tags: | ghcr.io/xroche/httrack-android-build:latest ghcr.io/xroche/httrack-android-build:${{ github.sha }} - name: Extract OpenSSL statics (for the container-less emulator job) + if: github.event_name != 'pull_request' run: | id=$(docker create ghcr.io/xroche/httrack-android-build:latest) docker cp "$id":/opt/openssl-android ./openssl-android docker rm "$id" - uses: actions/upload-artifact@v7 + if: github.event_name != 'pull_request' with: name: openssl-android-statics path: openssl-android diff --git a/docker/Dockerfile b/docker/Dockerfile index f724bd67..f1c53e26 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -21,8 +21,8 @@ ARG ANDROID_BUILD_TOOLS=36.0.0 ARG ANDROID_PLATFORM_PREV=android-35 ARG ANDROID_BUILD_TOOLS_PREV=35.0.0 ARG NDK_VERSION=27.3.13750724 -ARG OPENSSL_VERSION=3.0.15 -ARG OPENSSL_SHA256=23c666d0edf20f14249b3d8f0368acaee9ab585b09e1de82107c66e1f3ec9533 +ARG OPENSSL_VERSION=3.5.8 +ARG OPENSSL_SHA256=a8f84a39918ec6415ce765d9b429d313ba97b8143169c172e734b9514464f5b2 ENV ANDROID_SDK_ROOT=/opt/android-sdk \ ANDROID_HOME=/opt/android-sdk \ diff --git a/docker/build-openssl.sh b/docker/build-openssl.sh index 5e51ccf4..c9d7238a 100755 --- a/docker/build-openssl.sh +++ b/docker/build-openssl.sh @@ -13,9 +13,17 @@ # (wget, not curl: curl's threaded resolver fails on this host's Docker/kernel.) set -euo pipefail -OPENSSL_VERSION="${OPENSSL_VERSION:-3.0.15}" +DEFAULT_VERSION=3.5.8 # Pin the hash — verify against https://www.openssl.org/source/ before bumping. -OPENSSL_SHA256="${OPENSSL_SHA256:-23c666d0edf20f14249b3d8f0368acaee9ab585b09e1de82107c66e1f3ec9533}" +DEFAULT_SHA256=a8f84a39918ec6415ce765d9b429d313ba97b8143169c172e734b9514464f5b2 +OPENSSL_VERSION="${OPENSSL_VERSION:-$DEFAULT_VERSION}" +OPENSSL_SHA256="${OPENSSL_SHA256:-$DEFAULT_SHA256}" +# The default hash belongs to the default version, so a version override that +# brings no hash would check one release against another's digest. +if [ "$OPENSSL_VERSION" != "$DEFAULT_VERSION" ] && [ "$OPENSSL_SHA256" = "$DEFAULT_SHA256" ]; then + echo "set OPENSSL_SHA256 when overriding OPENSSL_VERSION" >&2 + exit 1 +fi MIN_API="${MIN_API:-21}" OUT="${OUT:-/opt/openssl-android}" ABIS="${ABIS:-arm64-v8a x86_64}" @@ -46,8 +54,17 @@ for abi in $ABIS; do echo "=== Building OpenSSL ${OPENSSL_VERSION} for ${abi} (${target}) ===" builddir="$work/build-$abi" cp -a "$src" "$builddir" + # Match the branch protection Android.mk gives our own code. The linker ANDs + # .note.gnu.property over every input, so one unmarked member clears it. + # OPENSSL_TLS_SECURITY_LEVEL pins what 3.0.15 shipped. 3.5 defaults to 2, which + # refuses the sub-2048-bit DH groups that old sites still offer. + harden=() + if [ "$abi" = arm64-v8a ]; then + harden=(-mbranch-protection=standard) + fi ( cd "$builddir" - ./Configure "$target" "-D__ANDROID_API__=${MIN_API}" \ + ./Configure "$target" "-D__ANDROID_API__=${MIN_API}" "${harden[@]}" \ + -DOPENSSL_TLS_SECURITY_LEVEL=1 \ no-shared no-tests no-ui-console no-engine no-comp no-dso no-legacy \ --prefix="$OUT/$abi" --libdir=lib make -j"$(nproc)" build_libs