constant-time-analysis
💡 摘要
一个用于检测多种语言和架构下已编译加密代码中时序侧信道漏洞的便携式工具。
🎯 适合人群
🤖 AI 吐槽: “这是一把寻找时序泄漏的瑞士军刀,但你需要一个编译器工具链的博士学位来设置所有的语言后端。”
该工具分析不受信任的代码,需要执行编译器和语言运行时(如node、php、python)。如果分析的代码是恶意的,这会引入供应链和本地执行风险。缓解措施:在无网络访问的沙盒化临时容器中运行分析器。
Constant-Time Analyzer (ct-analyzer)
A portable tool for detecting timing side-channel vulnerabilities in compiled cryptographic code. Analyzes assembly output from multiple compilers and architectures to detect instructions that could leak secret data through execution timing.
Background
Timing side-channel attacks exploit variations in execution time to extract secret information from cryptographic implementations. Common sources include:
- Hardware division (
DIV,IDIV): Execution time varies based on operand values - Floating-point operations (
FDIV,FSQRT): Variable latency based on inputs - Conditional branches: Different execution paths have different timing
The infamous KyberSlash attack demonstrated how division instructions in post-quantum cryptographic implementations could be exploited to recover secret keys.
Features
- Multi-language support: C, C++, Go, Rust, PHP, JavaScript, TypeScript, Python, Ruby
- Multi-architecture support: x86_64, ARM64, ARM, RISC-V, PowerPC, s390x, i386
- Multi-compiler support: GCC, Clang, Go compiler, Rustc
- Scripting language support: PHP (VLD/opcache), JavaScript/TypeScript (V8 bytecode), Python (dis), Ruby (YARV)
- Optimization-level testing: Test across O0-O3, Os, Oz
- Multiple output formats: Text, JSON, GitHub Actions annotations
- Cross-compilation: Analyze code for different target architectures
Quick Start
# Install uv pip install -e . # Analyze a C file ct-analyzer crypto.c
Usage
Basic Analysis
ct-analyzer <source_file>
Options
| Option | Description |
|--------|-------------|
| --arch, -a | Target architecture (x86_64, arm64, arm, riscv64, ppc64le, s390x, i386) |
| --compiler, -c | Compiler to use (gcc, clang, go, rustc) |
| --opt-level, -O | Optimization level (O0, O1, O2, O3, Os, Oz) - default: O2 |
| --warnings, -w | Include conditional branch warnings |
| --func, -f | Regex pattern to filter functions |
| --json | Output JSON format |
| --github | Output GitHub Actions annotations |
| --list-arch | List supported architectures |
Examples
# Test with different optimization levels ct-analyzer --opt-level O0 crypto.c ct-analyzer --opt-level O3 crypto.c # Cross-compile for ARM64 ct-analyzer --arch arm64 crypto.c # Include conditional branch warnings ct-analyzer --warnings crypto.c # Analyze specific functions ct-analyzer --func 'decompose|sign' crypto.c # JSON output for CI ct-analyzer --json crypto.c # Analyze Go code ct-analyzer crypto.go # Analyze Rust code ct-analyzer crypto.rs # Analyze PHP code (requires PHP with VLD extension or opcache) ct-analyzer crypto.php # Analyze TypeScript (transpiles to JS first) ct-analyzer crypto.ts # Analyze JavaScript (uses V8 bytecode analysis) ct-analyzer crypto.js # Analyze Python (uses dis module for bytecode disassembly) ct-analyzer crypto.py # Analyze Ruby (uses YARV instruction dump) ct-analyzer crypto.rb
Detected Vulnerabilities
Error-Level (Must Fix)
| Category | x86_64 | ARM64 | RISC-V | |----------|--------|-------|--------| | Integer Division | DIV, IDIV, DIVQ, IDIVQ | UDIV, SDIV | DIV, DIVU, REM, REMU | | FP Division | DIVSS, DIVSD, DIVPS, DIVPD | FDIV | FDIV.S, FDIV.D | | Square Root | SQRTSS, SQRTSD, SQRTPS, SQRTPD | FSQRT | FSQRT.S, FSQRT.D |
Warning-Level (Review Needed)
Conditional branches that may leak timing if condition depends on secret data:
- x86: JE, JNE, JZ, JNZ, JA, JB, JG, JL, etc.
- ARM: BEQ, BNE, CBZ, CBNZ, TBZ, TBNZ
- RISC-V: BEQ, BNE, BLT, BGE
Scripting Language Support
PHP Analysis
PHP analysis uses either the VLD extension (recommended) or opcache debug output:
Detected PHP Vulnerabilities:
| Category | Pattern | Recommendation |
|----------|---------|----------------|
| Division | ZEND_DIV, ZEND_MOD | Use Barrett reduction |
| Cache timing | chr(), ord() | Use pack('C', $int) / unpack('C', $char)[1] |
| Table lookups | bin2hex(), hex2bin(), base64_encode() | Use constant-time alternatives |
| Array access | FETCH_DIM_R (secret index) | Use constant-time table lookup |
| Bit shifts | ZEND_SL, ZEND_SR (secret amount) | Mask shift amount |
| Variable encoding | pack(), serialize(), json_encode() | Use fixed-length output |
| Weak RNG | rand(), mt_rand(), uniqid() | Use random_int() / random_bytes() |
| String comparison | strcmp(), === on secrets | Use hash_equals() |
Installation:
# Install VLD extension (recommended) # Query latest version from PECL VLD_VERSION=$(curl -s https://pecl.php.net/package/vld | grep -oP 'vld-\K[0-9.]+(?=\.tgz)' | head -1) pecl install channel://pecl.php.net/vld-${VLD_VERSION} # Or build from source (if PECL fails) git clone https://github.com/derickr/vld.git && cd vld phpize && ./configure && make && sudo make install # Or use opcache (built-in, fallback) # Enabled by default in PHP 7+
JavaScript/TypeScript Analysis
JavaScript analysis uses V8 bytecode via Node.js --print-bytecode. TypeScript files are automatically transpiled first.
Detected JS Vulnerabilities:
| Category | Pattern | Recommendation |
|----------|---------|----------------|
| Division | Div, Mod bytecodes | Use constant-time multiply-shift |
| Array access | LdaKeyedProperty (secret index) | Use constant-time table lookup |
| Bit shifts | ShiftLeft, ShiftRight (secret amount) | Mask shift amount |
| Variable encoding | TextEncoder, JSON.stringify(), btoa() | Use fixed-length output |
| Weak RNG | Math.random() | Use crypto.getRandomValues() or crypto.randomBytes() |
| Variable latency | Math.sqrt(), Math.pow() | Avoid in crypto paths |
| String comparison | === on secrets | Use crypto.timingSafeEqual() (Node.js) |
| Early-exit search | indexOf(), includes() | Use constant-time comparison |
Requirements:
# Node.js required node --version # TypeScript compiler (optional, for .ts files) npm install -g typescript
Python Analysis
Python analysis uses the built-in dis module to analyze CPython bytecode.
Detected Python Vulnerabilities:
| Category | Pattern | Recommendation |
|----------|---------|----------------|
| Division | BINARY_OP 11 (/), BINARY_OP 6 (%) | Use Barrett reduction or constant-time alternatives |
| Array access | BINARY_SUBSCR (secret index) | Use constant-time table lookup |
| Bit shifts | BINARY_LSHIFT, BINARY_RSHIFT (secret amount) | Mask shift amount |
| Variable encoding | int.to_bytes(), json.dumps(), base64.b64encode() | Use fixed-length output |
| Weak RNG | random.random(), random.randint() | Use secrets.token_bytes() / secrets.randbelow() |
| Variable latency | math.sqrt(), math.pow() | Avoid in crypto paths |
| String comparison | == on secrets | Use hmac.compare_digest() |
| Early-exit search | .find(), .startswith() | Use constant-time comparison |
Requirements:
# Python 3.x required (built-in dis module) python3 --version
Ruby Analysis
Ruby analysis uses YARV (Yet Another Ruby VM) bytecode via ruby --dump=insns.
Detected Ruby Vulnerabilities:
| Category | Pattern | Recommendation |
|----------|---------|----------------|
| Division | opt_div, opt_mod | Use constant-time alternatives |
| Array access | opt_aref (secret index) | Use constant-time table lookup |
| Bit shifts | opt_lshift, opt_rshift (secret amount) | Mask shift amount |
| Variable encoding | pack(), to_json(), Base64.encode64() | Use fixed-length output |
| Weak RNG | rand(), Random.new | Use SecureRandom.random_bytes() |
| Variable latency | Math.sqrt() | Avoid in crypto paths |
| String comparison | == on secrets | Use Rack::Utils.secure_compare() or OpenSSL |
| Early-exit search | .include?(), .start_with?() | Use constant-time comparison |
Requirements:
# Ruby required (YARV is standard since Ruby 1.9) ruby --version
Example Output
============================================================ Constant-Time Analysis Report ============================================================ Source: decompose.c Architecture: arm64 Compiler: clang Optimization: O2 Functions analyzed: 4 Instructions analyzed: 88 VIOLATIONS FOUND: ---------------------------------------- [ERROR] SDIV Function: decompose_vulnerable Reason: SDIV has early termination optimization; execution time depends on operand values [ERROR] SDIV Function: use_hint_vulnerable Reason: SDIV has early termination optimization; execution time depends on operand values ---------------------------------------- Result: FAILED Errors: 2, Warnings: 0
Fixing Violations
Replace Division with Barrett Reduction
// VULNERABLE int32_t q = a / divisor; // SAFE: Barrett reduction // Precompute: mu = ceil(2^32 / divisor) uint32_t q = (uint32_t)(((uint64_t)a * mu) >> 32);
Replace Branches with Constant-Time Selection
// VULNERABLE if (secret) { result = a; } else { result = b; } // SAFE: Constant-time selection uint32_t mask = -(uint32_t)(secret != 0); result = (a & mask) | (b & ~mask);
Replace Comparisons
// VULNERABLE if (memcmp(a, b, len) == 0) { ... } // SAFE: Use crypto/subtle or equivalent if (subtle.ConstantTimeCompare(a, b) == 1) { ... }
Test Samples
The repository includes test samples demonstrating vulnerable and secure implementations:
ct_analyzer/tests/test_samples/decompose_vulnerable.c- Vulnerable C implementationct_analyzer/tests/test_samples/decompose_constant_time.c- Constant-time C implementationct_analyzer/tests/test_samples/decompose_vulnerable.go- Vulnerable Go implementationct_analyzer/tests/test_samples/decompose_vulnerable.rs- Vulnerable Rust implementationct_analyzer/tests/test_samples/vulnerable.php- Vulnerable PHP implementation- `ct_analyzer/t
优点
- 支持广泛的语言和架构。
- 为检测到的问题提供具体的修复指导。
- 通过JSON和GitHub Actions输出与CI/CD集成。
缺点
- 某些语言需要特定的编译器/运行时设置(例如PHP VLD)。
- 分析深度可能受字节码/汇编输出保真度的限制。
- 主要是检测工具;修复漏洞需要手动实现。
相关技能
免责声明:本内容来源于 GitHub 开源项目,仅供展示和评分分析使用。
版权归原作者所有 trailofbits.
