Repository-Metriken
- Stars
- (30.157 Stars)
- PR-Merge-Metriken
- (Keine gemergten PRs in 30 T)
Beschreibung
Bug Report: AES-256-CBC decryption fails on Zhaoxin KX-7000 CPU with OpenSSL 3.5.x
Environment
| Item | Details |
|---|---|
| OS | Debian 13 (Trixie), kernel 6.12.88+deb13-amd64 |
| CPU (broken) | Zhaoxin KaiXian KX-7000 |
| OpenSSL (broken) | 3.5.6 |
| OpenSSL (working, same CPU) | 3.2.4 (UOS V25) |
| Node.js | v22.22.3 |
Description
AES-256-CBC decryption consistently fails with bad decrypt on Zhaoxin KX-7000 CPU when using OpenSSL 3.5.6. The exact same test passes on:
- Zhaoxin KX-7000 + OpenSSL 3.2.4
- Intel Celeron J1900 + OpenSSL 3.5.6
This confirms the bug is a regression specific to Zhaoxin KX-7000's AES-NI implementation triggered by changes introduced between OpenSSL 3.2 and 3.5.
AES-256-GCM works correctly on all tested combinations.
Reproduction
const crypto = require('crypto');
const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);
// Encryption succeeds
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
let encrypted = cipher.update('Hello Pylance!', 'utf8', 'hex');
encrypted += cipher.final('hex');
console.log('Encrypt OK:', encrypted);
// Decryption FAILS on Zhaoxin KX-7000 + OpenSSL 3.5.6
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
try {
decrypted += decipher.final('utf8');
console.log('Decrypt OK:', decrypted);
} catch (e) {
console.log('Decrypt FAILED:', e.code, e.message);
// Error: error:03000064:digital envelope routines::bad decrypt
// at Decipheriv.final (node:internal/crypto/cipher:184:29)
}
Test Results Matrix
| CPU | OpenSSL | AES-256-CBC Encrypt | AES-256-CBC Decrypt | AES-256-GCM |
|---|---|---|---|---|
| Zhaoxin KX-7000 | 3.2.4 | ✅ OK | ✅ OK | ✅ OK |
| Zhaoxin KX-7000 | 3.5.6 | ✅ OK | ❌ FAIL | ✅ OK |
| Intel Celeron J1900 | 3.5.6 | ✅ OK | ✅ OK | ✅ OK |
Key finding: Intel J1900 and Zhaoxin KX-7000 run the same Node.js v22.22.3 + OpenSSL 3.5.6 binary, but only Zhaoxin KX-7000 fails. This rules out any software version difference and points directly to Zhaoxin's AES-NI hardware behavior with the optimized CBC decryption path introduced in OpenSSL 3.3–3.5.
Error Output (Zhaoxin KX-7000 + OpenSSL 3.5.6)
=== 系统信息 ===
Platform: linux x64
CPU: ZHAOXIN KaiXian KX-7000
Node: v22.22.3
OpenSSL: 3.5.6
=== AES-256-CBC ===
Encrypt OK: f0a4ce97fd67763499379c0289e7b919...
FAILED: error:03000064:digital envelope routines::bad decrypt
=== AES-256-GCM ===
Encrypt OK, tag length: 16
Decrypt OK: Pylance cache data with authentication
=== PBKDF2 ===
PBKDF2(10000): 3ms ← works
PBKDF2(100000): 26ms ← works
Reference Output (Intel Celeron J1900 + OpenSSL 3.5.6)
=== 系统信息 ===
Platform: linux x64
CPU: Intel(R) Celeron(R) CPU J1900 @ 1.99GHz
Node: v22.22.3
OpenSSL: 3.5.6
=== AES-256-CBC ===
Encrypt OK: c674f04f87806bde855875ec2522bd04...
Decrypt OK: Hello Pylance! 这是一个测试 ← passes on Intel
=== AES-256-GCM ===
Encrypt OK, tag length: 16
Decrypt OK: Pylance cache data with authentication
Additional Notes
openssl speed -evp aes-256-cbcbenchmark runs without errors on Zhaoxin KX-7000 + OpenSSL 3.5.6, suggesting basic AES-NI instruction execution is functional- Only the EVP
Decipheriv.final()path fails; encryption always succeeds - Failure is 100% reproducible — every single AES-256-CBC decryption attempt fails
- AES-256-GCM on the same hardware + OpenSSL version works perfectly
- Setting
OPENSSL_ia32capto disable hardware AES caused the affected application (VS Code Pylance) to silently fail entirely, suggesting the flag approach is not a viable workaround
CPU Info
model name : ZHAOXIN KaiXian KX-7000
OPENSSL_ia32cap : 0x7ffa73e3afcbffff:0x0040001d201c25ab:0x0000000024000000:0x0000000000000000:0x0000000000000000
Hypothesis
The regression was introduced between OpenSSL 3.2 and 3.5, most likely related to:
- VAES (Vector AES) support added in OpenSSL 3.3
- Optimized CBC decryption scheduling changes in 3.4–3.5
Zhaoxin KX-7000 implements AES-NI but appears to have subtle behavioral differences from Intel/AMD in specific instruction sequences used by the newer CBC decryption path. The fact that GCM works and CBC encrypt works suggests the issue is isolated to the specific VAES/AES-NI instruction sequence used in the CBC decryption path.
Suggested Investigation
- Check if CBC decryption uses a different AES-NI instruction sequence than CBC encryption (e.g.,
AESDECvsAESENCpipelining) - Check VAES (
VAESDEC/VAESDECLAST) usage in the CBC path — Zhaoxin KX-7000's VAES support may have errata - Consider adding a CBC-decrypt self-test to
OPENSSL_cpuid_setup()similar to how some implementations detect RDRAND bugs - A targeted workaround: disable VAES for CBC decrypt specifically when running on Zhaoxin CPUs (detectable via CPUID vendor string
CentaurHauls/Shanghai)
Workaround
Use python:3.13-bookworm (Debian 12, OpenSSL 3.1.x) as the runtime environment. OpenSSL 3.1.x is not affected.