25  DTLS Handshake Protocols

In 60 Seconds

The DTLS handshake establishes encrypted sessions over UDP, adding a cookie exchange step to prevent DoS amplification attacks that exploit UDP’s lack of source verification. DTLS 1.2 requires 3 round trips while DTLS 1.3 reduces this to 2 for a full handshake (~19% latency reduction) or just 1 for session resumption (~37% reduction) – both improvements are critical for battery-powered IoT devices where every handshake costs energy.

Key Concepts
  • DTLS Full Handshake: 6-RTT process: ClientHello → HelloVerifyRequest → ClientHello+Cookie → ServerHello+Certificate+ServerHelloDone → ClientKeyExchange+ChangeCipherSpec+Finished → ChangeCipherSpec+Finished
  • DTLS Abbreviated Handshake: 3-RTT session resumption using cached session ID or session ticket; avoids full key exchange and certificate validation for known peers
  • message_seq Field: DTLS-specific field in handshake messages providing per-message sequence numbers for out-of-order reordering and retransmission detection
  • Flight: Group of DTLS handshake messages sent together without waiting for a response; DTLS retransmits entire flight if not acknowledged within the retransmission timer
  • DTLS Retransmission Timer: Initially 1 second, doubles on each timeout (exponential backoff); controls handshake message retransmission for reliability over lossy UDP
  • ClientHello Extensions: Fields added to ClientHello for capability negotiation: supported_versions (TLS 1.3/DTLS 1.3 preference), key_share (ECDHE parameters), signature_algorithms (accepted signature types), max_fragment_length
  • ECDHE Key Exchange: Ephemeral Elliptic Curve Diffie-Hellman; generates a temporary key pair per session to achieve Perfect Forward Secrecy; standard in TLS 1.3/DTLS 1.3
  • DTLS 1.3 Handshake: Reduced to 2 RTTs (vs 6 for DTLS 1.2 full handshake) by merging key exchange into first two flights; 1-RTT with 0-RTT session resumption (with replay risk)

25.1 Learning Objectives

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

  • Trace the DTLS 1.2 Handshake: Identify each message flight and explain the HelloVerifyRequest cookie mechanism for DoS protection
  • Compare DTLS Versions: Distinguish the 3-RTT DTLS 1.2 handshake from DTLS 1.3’s 2-RTT full handshake and 1-RTT session resumption
  • Explain TLS 1.3 Influence: Justify why DTLS 1.3 adopted TLS 1.3’s 1-RTT security model and mandatory forward secrecy
  • Evaluate Session Resumption: Assess 0-RTT resumption energy savings and justify when replay-attack risks make it unsuitable
  • Calculate Handshake Energy: Apply the energy formula to determine battery impact of DTLS version choice for a given IoT device

Before two devices can communicate securely, they need to agree on encryption rules – this agreement process is called a handshake. Think of it like a secret knock at a clubhouse door: both sides must exchange the right signals before any private conversation can begin. DTLS does this for IoT devices communicating over UDP, adding an extra cookie step to prevent imposters from faking the knock.

MVU: Minimum Viable Understanding

Core concept: DTLS handshakes establish encrypted sessions over UDP, with the cookie mechanism preventing DoS amplification attacks that plague UDP-based protocols.

Why it matters: The handshake is the most expensive part of DTLS - understanding it helps you optimize battery life and connection latency.

Key takeaway: DTLS 1.3 reduces handshake from 3-RTT to 2-RTT for a full connection (~19% faster) or 1-RTT for session resumption (~37% faster) compared to DTLS 1.2 on typical networks. Always use session resumption when reconnecting a device that was sleeping.

“Before two devices can talk securely, they need to agree on the rules – that is the handshake,” said Max the Microcontroller. “It is like two spies meeting for the first time. They exchange code words to prove they are who they claim to be.”

“The cookie exchange is the clever part,” explained Sammy the Sensor. “Before doing the full handshake, the server sends a puzzle. Only a legitimate client at a real address can solve it and send it back. This prevents attackers from flooding the server with fake handshake requests.”

“DTLS 1.3 is a big improvement,” added Lila the LED. “It reduced the handshake from 3 round trips to just 2 – and session resumption can do it in 1 round trip! For IoT devices that reconnect after sleeping, this saves significant connection time and energy, especially when using session resumption.”

“Every round trip saved is battery saved,” emphasized Bella the Battery. “On a sensor that reconnects 100 times a day, cutting the handshake from 3 round trips to 1 saves thousands of bytes and milliseconds of radio time. Over a year, that could mean weeks of extra battery life!”

25.2 Prerequisites

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

25.3 DTLS 1.2 Handshake

DTLS 1.2 handshake protocol flow showing 3-RTT connection establishment with cookie exchange for DoS protection

DTLS 1.2 handshake protocol flow diagram
Figure 25.1: DTLS 1.2 Handshake Protocol showing complete 3-RTT (round-trip time) connection establishment: Phase 1 – client sends ClientHello with supported versions, cipher suites, and random nonce; server responds with HelloVerifyRequest containing a stateless cookie for DoS protection. Phase 2 – client retransmits ClientHello including cookie, server sends ServerHello selecting cipher suite, Certificate, ServerKeyExchange with ECDHE parameters, and ServerHelloDone. Phase 3 – client sends ClientKeyExchange with key material, CertificateVerify signature, ChangeCipherSpec to activate encryption, and Finished message with handshake hash; server responds with ChangeCipherSpec and Finished. Phase 4 – encrypted application data flows, with all records protected by the negotiated cipher suite. All handshake messages include explicit sequence numbers and are retransmitted on loss since UDP provides no delivery guarantees.

This variant shows the same handshake concept through a side-by-side comparison - useful for understanding why DTLS requires extra round trips and how the cookie mechanism adds overhead for DoS protection.

Comparison diagram showing TLS 1.3 with 1-RTT handshake taking ~100ms versus DTLS 1.2 with 3-RTT handshake taking ~250ms. TLS 1.3 sends ClientHello with KeyShare, receives ServerHello bundle, completes with Finished. DTLS 1.2 adds HelloVerifyRequest cookie exchange step for DoS protection because UDP cannot rely on TCP's delivery guarantees. Center box explains three reasons for extra overhead: DoS protection via cookie validation, packet loss handling since UDP may drop handshake messages, and explicit sequence numbers since TCP ordering not available.
Figure 25.2: Side-by-side comparison of TLS 1.3 (1-RTT) versus DTLS 1.2 (3-RTT) handshakes showing why UDP requires additional round trips

25.3.1 DTLS 1.2 Handshake Steps

  1. ClientHello: Client proposes cipher suites
  2. HelloVerifyRequest: Server sends cookie (DoS protection)
  3. ClientHello (with cookie): Client proves legitimacy
  4. Server responds: Certificate, key exchange parameters
  5. Client key exchange: Client sends key material
  6. Finished messages: Both sides confirm (encrypted)
  7. Secure communication: Application data flows encrypted

Overhead: 6 distinct message events across 3 round trips (vs 3 message flights in 1 round trip for TLS 1.3 over TCP)

Why more overhead?

  • Unreliable transport: Must handle lost handshake packets
  • Retransmission: DTLS retransmits handshake messages
  • Cookie mechanism: Extra round trip for DoS protection

25.4 DTLS 1.2 vs DTLS 1.3

DTLS 1.3 (RFC 9147, 2022) improves upon DTLS 1.2:

Feature DTLS 1.2 DTLS 1.3
Handshake Latency 3-RTT (with cookie) 2-RTT full / 1-RTT resumption
Cipher Suites Many (some weak) Only AEAD (authenticated encryption)
Perfect Forward Secrecy Optional (ECDHE) Mandatory
0-RTT Resumption No Yes (risky, opt-in)
Legacy Crypto RSA, CBC, RC4 Removed (only modern ciphers)
Complexity Higher Lower (simplified)

25.4.1 DTLS 1.3 Handshake (2-RTT Full / 1-RTT Resumption)

DTLS 1.3 handshake protocol flow showing streamlined 2-RTT connection establishment with mandatory ECDHE key exchange and encrypted handshake messages

DTLS 1.3 handshake protocol flow diagram
Figure 25.3: DTLS 1.3 Handshake Protocol showing streamlined 2-RTT connection establishment: client sends ClientHello in first message already including KeyShare with ECDHE public key, SupportedGroups indicating elliptic curves, and SignatureAlgorithms for certificate verification, enabling server to derive encryption keys immediately; server responds with ServerHello containing its KeyShare for key agreement, then sends EncryptedExtensions, Certificate, CertificateVerify signature, and Finished message all encrypted under derived handshake keys; client verifies server certificate, sends its own Certificate (if mutual auth), CertificateVerify, and Finished message encrypted; both parties can immediately exchange application data encrypted under session keys; messages in curly braces are encrypted; 2-RTT full handshake is faster than DTLS 1.2’s 3-RTT handshake providing significant battery life improvement for IoT devices, mandatory perfect forward secrecy via ECDHE, eliminates legacy vulnerable ciphers.

Benefit: DTLS 1.3 eliminates the cookie round trip, reducing total handshake time by one RTT compared to DTLS 1.2 (critical for mobile IoT).

Quick Check: DTLS Versions

DTLS handshake round-trip reduction translates directly to latency savings. For DTLS 1.2 with 3 RTTs:

\[T_{\text{DTLS 1.2}} = 3 \times \text{RTT} + T_{\text{crypto}}\]

With 50ms RTT and 120ms total crypto operations:

\[T_{\text{DTLS 1.2}} = 3 \times 50ms + 120ms = 270ms\]

DTLS 1.3 full handshake reduces to 2-RTT (no cookie step needed):

\[T_{\text{DTLS 1.3}} = 2 \times \text{RTT} + T_{\text{crypto}} = 2 \times 50ms + 120ms = 220ms\]

Improvement: \((270 - 220) / 270 = 19\%\) faster for a full handshake. For session resumption (1-RTT):

\[T_{\text{DTLS 1.3 resume}} = 1 \times 50ms + 120ms = 170ms\]

Resumption improvement: \((270 - 170) / 270 = 37\%\) faster. For 0-RTT resumption with a pre-shared ticket, the handshake latency approaches zero, with data sent in the first packet.

25.5 TLS 1.3 Handshake: Step-by-Step

TLS 1.3 reduced the handshake from 2 round-trips to 1 (or 0 for resumption). Understanding the TLS 1.3 handshake is essential because DTLS 1.3 follows the same security model.

25.5.1 Full Handshake (1-RTT)

TLS 1.3 full handshake sequence diagram showing 1-RTT connection establishment: Step 1 Client sends ClientHello with KeyShare containing ECDHE public key and list of supported cipher suites to server; Step 2 Server responds with ServerHello containing its KeyShare plus Certificate for authentication and Finished message all in single flight; Step 3 Client sends Finished message and can immediately begin sending application data; Step 4 onwards both parties exchange encrypted application data bidirectionally; demonstrates how TLS 1.3 reduced handshake from 2-RTT to 1-RTT by having client send key material speculatively in first message enabling server to derive encryption keys immediately.
Figure 25.4: TLS 1.3 full 1-RTT handshake sequence

25.5.2 What Happens at Each Step

Step Client Action Server Action Security Achieved
1 Generate ephemeral key pair, send public - Forward secrecy initiated
2 - Verify client, send cert + key Server authenticated
3 Verify server cert, derive session key Derive session key Mutual key agreement
4+ Encrypt with session key Encrypt with session key Confidentiality + integrity

Step-by-Step Breakdown:

  1. ClientHello (Step 1):
    • Client generates ephemeral ECDHE key pair
    • Sends public key in key_share extension
    • Lists supported cipher suites (e.g., TLS_AES_256_GCM_SHA384)
    • Includes random nonce for freshness
  2. ServerHello (Step 2):
    • Server selects cipher suite
    • Generates its own ephemeral key pair
    • Derives handshake keys from ECDHE shared secret
    • Sends Certificate (encrypted with handshake keys)
    • Sends CertificateVerify (signature proving possession of private key)
    • Sends Finished (MAC over entire handshake transcript)
  3. Client Finished (Step 3):
    • Client verifies server certificate chain
    • Verifies CertificateVerify signature
    • Derives session keys
    • Sends Finished message
    • Can immediately send application data!
  4. Encrypted Data (Step 4+):
    • All subsequent data encrypted with AEAD cipher
    • Sequence numbers prevent replay
    • Session keys provide forward secrecy

25.5.3 0-RTT Resumption (Pre-Shared Key)

When clients have previously connected and cached session data, they can resume with zero round-trip latency:

TLS 1.3 0-RTT session resumption sequence diagram showing zero round-trip handshake: Client sends ClientHello including Pre-Shared Key identifier from previous session plus Early Data containing application request in first message; Server responds with ServerHello and Finished confirming session resumption; application data is sent with the very first packet eliminating handshake latency; warning box indicates 0-RTT is vulnerable to replay attacks since early data can be captured and retransmitted by attacker making it suitable only for idempotent requests like GET not for state-changing operations like POST or database writes.
Figure 25.5: TLS 1.3 0-RTT session resumption

0-RTT Benefits:

  • Latency: Application data sent immediately (no waiting for handshake)
  • Battery: Fewer packets = less radio-on time
  • User experience: Faster page loads, quicker sensor responses
0-RTT Security Warning

0-RTT is vulnerable to replay attacks. An attacker can capture the first message and retransmit it, causing the server to process the early data multiple times.

Safe for:

  • GET requests (idempotent)
  • Cache lookups
  • Read-only queries

NOT safe for:

  • POST/PUT requests
  • Database writes
  • Financial transactions
  • IoT actuator commands (door unlock, motor start)

Mitigation: Servers should mark 0-RTT data as potentially replayed and only process idempotent operations.

25.5.4 TLS 1.3 vs TLS 1.2 Handshake Comparison

Flowchart comparing TLS 1.2 and TLS 1.3 handshake flows side by side: TLS 1.2 path shows 2-RTT sequence with ClientHello followed by ServerHello then separate Certificate and KeyExchange messages then ChangeCipherSpec then Finished requiring two complete round trips; TLS 1.3 path shows 1-RTT sequence with ClientHello containing KeyShare followed by single server response with ServerHello plus Certificate plus Finished then client Finished enabling immediate encrypted data; decision diamond shows IoT devices should prefer TLS 1.3 for reduced latency and improved security through mandatory forward secrecy.
Figure 25.6: TLS 1.2 vs TLS 1.3 handshake comparison
Feature TLS 1.2 TLS 1.3
Round Trips 2-RTT 1-RTT (or 0-RTT resumption)
Messages 9+ messages 3-4 messages
Forward Secrecy Optional (DHE/ECDHE) Mandatory
Cipher Suites 300+ (many weak) 5 (all AEAD)
RSA Key Exchange Allowed Removed
CBC Mode Allowed Removed
Compression Allowed Removed (CRIME attack)

IoT Recommendation: Always use TLS 1.3 (or DTLS 1.3) when available for: - Faster handshakes (1-RTT vs 2-RTT for TLS, critical for battery life) - Mandatory forward secrecy (protects past sessions if key compromised) - Simplified cipher suite selection (5 AEAD suites vs 300+ weak options)

25.6 Working Code: Handshake Energy Analysis

Understanding the energy cost of DTLS handshakes is critical for battery-powered IoT devices. This Python tool calculates how much battery the handshake consumes and compares DTLS versions.

"""DTLS Handshake Energy Calculator for IoT Devices."""

def dtls_handshake_energy(version="1.2", radio_tx_mA=120, radio_rx_mA=40,
                          idle_mA=0.01, rtt_ms=100, battery_mAh=2000):
    """Calculate energy cost of a DTLS handshake for constrained devices.

    Args:
        version: "1.2", "1.3", or "1.3-resume" (0-RTT resumption)
        radio_tx_mA: Current draw during transmission
        radio_rx_mA: Current draw during reception
        idle_mA: Sleep current between round trips
        rtt_ms: Network round-trip time in milliseconds
        battery_mAh: Battery capacity
    """
    # Message sizes (bytes) and counts per handshake phase
    profiles = {
        "1.2": {
            "name": "DTLS 1.2 (3-RTT with cookie)",
            "flights": [
                ("ClientHello",           150, "tx"),
                ("HelloVerifyRequest",    100, "rx"),
                ("ClientHello+cookie",    200, "tx"),
                ("ServerHello+Cert+Done", 800, "rx"),
                ("ClientKeyExchange+CCS", 200, "tx"),
                ("CCS+Finished",          80,  "rx"),
            ],
            "round_trips": 3,
        },
        "1.3": {
            "name": "DTLS 1.3 (2-RTT full handshake)",
            "flights": [
                ("ClientHello+KeyShare",  250, "tx"),
                ("ServerHello+Cert+Fin",  900, "rx"),
                ("Client Finished",       100, "tx"),
            ],
            "round_trips": 2,
        },
        "1.3-resume": {
            "name": "DTLS 1.3 0-RTT Resumption",
            "flights": [
                ("ClientHello+PSK+Data",  300, "tx"),
                ("ServerHello+Finished",  200, "rx"),
            ],
            "round_trips": 1,
        },
    }

    p = profiles[version]
    tx_bytes = sum(s for _, s, d in p["flights"] if d == "tx")
    rx_bytes = sum(s for _, s, d in p["flights"] if d == "rx")

    # Time estimates (assume 250 kbps radio, typical for 802.15.4)
    radio_bps = 250_000
    tx_time_ms = (tx_bytes * 8 / radio_bps) * 1000
    rx_time_ms = (rx_bytes * 8 / radio_bps) * 1000
    wait_time_ms = p["round_trips"] * rtt_ms  # idle between flights

    # Energy in mAh
    tx_energy = radio_tx_mA * (tx_time_ms / 3_600_000)
    rx_energy = radio_rx_mA * (rx_time_ms / 3_600_000)
    wait_energy = idle_mA * (wait_time_ms / 3_600_000)
    total_energy = tx_energy + rx_energy + wait_energy

    total_time_ms = tx_time_ms + rx_time_ms + wait_time_ms

    # How many handshakes before battery dies (handshake-only budget)
    handshakes_per_battery = battery_mAh / total_energy if total_energy > 0 else float('inf')

    print(f"\n{'='*55}")
    print(f"  {p['name']}")
    print(f"{'='*55}")
    for name, size, direction in p["flights"]:
        arrow = "->" if direction == "tx" else "<-"
        print(f"  {arrow} {name:30s} {size:4d} bytes")
    print(f"  {'─'*55}")
    print(f"  TX: {tx_bytes} bytes ({tx_time_ms:.1f} ms at {radio_tx_mA} mA)")
    print(f"  RX: {rx_bytes} bytes ({rx_time_ms:.1f} ms at {radio_rx_mA} mA)")
    print(f"  Wait: {p['round_trips']} RTTs x {rtt_ms} ms = {wait_time_ms:.0f} ms")
    print(f"  Total time: {total_time_ms:.1f} ms")
    print(f"  Energy per handshake: {total_energy*1000:.3f} uAh")
    print(f"  Handshakes per {battery_mAh} mAh battery: {handshakes_per_battery:,.0f}")

    return {"energy_uAh": total_energy * 1000, "time_ms": total_time_ms,
            "tx_bytes": tx_bytes, "rx_bytes": rx_bytes}


# Compare all three DTLS handshake modes
print("DTLS Handshake Energy Comparison for IoT")
print("(802.15.4 radio, 100ms RTT, 2000 mAh battery)\n")

results = {}
for v in ["1.2", "1.3", "1.3-resume"]:
    results[v] = dtls_handshake_energy(v)

# Savings summary
print(f"\n{'='*55}")
print("  Savings Summary")
print(f"{'='*55}")
base = results["1.2"]["energy_uAh"]
for v in ["1.3", "1.3-resume"]:
    saving = (1 - results[v]["energy_uAh"] / base) * 100
    print(f"  {v:12s} saves {saving:.0f}% energy vs DTLS 1.2")

# Practical scenario: sensor reconnecting 100x/day
daily_reconnects = 100
for v, r in results.items():
    daily_uAh = r["energy_uAh"] * daily_reconnects
    yearly_mAh = daily_uAh * 365 / 1000
    print(f"\n  {v}: {daily_reconnects} reconnects/day = "
          f"{daily_uAh:.1f} uAh/day = {yearly_mAh:.1f} mAh/year")

Key insight: DTLS 1.3 with session resumption uses approximately 64% less energy per handshake than DTLS 1.2. For a device reconnecting 100 times daily, this saves measurable battery over a year – enough to matter for multi-year deployments.

25.7 Worked Example: Energy Cost Per DTLS Handshake

For battery-powered IoT devices, every DTLS handshake has a measurable energy cost. This analysis shows why session resumption and DTLS 1.3 matter for real deployments.

Device: nRF52840 (Nordic Semiconductor) with cellular modem (nRF9160)

Radio characteristics:
  TX current: 230 mA (at 23 dBm, LTE-M)
  RX current: 46 mA
  Idle/sleep: 7 uA
  Data rate: ~30 Kbps effective (LTE-M uplink)

DTLS 1.2 Full Handshake (3-RTT, with PSK):

Message exchange:
  ClientHello:           ~90 bytes, TX time: 24 ms
  HelloVerifyRequest:    ~50 bytes, RX time: 13 ms
  ClientHello + Cookie:  ~130 bytes, TX time: 35 ms
  ServerHello + Done:    ~120 bytes, RX time: 32 ms
  ClientKeyExchange:     ~80 bytes, TX time: 21 ms
  ChangeCipherSpec:      ~60 bytes, TX time: 16 ms
  ServerFinished:        ~60 bytes, RX time: 16 ms
  Total TX time: 96 ms at 230 mA = 0.0061 mAh
  Total RX time: 61 ms at 46 mA = 0.00078 mAh
  Network RTT wait: 3 x 100 ms = 300 ms at 7 uA = negligible

  Total energy per handshake: 0.0069 mAh

DTLS 1.3 Full Handshake (2-RTT, with PSK):

Reduced message count (merged flights):
  Total TX time: 62 ms at 230 mA = 0.0040 mAh
  Total RX time: 45 ms at 46 mA = 0.00058 mAh
  Network RTT wait: 2 x 100 ms = 200 ms

  Total energy per handshake: 0.0046 mAh (33% less than DTLS 1.2)

DTLS 1.3 Session Resumption (1-RTT):

Pre-shared session ticket, single round trip:
  Total TX time: 35 ms at 230 mA = 0.0022 mAh
  Total RX time: 25 ms at 46 mA = 0.00032 mAh

  Total energy per handshake: 0.0025 mAh (64% less than DTLS 1.2)

Annual impact for a device reconnecting 50 times per day:

Handshake Type Energy/Handshake Daily Cost Annual Cost Battery Life Impact
DTLS 1.2 full (PSK) 0.0069 mAh 0.345 mAh 126 mAh -4.2% of 3,000 mAh battery
DTLS 1.3 full (PSK) 0.0046 mAh 0.230 mAh 84 mAh -2.8%
DTLS 1.3 resumption 0.0025 mAh 0.125 mAh 46 mAh -1.5%
No security (UDP only) 0 mAh 0 mAh 0 mAh 0%

With certificate-based authentication (not PSK), the handshake carries 1-3 KB of certificates, increasing energy cost 3-5x. For constrained devices, PSK-based DTLS is strongly preferred unless the deployment requires certificate infrastructure for device identity management.

Design recommendation: Use DTLS 1.3 with session resumption for devices that reconnect frequently (>10 times/day). The 64% energy reduction over DTLS 1.2 full handshakes translates to months of additional battery life over a multi-year deployment.

Try It: DTLS Handshake Energy Calculator

Adjust your device parameters to see how DTLS version and session resumption affect handshake energy consumption.

Try It: Session Resumption Battery Life Estimator

Estimate how much longer your device’s battery lasts when using DTLS 1.3 session resumption instead of full handshakes.

25.8 Concept Relationships

Understanding how DTLS handshakes connect to broader transport and security concepts:

Prerequisites:

Builds Upon:

  • TLS 1.3 security model → DTLS 1.3 adapts for UDP’s unreliable delivery
  • TCP connection state machine → DTLS session state without connection overhead

Enables:

Related Concepts:

  • Session resumption (64% energy reduction) parallels TCP Fast Open optimization
  • Connection ID (RFC 9146) solves same NAT rebinding problem as QUIC connection migration

25.9 See Also

DTLS Deep Dives:

Transport Security:

Practical Implementation:

Standards:

  • RFC 6347: DTLS 1.2 specification
  • RFC 9147: DTLS 1.3 specification (2022)
  • RFC 9146: Connection ID extension for DTLS 1.2

25.10 Try It Yourself

Exercise 1: Handshake Energy Profiling (Hardware Required)

Measure the actual energy cost of DTLS handshakes on your hardware:

Materials:

  • ESP32 DevKit
  • USB power meter or oscilloscope with current probe
  • Wi-Fi access point

Steps:

  1. Flash the mbedTLS DTLS client example to ESP32
  2. Configure for DTLS 1.2 with PSK authentication
  3. Measure current draw during full handshake using power meter
  4. Calculate energy: E = I × V × t (integrate current over handshake duration)
  5. Repeat for DTLS 1.3 and session resumption
  6. Compare measured values to theoretical calculations in worked example

Expected Results:

  • DTLS 1.2 full handshake: 450-600 ms, ~7-10 mJ on Wi-Fi
  • DTLS 1.3 full handshake: 250-350 ms, ~4-6 mJ
  • Session resumption: 100-200 ms, ~2-3 mJ

What to Observe: Track not just average current but peak current spikes during crypto operations (ECDHE key generation, certificate verification).


Exercise 2: Cookie Amplification Test (Software Only)

Verify DTLS cookie mechanism prevents DoS amplification:

Setup (pseudocode sketch – requires an actual DTLS server and helper functions):

# dtls_cookie_test.py - Conceptual sketch of cookie amplification test
# NOTE: extract_cookie() and build_client_hello() must be implemented
# using a DTLS library such as mbedTLS Python bindings or OpenSSL.
import socket
import time

# Legitimate client flow
def legitimate_handshake(server_ip, server_port):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # Send ClientHello (no cookie)
    client_hello = b'\x16\xfe\xfd...'  # DTLS record header + ClientHello
    sock.sendto(client_hello, (server_ip, server_port))
    bytes_sent = len(client_hello)

    # Receive HelloVerifyRequest
    response, _ = sock.recvfrom(1500)
    bytes_received = len(response)

    # Extract cookie from HelloVerifyRequest
    cookie = extract_cookie(response)

    # Retransmit ClientHello with cookie
    client_hello_with_cookie = build_client_hello(cookie)
    sock.sendto(client_hello_with_cookie, (server_ip, server_port))

    print(f"Amplification factor: {bytes_received / bytes_sent:.2f}x")
    # Expected: < 2x (HelloVerifyRequest is small, ~100 bytes)

# Spoofed source test (attacker scenario)
def spoofed_attack_test():
    # Attacker sends ClientHello with spoofed source IP
    # Server sends HelloVerifyRequest to spoofed IP (victim)
    # Victim receives unsolicited HelloVerifyRequest but takes no action
    # Attacker cannot complete handshake without receiving the cookie
    # Result: Attack fails, victim receives only small HelloVerifyRequest
    pass

What to Test:

  1. Run legitimate handshake and verify amplification factor < 2x
  2. Compare to TLS over TCP (no cookie) where attacker can trigger multi-KB ServerHello
  3. Observe that without the cookie, attacker cannot proceed to expensive crypto operations

Expected Learning: Understand why DTLS cookie mechanism is critical for UDP-based security protocols.


Exercise 3: Session Resumption Battery Savings (Interactive)

Use the Session Resumption Battery Life Estimator in the Worked Example section above to explore how reconnection frequency and handshake times affect your device’s battery life. Enter your device’s parameters and observe how switching from full handshakes to session resumption extends deployment lifetime.

Example using default values:

  • 100 reconnects/day, 2000 mAh battery, 25 mA radio, 450ms full, 200ms resume, 10 µA sleep
  • Full handshakes: ~5.6 mAh/day, battery life ~342 days
  • Session resumption: ~2.98 mAh/day, battery life ~621 days
  • Gain: 279 additional days (82% improvement)

What to Observe: Notice how small percentage reductions in handshake time translate to large battery life gains when multiplied by hundreds of daily reconnections over multi-year deployments.

Common Pitfalls

DTLS Certificate messages can be 1–5 KB — larger than typical UDP MTU (1280 bytes for IPv6 minimum, 1500 bytes for Ethernet). DTLS implements a record-layer fragmentation mechanism (fragment_offset + fragment_length fields). Implementations that do not correctly handle fragmented handshake messages fail to complete the handshake with peers using different MTU configurations. Test DTLS handshake with both large (2 KB) and minimal MTU (1024 bytes) configurations on the target network.

DTLS retransmits the last sent flight when the retransmission timer expires. If the implementation retransmits individual messages rather than the entire flight, the peer may receive partial flights that fail message sequence validation. The DTLS specification requires retransmitting ALL messages in the last flight. Verify retransmission behavior under packet loss using network emulation tools (tc netem, Wireshark with manual drops) to ensure complete flight retransmission.

The DTLS default retransmission timer is 1 second (RFC 6347 recommends 1 second initial, max 60 seconds). This is appropriate for wired networks with <10 ms RTT. For NB-IoT (500 ms RTT) or LTE-M during coverage transitions (1–2 s RTT), the 1-second initial timeout triggers premature retransmission before the response can arrive, causing duplicate messages and handshake failure. Set initial DTLS retransmission timer to 5× measured network RTT for LPWAN networks.

Completing DTLS handshake after validating the certificate signature and chain but without verifying that the certificate Subject or SAN matches the server hostname allows an attacker with any valid certificate from the same CA to perform a MITM attack. Always verify that the server certificate CN (Common Name) or Subject Alternative Name (SAN) matches the DNS hostname or IP address used to connect. Use the TLS SNI extension to send the expected hostname and verify it against the certificate.

25.11 What’s Next?

Topic Link Why Read It
DTLS Attack Scenarios & Authentication dtls-sec-attacks-auth.html Analyze PSK vs certificate authentication trade-offs and implement defenses against DTLS-specific attacks
DTLS Performance & Optimization dtls-sec-performance.html Evaluate session caching strategies and Connection ID (RFC 9146) to minimize reconnect overhead
DTLS Fundamentals & Architecture dtls-sec-fundamentals.html Review the DTLS record layer and epoch/sequence number design that underpins the handshake
CoAP Security with DTLS ../app-protocols/coap-security-applications.html Apply DTLS handshake knowledge to configure CoAPS bindings for constrained IoT endpoints
TLS & DTLS Cipher Suites ../cryptography/encryption-tls-dtls.html Select appropriate AEAD cipher suites and compare TLS 1.3 vs DTLS 1.3 key exchange mechanics
Transport Protocol Selection transport-fund-comparison.html Justify when to add DTLS to UDP versus choosing QUIC or TLS/TCP for a given IoT scenario