Securing Connections with DTLS 1.3 in wolfJSSE

We are excited to announce that the wolfSSL Java JSSE provider (wolfJSSE) now officially supports DTLS 1.3. This addition brings the latest in datagram security to the Java ecosystem, providing a modern, efficient, and secure protocol for UDP-based applications.

Download wolfSSL →

This support is included as of the wolfSSL JNI/JSSE v1.16.0 release and is available for both client and server side through the SSLEngine interface.

Why Move to DTLS 1.3?

DTLS 1.3 (defined in RFC 9147) is a major leap forward from DTLS 1.2. It aligns the datagram protocol with the security and performance improvements found in TLS 1.3.

Key benefits:

  • Reduced Latency: A streamlined handshake process that requires fewer round trips, getting your data moving faster.
  • Enhanced Privacy: Handshake messages are now encrypted earlier in the process, protecting metadata and peer identities.
  • Improved Resilience: Provides protection against network attacks like spoofing, timing.
  • Modern Cryptography: Support for secure, state-of-the-art algorithms while removing obsolete and vulnerable ciphers.

Getting Started with DTLS 1.3 in wolfJSSE

To begin using DTLS 1.3, you will need to download the latest wolfSSL JNI/JSSE bundle or clone from the wolfSSL JNI/JSSE repository. wolfJSSE remains highly portable and can be built for Linux, macOS, Windows, and Android. Detailed build instructions are available in the wolfSSL JNI/JSSE Manual.

Using the Example Applications

To help you integrate this new protocol, we have included reference implementations for both a DTLS 1.3 client and server. You can compile these examples using the included Ant script:

./java.sh
ant
ant examples

The example scripts can be found in ./examples/provider and can be run from the root directory. To see the protocol in action, you can run the server and client in separate terminals:

Start the Server:

./examples/provider/DtlsServerEngine.sh

Start the Client:

./examples/provider/DtlsClientEngine.sh

You should see the handshake progress through the debug output, confirming the transition to encrypted application data using the DTLS 1.3 protocol.

./examples/provider/DtlsServerEngine.sh

DTLS 1.3 Server listening on port 11113
DTLS 1.3 Server Engine created
Waiting for client connection...
Client connected from /127.0.0.1:62797
DEBUG: Sent packet with 176 bytes
DEBUG: Received packet with 383 bytes
DEBUG: Sent packet with 176 bytes
DEBUG: Sent packet with 36 bytes
DEBUG: Sent packet with 69 bytes
DEBUG: Sent packet with 721 bytes
DEBUG: Sent packet with 109 bytes
DEBUG: Sent packet with 66 bytes
DEBUG: Received packet with 908 bytes
DEBUG: Received packet with 110 bytes
DEBUG: Received packet with 66 bytes
DEBUG: Sent packet with 72 bytes
DEBUG: Sent packet with 255 bytes
DTLS handshake completed successfully
Pausing briefly before processing application data...
DEBUG: Received packet with 40 bytes
DEBUG: Received packet with 49 bytes
Received from client: Hello from DTLS 1.3 Client!
Echoing message back to client
DEBUG: Sent packet with 49 bytes
Closing connection...
Connection closed

./examples/provider/DtlsClientEngine.sh 

Client socket created, connecting to localhost:11113
DTLS 1.3 Client Engine created
Starting DTLS handshake...
DEBUG: Sent packet with 310 bytes to localhost/127.0.0.1:11113
DEBUG: Received packet with 176 bytes from /127.0.0.1:11113
DEBUG: Sent packet with 383 bytes to localhost/127.0.0.1:11113
DEBUG: Received packet with 176 bytes from /127.0.0.1:11113
DEBUG: Received packet with 36 bytes from /127.0.0.1:11113
DEBUG: Received packet with 69 bytes from /127.0.0.1:11113
DEBUG: Received packet with 721 bytes from /127.0.0.1:11113
DEBUG: Received packet with 109 bytes from /127.0.0.1:11113
DEBUG: Received packet with 66 bytes from /127.0.0.1:11113
DEBUG: Sent packet with 908 bytes to localhost/127.0.0.1:11113
DEBUG: Sent packet with 110 bytes to localhost/127.0.0.1:11113
DEBUG: Sent packet with 66 bytes to localhost/127.0.0.1:11113
DEBUG: Received packet with 72 bytes from /127.0.0.1:11113
DTLS handshake completed successfully
Processing post-handshake session tickets...
Received post-handshake packet of 255 bytes, processing...
Processed post-handshake packet: OK, consumed: 255, produced: 0
Pausing briefly before sending data...
Pausing after handshake to allow connection to stabilize...
Sending application data: Hello from DTLS 1.3 Client!
DEBUG: Sent packet with 40 bytes to localhost/127.0.0.1:11113
DEBUG: Sent packet with 49 bytes to localhost/127.0.0.1:11113
Waiting for server response (allowing time for processing)...
Now attempting to receive server response...
Waiting for application data packet from server...
Received packet of 49 bytes
Raw bytes: 2F 34 E7 00 2C 31 01 25 AA 8C 83 E3 56 EA F9 DF 64 58 8E A4 ...
Unwrap result: OK, consumed: 49, produced: 27
Successfully decrypted data: Hello from DTLS 1.3 Client!
Closing connection...
Connection closed

Technical DTLS Highlights in v1.16.0

Beyond the core protocol support, this release includes enhancements specifically for DTLS 1.3.

Connection ID (CID) Support: Wraps native wolfSSL CID functions for improved reliability for connections where IP addresses or ports might change (e.g., mobile roaming), preventing session drops. To enable CID support, include –enable-dtlscid in your wolfSSL configuration.

The next steps show how run an example with CID:

./java.sh
ant
ant examples

Start Server:

./examples/server.sh -u -v 4 -cid

Start Client:

./examples/client.sh -u -v 4 -cid

When CID is active, the debug output will confirm the extension is enabled and display the specific RX/TX IDs being used for the session.

./examples/server.sh -u -v 4 -cid
Registered I/O callbacks
Registered DTLS cookie callback
Started server at local/127.0.0.1, port 11111

waiting for client connection...
client connection received from /127.0.0.1 at port 60263

Registered I/O callback user ctx
Registered DTLS cookie callback ctx
Enabled DTLS CID extension
Hello from Java verify callback!
issuer : /C=US/ST=Montana/L=Bozeman/O=wolfSSL_2048/OU=Programming-2048/CN=www.wolfssl.com/emailAddress=info@wolfssl.com
subject : /C=US/ST=Montana/L=Bozeman/O=wolfSSL_2048/OU=Programming-2048/CN=www.wolfssl.com/emailAddress=info@wolfssl.com
altname = example.com
altname = 127.0.0.1
SSL version is DTLSv1.3
SSL cipher suite is TLS_AES_256_GCM_SHA384

Testing DTLS CID APIs:
dtlsCidIsEnabled: 1
dtlsCidGetRxSize: 5
dtlsCidGetRx: 06 07 08 09 0A 
dtlsCidGet0Rx: 06 07 08 09 0A 
dtlsCidGetTxSize: 5
dtlsCidGetTx: 01 02 03 04 05 
dtlsCidGet0Tx: 01 02 03 04 05 
dtlsCidMaxSize: 10

client says: hello from jni

waiting for client connection...
client connection received from /127.0.0.1 at port 60263

Registered I/O callback user ctx
Registered DTLS cookie callback ctx
Enabled DTLS CID extension

./examples/client.sh -u -v 4 -cid
Registered I/O callbacks
Enabled DTLS CID extension
Registered I/O callback user contexts
Hello from Java verify callback!
Hello from Java verify callback!
issuer : /C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com
subject : /C=US/ST=Montana/L=Bozeman/O=wolfSSL/OU=Support/CN=www.wolfssl.com/emailAddress=info@wolfssl.com
altname = example.com
altname = 127.0.0.1
SSL version is DTLSv1.3
SSL cipher suite is TLS_AES_256_GCM_SHA384

Testing DTLS CID APIs:
dtlsCidIsEnabled: 1
dtlsCidGetRxSize: 5
dtlsCidGetRx: 01 02 03 04 05 
dtlsCidGet0Rx: 01 02 03 04 05 
dtlsCidGetTxSize: 5
dtlsCidGetTx: 06 07 08 09 0A 
dtlsCidGet0Tx: 06 07 08 09 0A 
dtlsCidMaxSize: 10

got back: I hear you fa shizzle, from Java!
Saved native WOLFSSL_SESSION

If you have questions about implementing DTLS 1.3 or need assistance with your specific use case, please contact us at facts@wolfssl.com or call us at +1 425 245 8247.

Download wolfSSL Now