wolfSSL is continuously improving its support for DTLS (Datagram Transport Layer Security) to make it easier for developers to handle connection IDs and implement stateless DTLS services. In this blog post, we’ll explore the new APIs introduced in wolfSSL 5.7.6 that simplify these tasks.
DTLS is a variant of TLS designed for datagram-based transports like UDP. It’s widely used in IoT and real-time applications where packet loss and reordering are common. Connection IDs allow to tag each connection so that they can be maintained despite network changes, reducing rehandshake frequency and enhancing security with features like encrypted record types and padding for privacy. The wolfSSL stack allows the server to establish new connections in a stateless manner by not allocating any extra resources until the client can prove that they can reply to server packets. Managing CIDs and stateless operations can be challenging, but wolfSSL has introduced new features to streamline this process.
Demultiplexing DTLS messages for a server involves distinguishing between multiple client connections using a single socket. When data arrives on the socket, the server reads the packet and extracts the source IP address, port, and the connection ID. This information is then used to search through a list of active connections, matching the incoming packet’s source details with existing connections. The matching is done either based on the source address of the received datagram or on the CID found in the message itself. If a match is found, the data is processed by that connection. If no match is found, it attempts to establish a new connection. This method ensures each packet is correctly routed to its respective connection, allowing multiple clients to communicate over a single socket efficiently without dropping any packet.
wolfDTLS_accept_stateless
This function allows accepting DTLS connections in a stateless manner. It’s designed to use a single WOLFSSL object to listen to all new connections and indicate to the user when the WOLFSSL object has entered stateful handling and should no longer be used for new connections.
Example:
WOLFSSL* ssl; do { rc = wolfDTLS_accept_stateless(ssl); if (rc == WOLFSSL_FATAL_ERROR) { /* re-allocate the ssl object with wolfSSL_free() and wolfSSL_new() */ } } while (rc != WOLFSSL_SUCCESS); rc = wolfSSL_accept(ssl); if (rc != SSL_SUCCESS) { /* Handle error */ }
wolfSSL_inject
The `wolfSSL_inject` function allows you to inject application data directly into the WOLFSSL object, bypassing the usual IO calls. This is useful when data needs to be read from a single place and demultiplexed into multiple connections. The caller should then call wolfSSL_read() to extract the plaintext data from the WOLFSSL object.
Example:
int rc; WOLFSSL* ssl; byte data[2000]; sz = recv(fd, data, sizeof(data), 0); if (sz <= 0) { /* Handle error */ } /* Inject received data */ rc = wolfSSL_inject(ssl, data, sz); if (rc != WOLFSSL_SUCCESS) { /* Handle error */ }
wolfSSL_dtls_set_pending_peer
This function is introduced to handle the peer address when using Connection IDs. It sets a pending peer that will be upgraded to a regular peer when the next record is successfully de-protected. This should be used with Connection ID's to allow seamless and safe transition to a new peer address. This function can be called for every incoming datagram or when an address change is detected.
Example:
WOLFSSL* ssl; sockaddr_in addr; rc = wolfSSL_dtls_set_pending_peer(ssl, &addr, sizeof(addr)); if (rc != WOLFSSL_SUCCESS) { /* Handle error */ }
wolfSSL_is_stateful
This function checks if the current SSL session is stateful. This can be useful for determining whether the listening WOLFSSL object is still waiting to be associated with a single peer or if it has already progressed to handling a single connection.
Example:
WOLFSSL* ssl; byte isStateful; rc = wolfSSL_accept(ssl); /* rc might indicate failure when using non-blocking sockets */ if (wolfSSL_is_stateful(ssl)) { /* Session is stateful */ } else { /* Session is stateless */ }
wolfSSL_dtls_cid_parse
This function parses a CID from a DTLS message. This is useful for extracting and handling connection IDs in your application.
Example:
WOLFSSL* ssl; /* DTLS 1.2 app data containing CID */ byte cid12[] = "\x19\xfe\xfd\x00\x01\x00\x00\x00\x00\x00\x01\x77\xa3\x79\x34\xb3" \ "\xf1\x1f\x34\x00\x1f\xdb\x8c\x28\x25\x9f\xe1\x02\x26\x77\x1c\x3a" \ "\x50\x1b\x50\x99\xd0\xb5\x20\xd8\x2c\x2e\xaa\x36\x36\xe0\xb7\xb7" \ "\xf7\x7d\xff\xb0"; size_t cid_len = 8; const unsigned char* cid = wolfSSL_dtls_cid_parse(cid12, sizeof(cid12), cid_len); if (cid == NULL) { /* Handle missing CID */ }
wolfSSL_SSLDisableRead and wolfSSL_SSLEnableRead
These functions allow you to control the reading of data from the IO layer. `wolfSSL_SSLDisableRead` disables read operations, while `wolfSSL_SSLEnableRead` re-enables them.
Example:
WOLFSSL* ssl; /* Disable reading */ wolfSSL_SSLDisableRead(ssl); /* Perform some operations */ /* Re-enable reading */ wolfSSL_SSLEnableRead(ssl);
These new APIs in wolfSSL make handling DTLS connection IDs and implementing stateless services easier and more efficient. By providing direct data injection, pending peer management, state checks, and read control, wolfSSL continues to enhance its support for secure datagram-based communications. For more information about new and existing API visit our manual and take a look at our examples.
If you have questions about any of the above, please contact us at facts@wolfSSL.com or +1 425 245 8247.
Download wolfSSL Now