27  DTLS Performance and Implementation

In 60 Seconds

DTLS adds roughly 10-20 ms latency per packet and requires 9x more RAM than unencrypted UDP, but session resumption reduces handshake packet count by 60% (10 packets down to 4), cutting battery drain and making it viable for battery-powered devices. The key optimization strategies are enabling session caching, using Connection ID for mobile devices that change IP addresses, and preferring PSK over certificates on constrained gateways to cut handshake time from 1,200 ms to 250 ms.

Key Concepts
  • DTLS Overhead Per Packet: DTLS 1.2 record header: 13 bytes; DTLS 1.3 unified header: 2–5 bytes; AES-128-GCM authentication tag: 16 bytes; total per-record overhead: 18–29 bytes
  • Handshake Cost on Constrained Devices: DTLS 1.2 full handshake (ECDHE + ECDSA): ~500 ms on Cortex-M3 at 72 MHz; DTLS 1.3: ~350 ms; PSK mode: ~200 ms; significant for battery-powered sensors transmitting infrequently
  • Session Resumption vs Full Handshake: Full DTLS 1.2 handshake: ~3 KB data exchange; session ticket resumption: ~200 bytes; 15× reduction in handshake data — critical for NB-IoT (1 MB/month data plan)
  • DTLS Connection ID (CID): DTLS 1.3 extension allowing a DTLS session to survive client IP/port changes (NAT rebinding); avoids full renegotiation when mobile IoT device changes network attachment point
  • mbedTLS Performance: ARM Cortex-M4 at 120 MHz: AES-128-GCM encrypt = 3 MB/s; ECDSA-P256 sign = 50 ms; ECDSA verify = 100 ms; RSA-2048 sign = 500 ms; RSA verify = 20 ms
  • Record Size Optimization: DTLS application records should be sized to fit within one network MTU (1280–1500 bytes including all headers) to avoid IP fragmentation; IP fragmentation causes additional packet loss under poor network conditions
  • TLS 1.3 0-RTT Data: DTLS 1.3 supports early data (0-RTT) on session resumption, allowing application data with the first flight; reduces handshake overhead for frequent short connections
  • Hardware Acceleration: IoT SoCs with hardware AES (e.g., ESP32, nRF9160, STM32) provide 10–100× faster DTLS bulk cipher operations vs software; critical for throughput on high-frequency data paths

27.1 Learning Objectives

By the end of this chapter, you will be able to:

  • Compare DTLS Configurations: Evaluate handshake time, latency, memory, and CPU overhead across PSK, certificate, and DTLS 1.2 vs 1.3 configurations
  • Implement Session Resumption: Configure session caching and Connection ID to achieve up to 82% longer battery life on reconnecting IoT devices
  • Calculate Resource Requirements: Assess RAM and flash requirements for DTLS deployments and select the appropriate authentication mode for constrained devices
  • Configure Replay Protection: Diagnose packet loss impacts and tune the sliding window size for high-loss networks
  • Design Optimized Deployments: Construct production-ready DTLS configurations for IoT fleets by applying session caching, Connection ID, and PSK trade-offs

Security always comes at a cost – encryption takes processing power, memory, and time. For tiny IoT devices running on batteries, these costs matter a lot. This chapter explores how to balance strong security with the limited resources of IoT devices, like finding a lock that is both secure and easy to open with a small key.

MVU: Minimum Viable Understanding

Core concept: DTLS adds 10-20ms latency per packet but session resumption reduces handshake packets from 10 to 4 (60% reduction), cutting battery drain – critical for battery-powered devices.

Why it matters: Without optimization, DTLS handshakes drain battery faster than the actual data transmission.

Key takeaway: Always enable session caching, use Connection ID for mobile devices, and prefer PSK for constrained gateways managing many connections.

“Security always has a price,” said Bella the Battery. “DTLS adds 10 to 20 milliseconds of latency per packet and uses 9 times more RAM than plain UDP. But with the right optimizations, it is totally worth it.”

“Session resumption is the biggest win,” explained Max the Microcontroller. “A full handshake sends 10 packets and takes around 450 milliseconds for DTLS 1.2. Session resumption needs only 4 packets and takes roughly 200 milliseconds. That is a 60 percent reduction in packets! For devices that reconnect after sleeping, this makes DTLS practical.”

“Connection ID is brilliant for mobile devices,” added Sammy the Sensor. “If a device moves and gets a new IP address, normally the DTLS session would break and need a full re-handshake. Connection ID lets the session survive address changes – the server identifies the device by its ID, not its address.”

“The bottom line is clear,” said Lila the LED. “Choose PSK over certificates on constrained gateways – it cuts handshake time from 1,200 milliseconds to 250 milliseconds. Always enable session caching. And tune the replay protection window for your specific packet loss rate. These three optimizations make DTLS viable even on tiny sensors.”

27.2 Prerequisites

Before diving into this chapter, you should be familiar with:

27.3 Performance Benchmarking

Test Setup: ESP32 at 240 MHz, CoAP request of 100 bytes

Metric UDP (no security) DTLS 1.2 (PSK) DTLS 1.2 (Cert) DTLS 1.3 (PSK)
Handshake Time N/A 450 ms 1200 ms 250 ms
Per-packet Latency 5 ms 15 ms 15 ms 12 ms
Throughput 1200 msg/s 950 msg/s 950 msg/s 1000 msg/s
Memory (RAM) 2 KB 18 KB 45 KB 22 KB
Code Size (Flash) 50 KB 180 KB 250 KB 200 KB
CPU per packet 0.5% 3% 3% 2.5%

Analysis:

  • Handshake: DTLS 1.3 is 44% faster than DTLS 1.2
  • Certificates: ~2.7x slower handshake than PSK (but better scalability)
  • Runtime overhead: DTLS adds 10ms latency (acceptable for most IoT)
  • Memory: DTLS requires 9x more RAM than unencrypted UDP

DTLS overhead can be quantified across dimensions. For handshake time improvement from DTLS 1.2 to 1.3:

\[\text{Improvement} = \frac{T_{\text{DTLS 1.2}} - T_{\text{DTLS 1.3}}}{T_{\text{DTLS 1.2}}} = \frac{450ms - 250ms}{450ms} = 44\%\]

For memory overhead, DTLS 1.2 with PSK uses 18 KB versus 2 KB for plain UDP:

\[\text{Overhead factor} = \frac{18 \text{ KB}}{2 \text{ KB}} = 9\times\]

Per-packet latency overhead from encryption (15ms vs 5ms):

\[\Delta t = 15ms - 5ms = 10ms\]

For throughput (950 msg/s vs 1200 msg/s):

\[\text{Throughput loss} = \frac{1200 - 950}{1200} = 20.8\%\]

These numbers show the security-performance tradeoff: DTLS costs ~10ms per packet, 9x RAM, and 21% throughput, but provides encryption and authentication.

Recommendation for IoT:

  • Resource-constrained (< 32 KB RAM): PSK mode
  • Enterprise (> 128 KB RAM): Certificate mode
  • Firmware: Upgrade to DTLS 1.3 when available (faster, more secure)

Try It: DTLS Configuration Overhead Calculator

Explore how DTLS authentication mode and version affect memory and handshake time for your IoT device.

27.4 Implementation Best Practices

27.4.1 Session Resumption

Problem: DTLS handshake costs 450ms + 10 UDP packets (battery drain)

Solution: Resume previous session

DTLS session resumption flow diagram showing two phases: an initial full handshake (3-RTT) with ClientHello, HelloVerifyRequest cookie exchange, ServerHello with Certificate, and key establishment storing a SessionID and master secret; followed by a fast session resumption (1-RTT) where the client presents the cached SessionID, the server reuses the stored master secret, skips certificate exchange and ECDHE operations, and both sides exchange only ChangeCipherSpec and Finished messages before proceeding directly to encrypted application data, reducing handshake from 10 packets to 4 packets

DTLS Session Resumption
Figure 27.1: DTLS session resumption cuts the full 10-packet handshake (3-RTT) down to just 4 packets (1-RTT) by reusing the cached master secret, reducing latency by 100-150ms and significantly extending battery life on IoT devices that reconnect frequently.

Savings (DTLS 1.2 PSK, full handshake vs. resumption): - Handshake time: 450ms -> 200ms (56% reduction) - Packets sent: 10 -> 4 (60% reduction) - Battery life extension: up to 82% (see worked example below)

Try It: Session Resumption Battery Life Calculator

Estimate how session resumption extends battery life for your IoT sensor.

Implementation:

// mbedTLS example
mbedtls_ssl_conf_session_cache(&conf, &cache,
                               mbedtls_ssl_cache_get,
                               mbedtls_ssl_cache_set);
// Cache sessions for 1 hour
mbedtls_ssl_cache_set_timeout(&cache, 3600);

27.4.2 Connection ID Extension (RFC 9146)

Problem: IoT devices change IP addresses (NAT rebinding, mobile handoff)

Traditional DTLS:

Session tied to: (Client IP, Client Port, Server IP, Server Port)
IP changes -> Session invalidated -> Must re-handshake

Connection ID:

Session tied to: Connection ID (random 4-byte value)
IP changes -> Session persists!

Use case: Mobile sensor moving between Wi-Fi APs

27.4.3 Replay Window Tuning

Default: 64-packet sliding window

Problem: High packet loss (Wi-Fi in motion) -> legitimate packets rejected as “too old”

Solution: Increase window size

// mbedTLS
mbedtls_ssl_conf_dtls_anti_replay(&conf, MBEDTLS_SSL_ANTI_REPLAY_ENABLED);
mbedtls_ssl_conf_dtls_badmac_limit(&conf, 100); // Allow 100 bad MACs before abort

Trade-off: Larger window = more memory, but tolerates more loss.

27.5 Worked Examples

Scenario: You are designing an IoT gateway for a smart factory that needs to maintain simultaneous DTLS connections to 150 sensors. The gateway has 512 KB RAM available for DTLS operations. You need to determine whether to use PSK or certificate-based authentication.

Given:

  • Number of sensors: 150
  • Available RAM: 512 KB
  • PSK mode memory per session: ~1.5 KB (32-byte PSK + 1 KB session state + 512 bytes crypto context)
  • Certificate mode memory per session: ~5 KB (2-4 KB certificate storage + 1 KB session state + 512 bytes crypto context)
  • Session cache overhead: 64 bytes per cached session

Steps:

  1. Calculate memory for PSK mode with all active sessions:

    Active sessions: 150 x 1.5 KB = 225 KB
    Session cache: 150 x 64 bytes = 9.6 KB
    Total PSK: 225 + 9.6 = 234.6 KB
  2. Calculate memory for certificate mode with all active sessions:

    Active sessions: 150 x 5 KB = 750 KB
    Session cache: 150 x 64 bytes = 9.6 KB
    Total Certificates: 750 + 9.6 = 759.6 KB
  3. Compare against available RAM (512 KB):

    PSK mode: 234.6 KB < 512 KB (fits with 277 KB headroom)
    Certificate mode: 759.6 KB > 512 KB (exceeds by 248 KB)
  4. Calculate maximum concurrent certificate sessions possible:

    Max sessions = (512 KB - overhead) / 5 KB = 100 sessions approx
    Need: 150 sessions -> Would require session rotation

Result: Use PSK mode for this deployment. It requires 234.6 KB RAM, leaving 277 KB headroom for other gateway functions. Certificate mode would exceed available memory by 48%.

Key Insight: PSK authentication uses approximately 70% less memory than certificate-based authentication, making it the preferred choice for resource-constrained gateways managing many concurrent connections. The trade-off is reduced scalability and manual key provisioning compared to PKI-based systems.

Scenario: A battery-powered environmental sensor sends data to a cloud server every 60 seconds using CoAP over DTLS. The sensor’s battery capacity is 2000 mAh at 3.3V. You need to calculate the battery life difference between full handshake every connection versus using session resumption.

Given:

  • Reporting interval: 60 seconds (1,440 connections per day)
  • Full DTLS 1.2 handshake: 10 packets, 450ms total, radio at 25mA during TX/RX
  • Session resumption: 4 packets, 200ms total
  • Data transmission: 2 packets, 50ms
  • Sleep current: 10 µA
  • Active current (CPU): 15mA for packet processing (100ms per connection)
  • Battery: 2000 mAh, 3.3V

Steps:

  1. Calculate daily energy for full handshake mode:

    Per connection:
    - Handshake radio: 25mA x 450ms = 11.25 mAs
    - Data radio: 25mA x 50ms = 1.25 mAs
    - CPU active: 15mA x 100ms = 1.5 mAs
    Total per connection: 14 mAs
    
    Daily:
    - Connections: 1,440 x 14 mAs = 20,160 mAs = 5.6 mAh
    - Sleep: 10 µA x 24h = 0.24 mAh
    - Total: 5.84 mAh/day
  2. Calculate daily energy with session resumption:

    Per connection:
    - Resumption radio: 25mA x 200ms = 5 mAs
    - Data radio: 25mA x 50ms = 1.25 mAs
    - CPU active: 15mA x 80ms = 1.2 mAs (faster processing)
    Total per connection: 7.45 mAs
    
    Daily:
    - Connections: 1,440 x 7.45 mAs = 10,728 mAs = 2.98 mAh
    - Sleep: 0.24 mAh
    - Total: 3.22 mAh/day
  3. Calculate battery life for each mode:

    Full handshake: 2000 mAh / 5.84 mAh/day = 342 days
    Session resumption: 2000 mAh / 3.22 mAh/day = 621 days
  4. Calculate improvement:

    Battery life improvement: 621 - 342 = 279 additional days
    Percentage improvement: (621 - 342) / 342 x 100 = 82% longer battery life

Result: Enabling session resumption extends battery life from 342 days to 621 days, an 82% improvement (nearly doubling the operational lifetime).

Key Insight: DTLS session resumption provides dramatic battery savings for frequently-connecting IoT devices. The 250ms saved per connection (450ms to 200ms) accumulates to massive energy savings over thousands of daily connections. Always enable session caching on battery-powered devices, and consider using DTLS 1.3 for even faster handshakes.

27.7 Real-World Case Study: Fleet-Wide DTLS Energy Optimization at Bosch IoT

Bosch’s Connected Building division deployed 45,000 HVAC sensors using CoAP over DTLS-PSK across 200 commercial buildings in Germany (2020-2022). After the first year, 18% of battery-powered sensors exhausted their batteries 2x faster than projected. A fleet-wide energy audit revealed DTLS handshake inefficiency as the primary cause.

The Problem:

Expected battery life: 5 years (2000 mAh, 3.3V lithium)
Actual battery life (affected sensors): 2.4 years

Energy audit per sensor per day:
  Planned:
    6 CoAP readings/hour * 24 hours = 144 readings/day
    Session resumption for all readings (200 ms handshake)
    Daily DTLS energy: 144 * 25mA * 200ms = 720 mAs = 0.2 mAh

  Actual (affected devices):
    Same 144 readings/day
    Session cache expired after 1 hour (server-side default)
    Full handshake every hour: 24 * 25mA * 450ms = 270 mAs = 0.075 mAh
    Session resumption within hour: 120 * 25mA * 200ms = 600 mAs = 0.167 mAh
    Retry due to handshake timeout (10% failure): 14 * 25mA * 900ms = 315 mAs = 0.088 mAh
    Daily DTLS energy: 0.33 mAh (65% higher than planned)

Root Cause Analysis:

The server-side DTLS session cache was configured with a 1-hour timeout (default in the open-source CoAP library). After 1 hour, cached sessions were evicted, forcing a full 6-message (3-flight) handshake for the next reading. Additionally, 10% of full handshakes timed out on the first attempt due to Wi-Fi congestion during business hours, triggering a retry with doubled airtime.

Three-Phase Optimization:

Phase 1 – Extend Session Cache Lifetime (Week 1):

Server configuration change:
  Session cache timeout: 1 hour -> 24 hours
  Session cache size: 10,000 -> 50,000 entries (needed for fleet)
  Server RAM impact: +200 MB (50,000 * 4 KB per cached session)

Result: Full handshakes reduced from 24/day to 1/day per sensor
  Energy savings: 0.33 mAh -> 0.22 mAh/day (33% reduction)

Phase 2 – Enable Connection ID (RFC 9146) (Month 2):

Problem: 12% of sensors lost DTLS sessions after Wi-Fi AP roaming
  (building HVAC sensors span multiple APs per floor)
  Each lost session = full re-handshake

With Connection ID:
  Session survives AP roaming (IP address change)
  Lost sessions from roaming: 12% -> 0%
  Energy savings: additional 8% reduction
  New daily energy: 0.20 mAh

Phase 3 – DTLS 1.3 Migration (Month 6):

Upgraded from DTLS 1.2 to DTLS 1.3 on 15,000 newer sensors:
  Full handshake: 450 ms -> 250 ms (1-RTT vs 2-RTT)
  Session resumption: 200 ms -> 100 ms (0-RTT)
  Per-packet overhead: 15 ms -> 12 ms

DTLS 1.3 daily energy: 0.14 mAh (58% lower than original problem)

Fleet-Wide Impact (45,000 sensors):

Metric Before Optimization After (Phase 1-3) Improvement
Daily DTLS energy (affected) 0.33 mAh 0.14 mAh 58% reduction
Projected battery life 2.4 years 5.8 years 2.4x longer
Annual battery replacements 8,100 sensors 0 (within target) 100% eliminated
Annual replacement cost $810,000 $0 $810K saved
Server RAM for session cache 40 MB 240 MB +200 MB (acceptable)

Key Insight: DTLS session management is the single largest controllable factor in battery life for CoAP-secured IoT devices. The three optimizations (extended cache, Connection ID, DTLS 1.3) are cumulative and independent – any one of them provides measurable improvement. The most impactful and easiest change was simply extending the server’s session cache timeout from 1 hour to 24 hours, which eliminated 23 of 24 daily full handshakes per sensor at zero device firmware cost. For any fleet of >1,000 DTLS-secured sensors, audit the session cache configuration before investigating device-side optimizations.


27.8 Summary

DTLS Fundamentals:

  • Purpose: TLS security for UDP applications
  • Use cases: CoAP, VoIP, WebRTC, real-time telemetry
  • Trade-off: Adds 10-20ms latency for encryption

Security Features:

  • Encryption: AES-GCM, ChaCha20
  • Authentication: PSK (simple) or Certificates (scalable)
  • Replay protection: Sequence numbers + sliding window
  • DoS protection: Cookie mechanism

Performance:

  • DTLS 1.3: 44% faster handshake than 1.2
  • Session resumption: up to 82% longer battery life (60% fewer handshake packets)
  • PSK vs Certs: PSK uses 70% less memory

Best Practices:

  • Enable session caching for battery-powered devices
  • Use Connection ID for mobile IoT
  • Choose PSK for small deployments, certificates for scale
  • Tune replay window for high-loss networks

DTLS makes real-time, secure IoT applications possible without the latency penalty of TCP.

27.9 Knowledge Check

27.10 Deep Dive: DTLS Session Cache Under the Hood

Understanding the session cache mechanism that enables up to 82% longer battery life:

Step 1: Initial Full Handshake

Client generates:
  - ClientRandom (28 bytes, current time + random)
  - ECDHE private key (32 bytes for P-256 curve)

Server generates:
  - ServerRandom (28 bytes)
  - ECDHE private key (32 bytes)
  - Session ID (32 bytes, random identifier)

Both derive master secret:
  master_secret = PRF(premaster_secret,
                      "master secret",
                      ClientRandom + ServerRandom)

Server stores in cache:
  cache[SessionID] = {
    master_secret,
    cipher_suite,
    expiry_time,
    peer_certificate (if used)
  }

Step 2: Session Resumption Handshake

Client sends ClientHello:
  - Previous SessionID (from initial handshake)
  - No ECDHE KeyShare (saves crypto computation)

Server looks up:
  if (SessionID in cache AND not expired):
    cached_session = cache[SessionID]
    skip_full_handshake = true
  else:
    perform_full_handshake = true

If cached:
  Server sends ServerHello with same SessionID
  Both reuse cached master_secret
  Derive new application keys from master_secret + new randoms
  Skip certificate exchange (saves 1-3 KB transmission)
  Skip ECDHE (saves 150-300 ms crypto time)

Step 3: Memory Management

Cache eviction strategies:
  - LRU (Least Recently Used): Drop oldest session first
  - TTL (Time To Live): Default 1 hour, configurable to 24 hours
  - Max entries: Gateway with 10,000 devices needs 40 MB for cache

Session ticket alternative (RFC 5077):
  - Server encrypts session state with secret key
  - Sends encrypted ticket to client
  - Client stores ticket (64-256 bytes)
  - Eliminates server-side memory requirement
  - Trade-off: Ticket encryption/decryption overhead

Why It Works: The expensive parts of a handshake are: 1. ECDHE key generation (asymmetric crypto: ~150 ms on ESP32) 2. Certificate verification (RSA signature: ~200 ms) 3. Transmitting certificates (1-3 KB over lossy link)

Session resumption skips all three by reusing the previously established master secret.

27.11 Concept Relationships

Prerequisites:

Builds Upon:

  • TLS session resumption (RFC 5077) → DTLS adapts for UDP
  • Symmetric key caching → Asymmetric operations only on first handshake

Enables:

Related Concepts:

  • Connection ID (RFC 9146) complements session resumption for mobile devices
  • QUIC 0-RTT resumption uses similar session ticket approach
  • HTTP/2 connection reuse parallels DTLS session cache at application layer

27.12 See Also

DTLS Deep Dives:

Performance Optimization:

Real-World Case Studies:

Implementation Guides:

27.13 Try It Yourself

Exercise 1: Profile Session Cache Hit Rates

Measure how often your deployment benefits from session resumption:

Setup (ESP32 + CoAP):

// Enable session cache tracking
int cache_hits = 0;
int cache_misses = 0;
int cache_full_count = 0;

// In DTLS session establishment callback:
void dtls_session_callback(bool resumed) {
  if (resumed) {
    cache_hits++;
    Serial.println("[CACHE] Session resumed - saved handshake");
  } else {
    cache_misses++;
    Serial.println("[CACHE] Full handshake - new session");
  }

  float hit_rate = (float)cache_hits / (cache_hits + cache_misses) * 100;
  Serial.printf("[STATS] Hit rate: %.1f%% (%d hits, %d misses)\n",
                hit_rate, cache_hits, cache_misses);
}

Test Scenarios:

  1. Reconnect every 60 seconds → Expect ~100% hit rate (within default 1-hour timeout)
  2. Reconnect every 2 hours → Expect 0% hit rate (cache expired)
  3. 1,000 different devices → Track cache evictions

What to Observe: If hit rate < 80%, investigate: - Is cache timeout too short for your reconnection interval? - Are devices changing IP addresses (need Connection ID)? - Is cache size sufficient for your device count?


Exercise 2: Connection ID NAT Survival Test

Verify Connection ID preserves sessions across IP changes:

Setup:

# dtls_connection_id_test.py
import socket
import time

def test_connection_id_survival(server_ip, server_port):
    # Establish DTLS session with Connection ID enabled
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    establish_dtls_session(sock, server_ip, server_port, use_cid=True)

    print("[1] Initial connection established from IP A")

    # Simulate network change (move to different Wi-Fi AP)
    # In real test: physically move device between APs
    # In simulation: rebind socket to different local port (simulates NAT rebinding)

    new_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    new_sock.bind(('0.0.0.0', 0))  # New local port = new NAT mapping

    # Copy DTLS session state to new socket
    transfer_dtls_session(old_sock=sock, new_sock=new_sock)

    # Send data on new socket
    send_dtls_application_data(new_sock, b"Hello after IP change")

    print("[2] Data sent from new IP (NAT rebinding simulated)")

    # Server should identify session by Connection ID, not source IP
    # No re-handshake required

test_connection_id_survival('192.168.1.100', 5684)

What to Expect:

  • Without Connection ID: Session breaks, full re-handshake required (450 ms)
  • With Connection ID: Session persists, data flows immediately (0 ms handshake)

Measure: Time between IP change and successful data transmission. Connection ID should reduce this from ~500 ms to <50 ms.


Exercise 3: Tune Replay Protection Window

Find the optimal window size for your packet loss rate:

Background: DTLS uses a sliding window (default 64 packets) to detect replayed messages. In high-loss networks, legitimate packets arriving out of order may be rejected if they fall outside the window.

Test Procedure:

// ESP32 test code
mbedtls_ssl_conf_dtls_anti_replay(&conf, MBEDTLS_SSL_ANTI_REPLAY_ENABLED);
mbedtls_ssl_conf_dtls_badmac_limit(&conf, 100);

// Try different window sizes:
// Small window (32): Low memory, rejects legitimate out-of-order packets
// Default (64): Balanced
// Large window (128): High memory, tolerates more reordering

// Measure:
int legitimate_rejects = 0;  // Good packets rejected as "too old"
int true_replays_caught = 0; // Actual attack packets detected

Calculation:

Window size needed = (packet_loss_rate × RTT × transmission_rate)

Example:
- 10% packet loss
- 200 ms RTT
- 10 packets/second transmission rate
- Window = 0.10 × 0.2s × 10 pps = 0.2 packets

Round up to 64 (minimum) for safety margin.

For high-loss cellular (20% loss, 1s RTT, 5 pps):
- Window = 0.20 × 1.0s × 5 pps = 1 packet
- Need at least 64 for burst tolerance
- Consider 128 for this scenario

What to Observe: Larger windows use more RAM (8 bytes per entry) but reduce false rejections. Find the sweet spot for your network conditions.

Common Pitfalls

Establishing a new DTLS session for each 50-byte sensor reading transmits 3–8 KB of handshake data — 60–160× the application payload. For applications sending 10 readings per day, handshake overhead dominates total data consumption. Implement DTLS session persistence: store session ticket in NVS, reuse sessions for 24 hours, only renegotiate on session expiry or server rejection. Session resumption reduces per-transaction overhead from 3 KB to 200 bytes.

DTLS key generation requires a cryptographically secure random number generator. Devices without a hardware True Random Number Generator (TRNG) using software PRNG seeded from boot time or memory content produce predictable key material. An attacker who knows the seed can derive all session keys. Use hardware entropy sources: ESP32 hardware RNG, nRF9160 TRNG, STM32 RNG peripheral. Never use time-based seeds (millis(), uptime) for cryptographic key generation.

DTLS anti-replay window defaults to 64 records. In high-throughput IoT data paths (100 records/second), out-of-order delivery within a 640 ms jitter window may drop valid records outside the window. In low-throughput paths (1 record/minute), replay windows of 64 are excessive — reduce to 16 for memory savings. Tune the replay window size to match expected network jitter: window_size = max_out_of_order_records × 1.5 as a safety margin.

DTLS implementations have had critical CVEs: CVE-2020-13935 (Tomcat DTLS crash), CVE-2021-3449 (OpenSSL null pointer), CVE-2021-38561 (mbedTLS DoS). IoT devices with hardcoded mbedTLS or WolfSSL versions that cannot be updated via OTA are permanently vulnerable to known exploits. Build the DTLS library version into the firmware version number, implement OTA updates for security-critical library updates, and monitor CVE databases for DTLS library vulnerabilities.

27.14 What’s Next?

Topic Link Why Read It
Transport Fundamentals transport-fundamentals.html Understand how TCP, UDP, and QUIC underpin all IoT communication before applying DTLS optimizations
DTLS Fundamentals and Architecture dtls-sec-fundamentals.html Review the record protocol and cookie mechanism that DTLS performance tuning builds upon
DTLS Handshake Protocols dtls-sec-handshake.html Examine the full flight-by-flight handshake sequence to understand exactly what session resumption skips
DTLS Attack Scenarios and Authentication dtls-sec-attacks-auth.html Evaluate PSK versus certificate trade-offs in the context of real DTLS attack vectors
CoAP Fundamentals and Architecture ../app-protocols/coap-fundamentals-and-architecture.html Apply DTLS session caching and Connection ID in practice with CoAPS (CoAP over DTLS)
Transport Optimizations and Implementation transport-optimizations-and-implementation.html Extend DTLS performance work with broader transport-layer tuning for constrained networks