Skip to content

Add named groups (supported_groups) to ConnectionSpec for post-quantum key exchange #2

Add named groups (supported_groups) to ConnectionSpec for post-quantum key exchange

Add named groups (supported_groups) to ConnectionSpec for post-quantum key exchange #2

# Post-quantum TLS test for Android: a PQC-only server runs as a Docker container on the runner host
# and the emulator reaches it at 10.0.2.2. Opt-in (heavy: emulator + Docker) via label or manual run.
#
# The emulator setup mirrors the `android` job in build.yml (extracted from testing_ech), including the
# experimental API 37 (16 KB page-size) entry.
name: android-containers
on:
workflow_dispatch:
pull_request:
types: [labeled, synchronize]
permissions:
contents: read
jobs:
android-pqc:
# Only run on manual dispatch or when the PR carries the "android-containers" label.
if: >
github.event_name == 'workflow_dispatch'
|| contains(github.event.pull_request.labels.*.name, 'android-containers')
runs-on: ubuntu-latest
timeout-minutes: 30
continue-on-error: ${{ matrix.experimental || false }}
strategy:
fail-fast: false
matrix:
include:
- api-level: 34
arch: x86_64
target: default
# API 37 only ships 16 KB page-size images; playstore_ps16k resolves to
# google_apis_playstore_ps16k. Quoted so YAML keeps the ".0".
- api-level: "37.0"
arch: x86_64
target: playstore_ps16k
memory: 4096
gpu: -gpu auto
experimental: true
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Configure JDK
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: 21
- name: Enable KVM group perms
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v5
- name: Warm the Gradle cache
run: ./gradlew :android-test:assembleDebugAndroidTest
# OpenSSL >= 3.5 ships native ML-KEM; restrict the server to the PQC hybrid group so a
# successful handshake proves the group was negotiated. Maps container 4433 -> host 8443.
- name: Start post-quantum server
run: |
docker run -d --name pqc-server -p 8443:4433 alpine:3.22 sh -c '
apk add --no-cache openssl &&
openssl req -x509 -newkey rsa:2048 -nodes -days 1 -subj /CN=localhost \
-keyout /key.pem -out /cert.pem &&
openssl s_server -accept 4433 -cert /cert.pem -key /key.pem \
-groups X25519MLKEM768 -tls1_3 -www
'
# Wait for the TLS port to accept connections.
for i in $(seq 1 30); do
if openssl s_client -connect 127.0.0.1:8443 -groups X25519MLKEM768 </dev/null 2>/dev/null | grep -q "BEGIN CERTIFICATE"; then
echo "PQC server ready" && break
fi
sleep 2
done
- name: AVD System Image Cache
uses: actions/cache@v6
id: avd-cache
with:
key: avd-${{ runner.os }}-${{ matrix.api-level }}-${{ matrix.target }}-${{ matrix.arch }}
path: |
~/.android/avd/*
~/.android/adb*
${{ env.ANDROID_HOME }}/system-images/android-${{ matrix.api-level }}
- name: Create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api-level }}
force-avd-creation: false
target: ${{ matrix.target }}
arch: ${{ matrix.arch }}
emulator-boot-timeout: 120
emulator-options: >
-no-window
${{ matrix.gpu || '-gpu swiftshader_indirect' }}
-noaudio
-no-boot-anim
-camera-back none
-memory ${{ matrix.memory || '2048' }}
-feature GLDirectMem,HasSharedSlotsHostMemoryAllocator
disable-animations: true
script: echo "Generated AVD snapshot for caching."
# The emulator reaches the host container at 10.0.2.2; pass the endpoint to the test and run
# only the PQC test class. Boot options must match the snapshot step above.
- name: Run post-quantum Android test
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api-level }}
target: ${{ matrix.target }}
arch: ${{ matrix.arch }}
emulator-boot-timeout: 120
emulator-options: >
-no-window
${{ matrix.gpu || '-gpu swiftshader_indirect' }}
-noaudio
-no-boot-anim
-camera-back none
-memory ${{ matrix.memory || '2048' }}
-feature GLDirectMem,HasSharedSlotsHostMemoryAllocator
script: >
./gradlew -PandroidBuild=true :android-test:connectedCheck
-Pandroid.testInstrumentationRunnerArguments.class=okhttp.android.test.PostQuantumAndroidTest
-Pandroid.testInstrumentationRunnerArguments.pqcServerUrl=https://10.0.2.2:8443/
env:
API_LEVEL: ${{ matrix.api-level }}
- name: Stop post-quantum server
if: always()
run: docker rm -f pqc-server || true