Skip to content

fix: use native AES-CFB8 for ARM32 processes - #7

Merged
milutinke merged 2 commits into
masterfrom
fix/arm32-native-aes-cfb8
Oct 9, 2026
Merged

milutinke merged 2 commits into
masterfrom
fix/arm32-native-aes-cfb8

Conversation

@milutinke

@milutinke milutinke commented Oct 9, 2026 •

Copy link
Copy Markdown
Member

What changed?

On a 32-bit ARM process, .NET does not expose the ARM AES intrinsics used by UMPK. The existing fallback encrypts a complete AES block in managed code for every CFB8 byte. Select the platform AES-CFB8 provider for Architecture.Arm and process whole buffers through it. Linux uses OpenSSL. Preserve the continuous ciphertext feedback register across calls, including short buffers and in-place decryption, and dispose native cipher resources within each call.

Keep the existing intrinsic/software selection for other architectures and preserve forceSoftware: true. Add 17 regression cases for selection, NIST vectors, fragmented streams, in-place operations, shared feedback, output bounds, and key/IV ownership. The test-count baseline increases by exactly those 17 cases.

Prepare UMPK 0.9.0-beta.5 by updating the shared build version, current install examples, version documentation, bug-report example, and changelog. Historical release entries retain their original versions.

Versions affected

Encrypted Java sessions in ARM32 processes use the new backend. AES-CFB8 is shared across the supported protocols; this change adds no version-specific wire behavior. Live feature tests ran on vanilla 26.1 (775) and 26.2 (776). The ARM32 encrypted traffic check uses vanilla 26.1 (775).

Evidence

  • The supplied ARM32 diagnostics showed receive backlog before the server reset the connection. This PR addresses the cipher bottleneck; it does not establish that AES was the only contributor to that incident.
  • .NET 10 ARM intrinsic implementation selection and Linux AES provider.
  • NIST SP 800-38A, sections F.3.7/F.3.8, supplies the independent AES-128-CFB8 vector.
  • Official server SHA-1 values, checked against Mojang metadata: 26.1 3872a7f07a1a595e651aef8b058dfc2bb3772f46; 26.2 823e2250d24b3ddac457a60c92a6a941943fcd6a.

Validation

Build and full regression validation were rerun on commit 970053f0abf6ea6531f939b11d1f8c08b8859d1a after the version bump. The focused crypto, full formatting, dataset, generated-output, and live-server checks ran on AES commit 9a4b0f0531f6f1c6282cff5680771dced66fc791, against master a2c5e1e. The version commit changes metadata, comments, and documentation. Commands used SDK 10.0.401 at /tmp/mcc-skills-sdk/dotnet, through rtk proxy.

dotnet build UMPK.sln -c Release --no-restore -m:1 -nr:false
dotnet test tests/Umpk.Protocol.Java.Tests/Umpk.Protocol.Java.Tests.csproj -c Release --no-build --no-restore -m:1 -nr:false --filter 'FullyQualifiedName~Crypto'
dotnet test UMPK.sln -c Release --no-build --no-restore -m:1 -nr:false
python3 engineering/testcounts/check_test_counts.py /tmp/umpk-beta5-tests.log --baseline engineering/testcounts/expected_counts.json
dotnet format UMPK.sln --verify-no-changes --no-restore --verbosity quiet
dotnet run --project tools/Umpk.DataGen -c Release --no-build --no-restore -- verify --data data/java
python3 tools/extraction/extract_lang.py --data data/java --downloads /home/anon/Minecraft/Minecraft-Console-Client/MinecraftOfficial/downloads --check
dotnet run --project tools/Umpk.DataGen -c Release --no-build --no-restore -- generate --data data/java --out /tmp/umpk-arm32-pr-generated/data --out-lang /tmp/umpk-arm32-pr-generated/lang --protocol-out /tmp/umpk-arm32-pr-generated/protocol

Build: zero warnings/errors. Focused crypto tests: 45 passed. Full suite: 12,579 passed, 7 skipped, no failures; all 17 suite totals match the baseline. Formatting passed. Dataset and language checks passed for 50 protocols. All 60 regenerated files are byte-identical to the checkout. The seven default skips comprise six opt-in live tests and the citation check requiring decompiled vanilla trees.

Release packaging passed using the shared version without a command-line version override. The verifier checked all 14 primary packages, 13 symbol packages, internal dependency versions, release-note URLs, and package metadata against 0.9.0-beta.5. All 16 source projects' assembly informational versions carry 0.9.0-beta.5 plus commit metadata. Formatting of the changed C# documentation passed after the bump.

dotnet pack UMPK.sln -c Release --no-build --no-restore -m:1 -nr:false -o /tmp/umpk-beta5-packages
python3 engineering/release/verify_packages.py --packages /tmp/umpk-beta5-packages --version 0.9.0-beta.5
dotnet format UMPK.sln --verify-no-changes --no-restore --verbosity quiet --include src/Umpk.Client/UmpkVersion.cs

Real vanilla servers ran sequentially through Umpk.IntegrationTests.LiveServerTests.FullFeatureLeg, with fresh temporary worlds, a 1 GiB heap, loopback port 25599, and /usr/bin/java (OpenJDK 27). Both legs passed chunks/world decoding, movement, chat in both directions, inventory, effects, entity metadata/attack, block placement/digging, chest open/content/server-confirmed quick-move, commands, 60-second keep-alive survival, and disconnect.

UMPK_NIGHTLY=1 UMPK_ORACLE_ROOT=/tmp/umpk-arm32-pr-oracle UMPK_SERVER_ROOT=/tmp/umpk-arm32-pr-oracle/downloads UMPK_JAVA25=/usr/bin/java dotnet test tests/Umpk.IntegrationTests/Umpk.IntegrationTests.csproj -c Release --no-build --no-restore -m:1 -nr:false --filter 'FullyQualifiedName~FullFeatureLeg&DisplayName~26.1' --logger 'console;verbosity=normal'
UMPK_NIGHTLY=1 UMPK_ORACLE_ROOT=/tmp/umpk-arm32-pr-oracle UMPK_SERVER_ROOT=/tmp/umpk-arm32-pr-oracle/downloads UMPK_JAVA25=/usr/bin/java UMPK_LIVE_RESULTS=/tmp/umpk-arm32-pr-live-results.log dotnet test tests/Umpk.IntegrationTests/Umpk.IntegrationTests.csproj -c Release --no-build --no-restore -m:1 -nr:false --filter 'FullyQualifiedName~FullFeatureLeg&DisplayName~26.2' --logger 'console;verbosity=detailed'

An actual self-contained linux-arm process under QEMU selected the native backend automatically and passed the NIST vector, one-byte/in-place feedback checks, and 1 MiB streaming equality checks in both directions. The native path took about 132–138 ms/MiB versus about 9,982–10,005 ms/MiB for the scalar path in that emulator. These are emulated measurements, not physical-device throughput.

The additional encrypted live probe used the PR's ARM32 client binary, synthetic session credentials, an AES-128-CFB8 loopback gateway on port 25620, and a real offline vanilla 26.1 backend on port 25619, started by LocalServer. One run decoded 101 chunks in 9.23 seconds and completed inventory, bidirectional chat, effects, command-tree, movement-send, and server-confirmed digging checks. The intended 80-second survival check did not complete: QEMU aborted with thumb_tr_translate_insn: Assertion '(dc->base.pc_next & 1) == 0' failed. The fault also occurred with QEMU 10.0.13, a different CPU model, and runtime mapping/tiering options. These are incomplete emulator runs, not passing ARM32 live-session results. No production workaround for the emulator was added.

  • Focused tests pass.
  • dotnet build UMPK.sln passes with no warnings.
  • The full test count matches engineering/testcounts/expected_counts.json.
  • dotnet format --verify-no-changes passes.
  • Data and generated files are current.
  • Public API files are current; no public API changes.
  • The change contains no secrets, raw logs, Minecraft artifacts, or unrelated changes.

Notes for reviewers

IsHardwareAccelerated continues to describe UMPK's intrinsic implementation. It returns false for the ARM32 platform provider because OpenSSL's acceleration is not exposed through that property. There are no package dependencies or public API additions. Transport teardown after a failed send is separate follow-up work. Physical ARM32 hardware was unavailable; the full 50-version live matrix was not run.

@milutinke
milutinke merged commit cdf8f1b into master Oct 9, 2026
7 checks passed
@milutinke
milutinke deleted the fix/arm32-native-aes-cfb8 branch October 9, 2026 19:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant