Skip to main content
Analyze cryptographic implementations to detect operations that leak secret data through execution timing variations. Helps prevent timing attacks like KyberSlash by identifying variable-time operations in compiled assembly and bytecode.

Overview

The Constant-Time Analysis plugin detects timing side-channel vulnerabilities by analyzing compiler output and runtime bytecode for dangerous operations:
  • Division on secrets - Hardware division timing varies based on operand values
  • Secret-dependent branches - Different execution paths have different timing
  • Floating-point operations - Variable latency based on inputs
  • Non-constant comparisons - Early-exit string/memory comparison
This tool performs static analysis only - it flags potentially dangerous operations but requires manual verification to confirm whether they process secret data.

Supported Languages

Native Compiled Languages

Analyzes assembly output from compilers:
  • C/C++ - GCC, Clang
  • Go - Go compiler
  • Rust - Rustc
  • Swift - swiftc (iOS/macOS)

VM-Compiled Languages

Analyzes bytecode (JVM/CIL):
  • Java - JVM bytecode via javap
  • Kotlin - JVM bytecode via kotlinc
  • C# - CIL bytecode via ilspycmd

Interpreted/Scripting Languages

Analyzes VM bytecode or opcodes:
  • PHP - VLD extension or opcache
  • JavaScript/TypeScript - V8 bytecode
  • Python - CPython bytecode via dis
  • Ruby - YARV bytecode

Key Features

Multi-Architecture

Supports x86_64, ARM64, ARM, RISC-V, PowerPC, s390x, i386 for cross-platform analysis

Optimization Testing

Test across O0-O3, Os, Oz to catch optimization-induced vulnerabilities

CI Integration

GitHub Actions annotations and JSON output for automated security checks

Real-World Coverage

Detects vulnerability classes from KyberSlash, Lucky Thirteen, and RSA timing attacks

Installation

ct-analyzer --version
If not installed:
uv pip install -e .

Usage

Basic Analysis

ct-analyzer crypto.c

Advanced Options

--arch
string
default:"native"
Target architecture: x86_64, arm64, arm, riscv64, ppc64le, s390x, i386
--opt-level
string
default:"O2"
Optimization level: O0, O1, O2, O3, Os, Oz
--warnings
boolean
Include conditional branch warnings
--func
regex
Filter to specific functions by pattern
--json
boolean
Output JSON format for CI integration

Cross-Architecture Testing

# Test for ARM64 deployment
ct-analyzer --arch arm64 crypto.c

# Test multiple optimization levels
ct-analyzer --opt-level O0 crypto.c
ct-analyzer --opt-level O3 crypto.c

CI Integration

GitHub Actions
name: Constant-Time Check

on: [push, pull_request]

jobs:
  ct-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      
      - name: Install ct-analyzer
        run: uv pip install -e .
      
      - name: Check constant-time properties
        run: ct-analyzer --github src/crypto/*.c

/ct-check Command

The plugin provides a slash command for quick analysis:
/ct-check <source-file> [--warnings] [--json] [--arch <arch>]
Example:
/ct-check src/sign.c --warnings --arch arm64
This invokes the constant-time-analysis skill with full workflow execution.

Detected Vulnerabilities

Error-Level (Must Fix)

Integer Division: DIV, IDIV, DIVQ, IDIVQFP Division: DIVSS, DIVSD, DIVPS, DIVPDSquare Root: SQRTSS, SQRTSD, SQRTPS, SQRTPD

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
  • ARM: BEQ, BNE, CBZ, CBNZ, TBZ, TBNZ
  • RISC-V: BEQ, BNE, BLT, BGE

Interpreting Results

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

Verifying Results (Critical)

Not every flagged operation is a vulnerability. The tool has no data flow analysis - it flags ALL potentially dangerous operations regardless of whether they involve secrets.
For each flagged violation:
  1. Identify secret inputs - Private keys, plaintext, signatures, tokens
  2. Trace data flow - Does the flagged instruction process secret-derived values?
  3. Apply triage questions:
Likely false positive - Constants don’t leak timing information
// FALSE POSITIVE
int blocks = TOTAL_SIZE / 16;  // Division by constant
Likely false positive - Length/count parameters are usually safe
// FALSE POSITIVE
int num_blocks = data_len / BLOCK_SIZE;  // Length, not content
TRUE POSITIVE - Secret-dependent operations leak timing
// TRUE POSITIVE
int32_t q = secret_coef / GAMMA2;  // secret_coef from private key
TRUE POSITIVE - Attacker-controlled values enable timing attacks
// TRUE POSITIVE
int result = user_input / divisor;  // Timing varies with user_input

Fixing Vulnerabilities

Replace Division with Barrett Reduction

int32_t q = a / divisor;  // Variable-time division

Replace Branches with Constant-Time Selection

if (secret) {
    result = a;
} else {
    result = b;
}

Replace Comparisons

if (memcmp(a, b, len) == 0) {
    // Early-exit comparison leaks timing
}

Language-Specific Detection

PHP Analysis

Detected patterns:
  • Division: ZEND_DIV, ZEND_MOD → Use Barrett reduction
  • String comparison: strcmp(), === on secrets → Use hash_equals()
  • Weak RNG: rand(), mt_rand() → Use random_int()/random_bytes()
  • Cache timing: chr(), ord() → Use pack()/unpack()
Installation:
pecl install vld  # Recommended
# Or use built-in opcache

JavaScript/TypeScript Analysis

Detected patterns:
  • Division: Div, Mod bytecodes → Use constant-time multiply-shift
  • String comparison: === on secrets → Use crypto.timingSafeEqual()
  • Weak RNG: Math.random() → Use crypto.getRandomValues()
  • Variable latency: Math.sqrt(), Math.pow() → Avoid in crypto paths
Requirements:
node --version  # Node.js required
npm install -g typescript  # For .ts files

Python Analysis

Detected patterns:
  • Division: BINARY_OP 11 (/), BINARY_OP 6 (%) → Use Barrett reduction
  • String comparison: == on secrets → Use hmac.compare_digest()
  • Weak RNG: random.random() → Use secrets.token_bytes()
  • Variable latency: math.sqrt(), math.pow() → Avoid in crypto paths

Ruby Analysis

Detected patterns:
  • Division: opt_div, opt_mod → Use constant-time alternatives
  • String comparison: == on secrets → Use Rack::Utils.secure_compare()
  • Weak RNG: rand() → Use SecureRandom.random_bytes()
  • Variable latency: Math.sqrt() → Avoid in crypto paths

Limitations

Important limitations to understand:
  1. Static Analysis Only - Analyzes compiler output, not runtime behavior. Cannot detect:
    • Cache timing attacks from memory access patterns
    • Microarchitectural side-channels (Spectre, Meltdown)
    • Processor-specific optimizations
  2. No Data Flow Analysis - Flags ALL dangerous instructions regardless of whether they operate on secrets. Manual review required to eliminate false positives.
  3. Compiler Variations - Different compilers/versions may produce different assembly. Test with multiple optimization levels and target production architectures.

Real-World Impact

  • KyberSlash (2023) - Division instructions in ML-KEM allowed key recovery
  • Lucky Thirteen (2013) - CBC padding timing enabled plaintext recovery
  • RSA Timing Attacks - Division timing leaked private key bits

References

Author: Scott Arciszewski (Trail of Bits)Version: 0.1.0

Build docs developers (and LLMs) love