OpenSSL 3.2 vs 3.1: Performance Analysis

About This Analysis

This page explains the technical reasons behind the performance differences observed in OpenSSL version 3.2 compared to 3.1. Understanding these changes helps system administrators and developers make informed decisions about which OpenSSL version to deploy.

How to Use This Page: Start with the Executive Summary for key takeaways, then dive into the technical details if you want to understand the root causes. The benchmark data table shows actual measurements from our test environment.

Version Analysis Series

This is part of a series analyzing performance changes across OpenSSL versions:

Executive Summary

OpenSSL 3.2.0 (released November 23, 2023) delivered significant performance improvements over the 3.1.x series, marking a turning point in recovering the performance lost during the 3.0 architecture transition. This analysis examines the key code changes that enabled 2-2.5× improvement in TLS handshake performance.

~2,500
Commits between 3.1.0 and 3.2.0
+100-150%
TLS handshake improvement
Nov 2023
OpenSSL 3.2.0 Release
Key Finding: The dramatic performance improvement comes from provider architecture optimizations that reduced per-operation overhead. OpenSSL 3.0/3.1 introduced significant dispatch overhead with the provider model; version 3.2 addressed the most critical bottlenecks.

The Primary Cause: Provider Architecture Optimization

OpenSSL 3.0 introduced a new "provider" architecture that added flexibility but also introduced significant per-operation overhead. The 3.2 release included focused optimizations to reduce this overhead.

The Core Improvement: Reduced per-operation provider dispatch overhead through better caching, algorithm fetching optimization, and streamlined context management.

What Was Slow in OpenSSL 3.0/3.1

The Provider Overhead Problem

  • Algorithm Fetching: Every cryptographic operation required looking up the algorithm implementation through the provider framework
  • Context Creation: Creating EVP contexts had significant overhead due to provider dispatch
  • Property Queries: The property-based algorithm selection system added string parsing overhead
  • Lock Contention: Provider operations required locking that hurt multi-threaded performance

What OpenSSL 3.2 Fixed

  • Improved Algorithm Caching: Better caching of fetched algorithm implementations
  • Reduced Context Overhead: Streamlined EVP context creation paths
  • Property Query Optimization: Faster property string parsing and matching
  • Lock Optimization: Reduced lock contention in hot paths

Understanding the 3.x Performance Journey

Version Performance vs 1.1.1w Notes
1.1.1w Baseline (100%) Direct API, no provider overhead
3.0.x ~70-80% Provider architecture introduced, significant overhead
3.1.x ~75-85% Minor improvements, still significant overhead
3.2.x ~95-105% Major optimization effort, approaching 1.1.1w levels
3.4.x ~100-110% Continued optimization, often exceeds 1.1.1w
Key Insight: The ~2.5× improvement from 3.1 to 3.2 is primarily due to the accumulation of performance fixes addressing the provider overhead introduced in 3.0. This was a focused effort by the OpenSSL team in response to community performance concerns.

GitHub Reference

View the changes between these versions:

Compare 3.1.0...3.2.0 View 3.2.0 Release

Benchmark Performance Comparison

Data Source: These results are from our local benchmark runs comparing the 3.1.x and 3.2.x series.
Metric OpenSSL 3.1.x OpenSSL 3.2.x Change
TLS 1.3 RSA Handshakes/sec ~2,500 ~6,200 +148%
TLS 1.3 ECDSA Handshakes/sec ~7,500 ~11,500 +53%
TLS 1.2 RSA Handshakes/sec ~2,600 ~6,600 +154%
TLS 1.2 ECDSA Handshakes/sec ~7,600 ~11,300 +49%
RSA-2048 Sign/sec ~8,250 ~8,350 +1.2%
ECDSA P-256 Sign/sec ~43,000 ~43,500 +1.2%
Analysis: The handshake performance improvements are dramatic (50-150%), while raw cryptographic operations (RSA/ECDSA signing) show minimal change. This confirms the improvement is in the TLS stack and provider dispatch overhead, not in the underlying crypto primitives.

Major Feature Changes in OpenSSL 3.2

Beyond performance, OpenSSL 3.2 introduced several significant features:

Client-Side QUIC Support (RFC 9000)

  • Full client-side QUIC implementation with multiple streams
  • New APIs for QUIC connection and stream management
  • Foundation for future server-side QUIC (added in 3.5)
View QUIC Documentation

TLS Certificate Compression (RFC 8879)

  • Support for compressing certificate chains during TLS handshake
  • Reduces bandwidth and speeds up connection establishment
  • Supports zlib, Brotli, and Zstandard compression algorithms

Hybrid Public Key Encryption - HPKE (RFC 9180)

  • New high-level API for authenticated encryption with public keys
  • Foundation for Encrypted Client Hello (ECH) support
  • Combines KEM, KDF, and AEAD in a single, secure construction

Deterministic ECDSA Signatures (RFC 6979)

  • ECDSA signatures no longer require random nonces
  • Eliminates class of attacks related to poor RNG
  • Provides consistent, reproducible signatures

New Cryptographic Algorithms

  • Ed25519ctx, Ed25519ph, Ed448ph - Extended EdDSA variants (RFC 8032)
  • AES-GCM-SIV - Nonce-misuse resistant authenticated encryption (RFC 8452)
  • Argon2 - Memory-hard password hashing (RFC 9106)
  • X9.42 KDF - Key derivation for Diffie-Hellman
  • KMAC-256/512 - SHAKE-based message authentication

🚀 Understanding QUIC in OpenSSL 3.2

New in 3.2: OpenSSL 3.2 introduced client-side QUIC support (RFC 9000), marking the beginning of OpenSSL's QUIC journey. Server-side QUIC was later added in OpenSSL 3.5.

What is QUIC?

QUIC (Quick UDP Internet Connections) is a transport layer protocol originally designed by Google and standardized by the IETF as RFC 9000. It fundamentally reimagines how secure connections work by combining the transport layer (like TCP) with the encryption layer (like TLS) into a single, optimized protocol.

0-RTT
Connection resumption
1-RTT
New connections
UDP
Based transport
HTTP/3
Primary use case

Why QUIC Matters for Performance

Traditional TLS over TCP (HTTP/2)

  • TCP 3-way handshake: 1 round-trip (SYN → SYN-ACK → ACK)
  • TLS 1.3 handshake: 1 round-trip (ClientHello → ServerHello + data)
  • Total minimum latency: 2 round-trips before application data flows
  • Head-of-line blocking: One lost packet blocks ALL streams

QUIC (HTTP/3)

  • Combined handshake: Transport + crypto negotiation in parallel
  • New connection: 1 round-trip total (50% faster than TCP+TLS)
  • Resumed connection (0-RTT): Application data in first packet!
  • No head-of-line blocking: Independent streams don't block each other

QUIC vs Traditional TLS: Connection Latency Comparison

The chart below illustrates the round-trip time (RTT) savings when using QUIC compared to traditional TCP+TLS connections:

TCP + TLS 1.3 (New Connection)
TCP Handshake: 1 RTT
TLS 1.3 Handshake: 1 RTT
Total: 2 RTTs
QUIC (New Connection)
Combined QUIC+TLS: 1 RTT
Total: 1 RTT (50% faster!)
TCP + TLS 1.3 (Session Resumption)
TCP Handshake: 1 RTT
TLS 1.3 Resume: 1 RTT
Total: 2 RTTs
QUIC (0-RTT Resumption)
Application data in first packet!
Total: 0 RTT (instant!)

Real-World Performance Impact

Metric TCP + TLS 1.3 QUIC Improvement
Connection establishment (50ms RTT) 100ms minimum 50ms 50% faster
Session resumption (50ms RTT) 100ms minimum 0ms (0-RTT) 100% faster
Mobile network handoff Full reconnection needed Connection ID survives Seamless
Packet loss impact All streams blocked Only affected stream Independent streams

How OpenSSL Implements QUIC

Unlike traditional TLS which handles everything internally, OpenSSL's QUIC implementation uses a hybrid approach:

OpenSSL QUIC Architecture

  • TLS 1.3 Handshake: OpenSSL handles the cryptographic handshake (certificates, key exchange)
  • QUIC Record Layer: OpenSSL provides QUIC-specific packet protection and encryption
  • Connection Management: OpenSSL manages QUIC connection state and stream multiplexing
  • Integration APIs: New OSSL_QUIC_* functions for applications to use QUIC directly
Why QUIC is Important:
  • HTTP/3 adoption: Major websites (Google, Cloudflare, Facebook) already use QUIC for 25%+ of traffic
  • Mobile performance: QUIC's connection migration is crucial for mobile users switching networks
  • CDN efficiency: Reduced connection overhead means faster content delivery
  • Future-proofing: QUIC is becoming the dominant transport for modern web applications

OpenSSL QUIC Timeline

Version QUIC Support Status
OpenSSL 3.2 Client-side QUIC (RFC 9000) First release
OpenSSL 3.3 Client improvements, QLOG support Enhanced
OpenSSL 3.4 Stability and performance fixes Matured
OpenSSL 3.5 Server-side QUIC + 0-RTT Full support

Client-Side vs Server-Side QUIC: What's the Difference?

OpenSSL implemented QUIC in two phases. Understanding the difference is crucial for deployment planning:

🖥️ Client-Side QUIC (OpenSSL 3.2+)

What it means: Your application can connect to QUIC-enabled servers.

  • Initiates connections: Sends ClientHello, negotiates parameters
  • Use cases: Web browsers, HTTP clients, mobile apps
  • Responsibility: Generates key shares, validates server certificates
  • Examples: curl with HTTP/3, custom QUIC clients

API: Use SSL_new_stream() to create streams, SSL_connect() to initiate

Server-Side QUIC (OpenSSL 3.5+)

What it means: Your application can accept QUIC connections from clients.

  • Accepts connections: Listens on UDP, handles ClientHello
  • Use cases: Web servers, API gateways, load balancers
  • Responsibility: Presents certificates, manages multiple clients
  • Examples: nginx (with quic module), custom QUIC servers

API: Use SSL_accept_stream(), SSL_get_accept_stream_queue_len()

Why the phased approach? Server-side QUIC is significantly more complex:
  • Connection multiplexing: Servers must handle thousands of concurrent connections
  • Address validation: Servers need to prevent IP spoofing attacks (Retry tokens)
  • 0-RTT anti-replay: Servers must track 0-RTT tickets to prevent replay attacks
  • Migration handling: Servers must gracefully handle clients changing IP addresses

What is QLOG?

Added in OpenSSL 3.3: QLOG support enables deep protocol inspection and debugging for QUIC connections.

QLOG (QUIC Logging) is a standardized JSON-based logging format specifically designed for QUIC and HTTP/3. It captures detailed protocol events that are essential for debugging, performance analysis, and interoperability testing.

What QLOG Captures

  • Connection events: Handshake start/completion, connection close, migration
  • Packet information: Packet numbers, types, sizes, timing
  • Frame details: Stream frames, ACK frames, crypto frames
  • Recovery events: Packet loss detection, retransmissions, RTT measurements
  • Flow control: Window updates, blocked streams, data limits

Why QLOG Matters

  • Debugging: Identify handshake failures, packet loss patterns, congestion issues
  • Performance tuning: Analyze RTT, loss rates, and stream prioritization
  • Interoperability: Compare behavior between different QUIC implementations
  • Visualization: Tools like qvis render QLOG files as interactive diagrams
Example: Enabling QLOG in OpenSSL
# Set environment variable to enable QLOG output
export QLOGDIR=/tmp/qlogs

# Run OpenSSL with QUIC (QLOG files written automatically)
openssl s_client -quic -connect example.com:443

# View the generated QLOG file
cat /tmp/qlogs/*.qlog | jq .
QLOG IETF Draft qvis Visualizer

⚠️ The QUIC + Post-Quantum Challenge: MTU and Large Keys

Critical Issue: Post-quantum cryptography creates significant complications for QUIC due to UDP packet size constraints. This is an active area of research and concern in the cryptographic community.

QUIC was designed with specific assumptions about key sizes that post-quantum cryptography fundamentally challenges:

The Problem: Key Size Explosion

Algorithm Public Key Size Ciphertext Size Total Key Share
X25519 (classical) 32 bytes 32 bytes 64 bytes
P-256 (classical) 65 bytes 65 bytes 130 bytes
ML-KEM-768 (PQC) 1,184 bytes 1,088 bytes 2,272 bytes
X25519MLKEM768 (hybrid) 1,216 bytes 1,120 bytes 2,336 bytes

QUIC's MTU Constraint

  • QUIC Initial packets: Must fit within ~1,200 bytes (minimum QUIC MTU per RFC 9000)
  • Typical UDP MTU: ~1,472 bytes on most networks (1500 - 28 header bytes)
  • Problem: A hybrid key share (2,336 bytes) exceeds the entire packet!
  • Impact: ClientHello may require fragmentation or multiple round trips

Why This Matters for Performance

Classical QUIC Handshake
ClientHello + X25519 key share (~300 bytes)
↓ Fits in 1 packet ✓
1 RTT handshake
PQC QUIC Handshake (Challenge)
ClientHello + ML-KEM key share (~2,500+ bytes)
↓ Exceeds MTU! Multiple packets needed
Potential fragmentation overhead

Current Solutions and Research

Approaches Being Explored

  • QUIC coalescing: Multiple QUIC packets in a single UDP datagram
  • Deferred key exchange: Send PQC key share in a subsequent packet
  • Smaller PQC algorithms: ML-KEM-512 is smaller but provides less security
  • Path MTU discovery: Negotiate larger MTU when available
  • Compression techniques: Research into compressible key formats
OpenSSL's Approach (3.5+): OpenSSL handles this by allowing multiple key shares and supporting HelloRetryRequest (HRR) fallback. If the initial key share doesn't work, the server can request a different one. However, this adds latency—potentially negating QUIC's speed benefits.

→ See our OpenSSL 3.5/3.6 Analysis for details on how ML-KEM default keyshares impact performance.

Real-World Implications

  • HTTP/3 adoption: May be slowed until PQC MTU issues are resolved
  • Mobile networks: Often have smaller MTUs, exacerbating the problem
  • Middleboxes: Some firewalls/NATs fragment or drop oversized UDP packets
  • Performance regression: QUIC's latency benefits may be partially lost with PQC

Further Reading

Testing QUIC: OpenSSL provides QUIC testing capabilities through its s_server and s_client tools with the -quic flag. For benchmarking, we measure the cryptographic operations that underpin QUIC connections (key exchange, packet protection) rather than network-dependent metrics.

QUIC Code References

Explore the QUIC implementation in OpenSSL:

QUIC README QUIC Source Code RFC 9000 Spec

Key Code Areas

Performance-Critical Files

Release Tags

Changelog & Documentation

The Bigger Picture: OpenSSL 3.x Performance Recovery

The OpenSSL 3.2 release represents a critical milestone in the OpenSSL 3.x performance story:

The Challenge (2021-2023)

  • OpenSSL 3.0 (Sept 2021) introduced provider architecture for modularity
  • This caused 20-40% performance regression vs 1.1.1w
  • Community raised concerns about production performance
  • OpenSSL team prioritized performance work

The Recovery (2023-2024)

  • OpenSSL 3.2 (Nov 2023) delivered major optimizations
  • OpenSSL 3.3 (Apr 2024) continued refinements
  • OpenSSL 3.4 (Oct 2024) achieved/exceeded 1.1.1w performance
  • Provider architecture overhead largely mitigated
Recommendation: For production systems requiring maximum performance, OpenSSL 3.2+ provides the best balance of modern features and performance. Organizations still on 3.0.x or 3.1.x should prioritize upgrading to capture these gains.

Why This Matters for Your Deployment

Understanding the performance changes between OpenSSL versions helps you make informed decisions:

If You're Running OpenSSL 3.0.x or 3.1.x

  • Strong recommendation to upgrade: OpenSSL 3.2+ provides 50-150% better handshake performance
  • The upgrade is straightforward with minimal API changes
  • You'll get improved security features (QUIC, HPKE, RFC 6979) as a bonus

If You're Evaluating OpenSSL Versions

  • OpenSSL 3.2-3.4: Best performance for traditional TLS workloads
  • OpenSSL 3.5+: Adds post-quantum cryptography but with ~13% handshake overhead (see analysis)
  • Consider your security requirements vs performance needs

Understanding the OpenSSL 3.x Performance Journey

This page documents one chapter in a larger story:

  • 3.0 (Sept 2021): Provider architecture caused 20-40% regression
  • 3.2 (Nov 2023): Major optimization effort recovered most performance — this page
  • 3.5 (Apr 2025): Post-quantum defaults add ~13% overhead — see analysis

Related Analysis & External Resources

Benchmark Reports

Official OpenSSL Resources

Further Reading

Back to Overview View Handshake Benchmarks
View on GitHub
Open Source Benchmark
Found a problem? Have an improvement?
Fork the repository and submit a pull request!
Licensed under Apache 2.0 • Community-driven development