This chapter contains a description of all NetX Duo Secure DTLS services (listed below) in alphabetic order.
In the Return Values section in the following API descriptions, values in BOLD are not affected by the NX_SECURE_DISABLE_ERROR_CHECKING macro that is used to disable API error checking, while non-bold values are completely disabled.
Start a NetX Duo Secure DTLS Client Session
UINT nx_secure_dtls_client_session_start(
NX_SECURE_DTLS_SESSION *dtls_session,
NX_UDP_SOCKET *udp_socket,
NXD_ADDRESS *ip_address, UINT port,
UINT wait_option);
This service starts a DTLS Client session, connecting to the server at the provided IP address and UDP port, using the provided UDP socket for network communications.
The DTLS session control block must be initialized prior to calling this service using nx_secure_dtls_session_create. Additionally, the DTLS Client requires that at least one trusted CA certificate has been added to the session using nx_secure_dtls_session_trusted_certificate_add or Pre-Shared Keys are enabled and configured.
Threads
/* Sockets, sessions, certificates defined in global static space to preserve
application stack. */
NX_SECURE_DTLS_SESSION client_dtls_session;
/* Trusted certificate structure and raw data. */
NX_SECURE_X509_CERT trusted_cert;
const UCHAR trusted_cert_der = { … };
/* Cryptography routines and crypto work buffers. */
extern const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers;
UCHAR crypto_metadata[9000];
/* Packet reassembly buffer for decryption. */
UCHAR packet_buffer[4000];
/* Remote certificate buffer for incoming certificates. */
#define REMOTE_CERT_SIZE (sizeof(NX_SECURE_X509_CERT) + 2000)
#define REMOTE_CERT_NUMBER (3)
UCHAR remote_certs_buffer[REMOTE_CERT_SIZE * REMOTE_CERT_NUMBER];
/* Application thread where TLS session is started. */
void application_thread()
{
NXD_ADDRESS server_ip;
/* Create a TLS session for our socket. Ciphers and metadata defined
elsewhere. See nx_secure_tls_session_create reference for more
information. */
status = nx_secure_dtls_session_create(&client_dtls_session,
&nx_crypto_tls_ciphers,
crypto_metadata,
sizeof(crypto_metadata),
packet_buffer,
sizeof(packet_buffer),
REMOTE_CERT_NUMBER,
remote_certs_buffer,
sizeof(remote_certs_buffer));
/* Check for error. */
if(status)
{
printf("Error in function nx_secure_dtls_session_create: 0x%x\n", status);
}
/* Initialize our trusted certificate. See section "Importing X.509
Certificates into NetX Duo Secure" for more information. */
nx_secure_x509_certificate_initialize(&trusted_certificate,
trusted_cert_der,
trusted_cert_der_len,
NX_NULL, 0, NX_NULL, 0,
NX_SECURE_X509_KEY_TYPE_NONE);
/* Add the certificate to the local store using a numeric ID. */
nx_secure_dtls_session_trusted_certificate_add(&client_dtls_session,
&certificate, 1);
/* Set up IP address of remote host. */
server_ip.nxd_ip_version = NX_IP_VERSION_V4;
server_ip.nxd_ip_address.v4 = IP_ADDRESS(192, 168, 1, 150);
/* Now we can start the DTLS session as normal. */
status = nx_secure_dtls_client_session_start(&client_dtls_session,
&udp_socket, &server_ip,
4443,
NX_IP_PERIODIC_RATE);
if(status != NX_SUCCESS)
{
/* Error! */
return(status);
}
/* Add data to send packet as usual for NX_PACKET and send to server. */
status = nx_secure_dtls_session_send(&client_dtls_session, &send_packet,
&server_ip, 4443);
/* Receive response from server. */
status = nx_secure_dtls_session_receive(&client_dtls_session, &receive_packet,
NX_IP_PERIODIC_RATE);
/* Process response. */
/* Shut down DTLS session. */
status = nx_secure_dtls_session_end(&client_dtls_session, NX_IP_PERIODIC_RATE);
/* Clean up. */
status = nx_secure_dtls_session_delete(&client_dtls_session);
}
Allocate a packet for a NetX Duo Secure DTLS Session
UINT nx_secure_dtls_packet_allocate(
NX_SECURE_DTLS_SESSION *session_ptr,
NX_PACKET_POOL *pool_ptr,
NX_PACKET **packet_ptr,
ULONG wait_option);
This service allocates an NX_PACKET for the specified active DTLS session from the specified NX_PACKET_POOL. This service should be called by the application to allocate data packets to be sent over a DTLS connection. The DTLS session must be initialized before calling this service.
The allocated packet is properly initialized so that DTLS header and footer data may be added after the packet data is populated. The behavior is otherwise identical to nx_packet_allocate.
Threads
/* Allocate a new DTLS packet from the previously created packet pool and
previously initialized DTLS session. */
status = nx_secure_dtls_packet_allocate(&dtls_session, &pool_0, &packet_ptr,
NX_WAIT_FOREVER);
/* If status is NX_SUCCESS, the newly allocated packet pointer is found in
the variable packet_ptr. */
Add a Pre-Shared Key to a NetX Duo Secure DTLS Session
UINT nx_secure_dtls_psk_add(
NX_SECURE_DTLS_SESSION *session_ptr,
UCHAR *pre_shared_key,
UINT psk_length,
UCHAR *psk_identity,
UINT identity_length,
UCHAR *hint,
UINT hint_length);
This service adds a Pre-Shared Key (PSK), its identity string, and an identity hint to a DTLS Session control block. The PSK is used in place of a digital certificate when PSK ciphersuites are enabled and used.
Threads
/* PSK value. */
UCHAR psk[] = { 0x1a, 0x2b, 0x3c, 0x4d };
/* Add PSK to DTLS session. */
status = nx_secure_dtls_psk_add(&dtls_session, psk,
sizeof(psk), "psk_1", 4,
"Client_identity", 15);
/* If status is NX_SUCCESS the PSK was successfully added. */
Create a NetX Duo Secure DTLS Server
UINT nx_secure_dtls_server_create(
NX_SECURE_DTLS_SERVER *server_ptr,
NX_IP *ip_ptr,
UINT port,
ULONG timeout,
VOID *session_buffer,
UINT session_buffer_size,
const NX_SECURE_TLS_CRYPTO *crypto_table,
VOID *crypto_metadata_buffer,
ULONG crypto_metadata_size,
UCHAR *packet_reassembly_buffer,
UINT packet_reassembly_buffer_size,
UINT (*connect_notify)(
NX_SECURE_DTLS_SESSION *dtls_session,
NXD_ADDRESS *ip_address, UINT port),
UINT (*receive_notify)(NX_SECURE_DTLS_SESSION *dtls_session));
This service creates an instance of a DTLS server to handle incoming DTLS requests on a particular UDP port. Due to the fact that UDP is stateless, DTLS requests from multiple clients can come in on a single port while other DTLS sessions are active. Thus, the server is needed to maintain active sessions and properly route incoming messages to the proper handler.
The ip_ptr parameter points to an NX_IP instance to be used for the internal UDP socket associated with the DTLS Server (and stored in the NX_SECURE_DTLS_SERVER control block). The IP instance and port are used to define the UDP interface upon which the server is instantiated with the nx_secure_dtls_server_start service.
The session buffer parameter is used to hold the control blocks for all the possible simultaneous DTLS sessions for the DTLS server. It should be allocated with a size that is an even multiple of the size of the NX_SECURE_DTLS_SESSION control block structure.
To calculate the necessary metadata size, the API nx_secure_tls_metadata_size_calculate may be used.
The packet_reassembly_buffer parameter is used by DTLS to reassemble UDP datagrams into a complete DTLS record for the purposes of decryption and should be large enough to accommodate the largest expected DTLS record (16KB is the DTLS maximum record size but many applications don’t send that much data in a single record).
The connect_notify callback routine is invoked whenever a new DTLS client connects to the server. It is up to the application to then start the DTLS session using the service nx_secure_dtls_server_session_start. While the session may be started in the callback itself, it is recommended that the callback only be used to notify the application thread (or dedicated DTLS thread created by the application) of the connection as the callback is invoked by the IP thread which is used to process all lower-level network processing (e.g. UDP). This can be as simple as saving the DTLS session parameter (provided as a parameter to the callback) and invoking nx_secure_dtls_server_session_start in the other thread. The connect_notify callback should generally return NX_SUCCESS.
The receive_notify callback routine is invoked whenever a DTLS record is received that matches an existing established DTLS session (the remote host IP address and port are used to identify an existing session). This represents the “application data” that is encrypted and sent over DTLS. The application must call the service nx_secure_dtls_session_receive on the provided DTLS session to retrieve the received data. As with the connect_receive callback, it is recommended that the session be passed to another thread to handle the message processing as the callback is invoked from the IP thread. The receive_notify callback should generally return NX_SUCCESS.
Threads
#define DTLS_SERVER_SESSION (3)
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SERVER dtls_server;
/* Allocate space for DTLS sessions in the DTLS server. */
UCHAR dtls_server_session_buffer[sizeof(NX_SECURE_DTLS_SESSION)
* DTLS_SERVER_SESSIONS];
/* Flag used to indicate that a DTLS Client has connected. */
UINT connect_flag = 0;
/* Flag used to indicate application data reception. */
UINT receive_flag = 0;
/* Pointer to newly-connected DTLS session.
NOTE: In practice this should be an array or list in case a new connection is
attempted while a previous session is being started. */
NX_SECURE_DTLS_SESSION *new_dtls_session;
/* Pointer to session for application data receive.
NOTE: Should be an array or list as
with new_dtls_session */
NX_SECURE_DTLS_SESSION *receive_dtls_session;
/* Connect notify callback routine. */
UINT dtls_server_connect_notify(NX_SECURE_DTLS_SESSION *dtls_session, NXD_ADDRESS
*ip_address, UINT port)
{
/* NOTE: proper inter-thread communication procedures (e.g. mutex handling)
Omitted for clarity. */
/* Notify application thread that a connection request has been received. */
connect_flag = 1;
new_dtls_session = dtls_session;
return(NX_SUCCESS);
}
/* Receive notify callback routine invoked when DTLS application data is received
on an existing DTLS server session. */
UINT dtls_server_receive_notify(NX_SECURE_DTLS_SESSION *dtls_session)
{
/* Receive and process DTLS record.
NOTE: Mutex handling omitted for clarity. */
receive_flag = 1;
receive_dtls_session = dtls_session;
return(NX_SUCCESS);
}
/* Primary application thread for handling DTLS server operations. */
void dtls_server_thread(void)
{
NX_PACKET *send_packet;
NX_PACKET *receive_packet;
UINT status;
/* Setup DTLS Server instance. */
status = nx_secure_dtls_server_create(&dtls_server, &ip_instance,
LOCAL_SERVER_PORT,
NX_IP_PERIODIC_RATE, dtls_server_session_buffer,
sizeof(dtls_server_session_buffer),
&tls_crypto_table, crypto_metadata_buffer,
sizeof(crypto_metadata_buffer), packet_buffer,
sizeof(packet_buffer),
dtls_server_connect_notify,
dtls_server_receive_notify);
/* Initialize local server identity certificate with key and add to server. */
status = nx_secure_x509_certificate_initialize(&certificate, device_cert_der,
device_cert_der_len, NX_NULL, 0,
device_cert_key_der, device_cert_key_der_len,
NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);
/* Add local server identity certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_server_local_certificate_add(&dtls_server,
&certificate, 1);
/* Start server. */
status = nx_secure_dtls_server_start(&dtls_server);
/* Loop continuously to handle incoming data. */
while(1)
{
/* Check for new connections. Muxtex handling omitted for clarity. */
if(connect_flag)
{
/* We have a new connection attempt, start the DTLS session. */
status = nx_secure_dtls_server_session_start(new_dtls_session,
NX_IP_PERIODIC_RATE);
}
/* Check for received application data. */
if(receive_flag)
{
/* We have received data over a previously-established DTLS session.
Mutex handling omitted for clarity. */
Status = nx_secure_dtls_session_receive(receive_dtls_session,
&receive_packet,
NX_IP_PERIODIC_RATE);
/* Process received data… */
/* Prepare and send response to client. */
status = nx_secure_dtls_packet_allocate(receive_dtls_session, &packet_pool,
&send_packet, NX_IP_PERIODIC_RATE);
/* Check for errors and prepare response data
(e.g. nx_packet_data_append). */
/* Send response to client. */
status = nx_secure_dtls_server_session_send(receive_dtls_session,
send_packet);
}
/* If not processing connections or received data,
let the thread sleep. */
if(!connect_flag && !receive_flag)
{
tx_thread_sleep(100);
}
}
/* Server processing is done, stop the server
instance from accepting requests. */
status = nx_secure_dtls_server_stop(&dtls_server);
/* If we exit the processing loop, clean up the server. */
status = nx_secure_dtls_server_delete(&dtls_server);
}
Free up resources used by a NetX Duo Secure DTLS Server
UINT nx_secure_dtls_server_delete(NX_SECURE_DTLS_SERVER *server_ptr);
This service frees up the resources allocated to a DTLS Server instance, including the internal UDP socket used by the server.
Threads
#define DTLS_SERVER_SESSION (3)
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SERVER dtls_server;
/* Allocate space for DTLS sessions in the DTLS server. */
UCHAR dtls_server_session_buffer[sizeof(NX_SECURE_DTLS_SESSION)
* DTLS_SERVER_SESSIONS];
/* Flag used to indicate that a DTLS Client has connected. */
UINT connect_flag = 0;
/* Flag used to indicate application data reception. */
UINT receive_flag = 0;
/* Pointer to newly-connected DTLS session.
NOTE: In practice this should be an array or list in case a new connection is
attempted while a previous session is being started. */
NX_SECURE_DTLS_SESSION *new_dtls_session;
/* Pointer to session for application data receive.
NOTE: Should be an array or list as
with new_dtls_session */
NX_SECURE_DTLS_SESSION *receive_dtls_session;
/* Connect notify callback routine. */
UINT dtls_server_connect_notify(NX_SECURE_DTLS_SESSION *dtls_session, NXD_ADDRESS
*ip_address, UINT port)
{
/* NOTE: proper inter-thread communication procedures (e.g. mutex handling)
Omitted for clarity. */
/* Notify application thread that a connection request has been received. */
connect_flag = 1;
new_dtls_session = dtls_session;
return(NX_SUCCESS);
}
/* Receive notify callback routine invoked when DTLS application data is received
on an existing DTLS server session. */
UINT dtls_server_receive_notify(NX_SECURE_DTLS_SESSION *dtls_session)
{
/* Receive and process DTLS record.
NOTE: Mutex handling omitted for clarity. */
receive_flag = 1;
receive_dtls_session = dtls_session;
return(NX_SUCCESS);
}
/* Primary application thread for handling DTLS server operations. */
void dtls_server_thread(void)
{
NX_PACKET *send_packet;
NX_PACKET *receive_packet;
UINT status;
/* Setup DTLS Server instance. */
status = nx_secure_dtls_server_create(&dtls_server, &ip_instance,
LOCAL_SERVER_PORT,
NX_IP_PERIODIC_RATE,
dtls_server_session_buffer,
sizeof(dtls_server_session_buffer),
&tls_crypto_table,
crypto_metadata_buffer,
sizeof(crypto_metadata_buffer),
packet_buffer, sizeof(packet_buffer),
dtls_server_connect_notify,
dtls_server_receive_notify);
/* Check for errors. */
/* Initialize local server identity certificate with key and add to server. */
status = nx_secure_x509_certificate_initialize(&certificate, device_cert_der,
device_cert_der_len,
NX_NULL, 0,
device_cert_key_der,
device_cert_key_der_len,
NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);
/* Add local server identity certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_server_local_certificate_add(&dtls_server,
&certificate, 1);
/* Start server. */
status = nx_secure_dtls_server_start(&dtls_server);
/* Loop continuously to handle incoming data. */
while(1)
{
/* Check for new connections. Muxtex handling omitted for clarity. */
if(connect_flag)
{
/* We have a new connection attempt, start the DTLS session. */
status = nx_secure_dtls_server_session_start(new_dtls_session,
NX_IP_PERIODIC_RATE);
}
/* Check for received application data. */
if(receive_flag)
{
/* We have received data over a previously-established DTLS session.
Mutex handling omitted for clarity. */
Status = nx_secure_dtls_session_receive(receive_dtls_session,
&receive_packet,
NX_IP_PERIODIC_RATE);
/* Process received data… */
/* Prepare and send response to client. */
status = nx_secure_dtls_packet_allocate(receive_dtls_session,
&packet_pool,
&send_packet,
NX_IP_PERIODIC_RATE);
/* Send response to client. */
status = nx_secure_dtls_server_session_send(receive_dtls_session,
send_packet);
}
/* If not processing connections or received data, let the thread sleep. */
if(!connect_flag && !receive_flag)
{
tx_thread_sleep(100);
}
}
/* If we exit the processing loop, clean up the server. */
status = nx_secure_dtls_server_delete(&dtls_server);
}
Add a local server identity certificate to a NetX Duo Secure DTLS Server
UINT nx_secure_dtls_server_local_certificate_add(
NX_SECURE_DTLS_SERVER *server_ptr,
NX_SECURE_X509_CERT *certificate,
UINT cert_id);
This service adds a local server identity certificate to a DTLS Server instance. At least one identity certificate is required for clients to connect to a DTLS server unless an alternate authentication mechanism (e.g. Pre-Shared Keys) is used.
The cert_id parameter is a numeric, non-zero identifier for the certificate. This enables the certificate to be easily removed or found in the event there are multiple identity certificates with the same X.509 Common Name present in the DTLS server store. See the NetX Duo Secure TLS User Guide for more information about X.509 server certificates.
Threads
See reference for *nx_secure_dtls_server_create for a more complete example.
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SERVER dtls_server;
/* Certificate control block and data. */
NX_SECURE_X509_CERT certificate;
UCHAR certificate_der_data[] = { … };
UCHAR certificate_key_der_data[] = { … };
/* Primary application thread for handling DTLS server operations. */
void dtls_server_thread(void)
{
UINT status;
/* Setup DTLS Server instance. */
status = nx_secure_dtls_server_create(&dtls_server, &ip_instance,
LOCAL_SERVER_PORT,
NX_IP_PERIODIC_RATE,
dtls_server_session_buffer,
sizeof(dtls_server_session_buffer),
&tls_crypto_table,
crypto_metadata_buffer,
sizeof(crypto_metadata_buffer),
packet_buffer,
sizeof(packet_buffer),
dtls_server_connect_notify,
dtls_server_receive_notify);
/* Check for errors. */
/* Initialize local server identity certificate with key and add to server. */
status = nx_secure_x509_certificate_initialize(&certificate,
certificate_der_data,
sizeof(certificate_der_data),
NX_NULL, 0,
certificate_key_der_data,
sizeof(certificate_key_der_data),
NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);
/* Add local server identity certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_server_local_certificate_add(&dtls_server,
&certificate, 1);
/* Start server. */
status = nx_secure_dtls_server_start(&dtls_server);
/* Loop continuously to handle incoming data. */
while(1)
{
/* Process incoming requests and data. */
}
}
Remove a local server identity certificate from a NetX Duo Secure DTLS Server
UINT nx_secure_dtls_server_local_certificate_remove(
NX_SECURE_DTLS_SERVER *server_ptr,
UCHAR *common_name,
UINT common_name_length,
UINT cert_id);
This service removes a local server identity certificate from a DTLS Server instance. At least one identity certificate is required for clients to connect to a DTLS server unless an alternate authentication mechanism (e.g. Pre-Shared Keys) is used.
The certificate to be removed can be identified either by its X.509 Common Name or by the numeric cert_id that was assigned in the call to nx_secure_dtls_server_local_certificate_add. The cert_id is only used to identify the certificate and is maintained by the application. If the Common Name is used instead of the numeric certificate identifier, the cert_id parameter should be set to 0.
Note: Removing a certificate while a DTLS handshake is being processed will result in unexpected behavior. The service nx_secure_dtls_server_stop should be called before removing certificates.
Threads
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SERVER dtls_server;
/* Certificate control block and data. */
NX_SECURE_X509_CERT certificate;
UCHAR certificate_der_data[] = { … };
UCHAR certificate_key_der_data[] = { … };
/* Primary application thread for handling DTLS server operations. */
void dtls_server_thread(void)
{
UINT status;
/* Setup DTLS Server instance. */
status = nx_secure_dtls_server_create(&dtls_server, &ip_instance,
LOCAL_SERVER_PORT, NX_IP_PERIODIC_RATE,
dtls_server_session_buffer,
sizeof(dtls_server_session_buffer),
&tls_crypto_table, crypto_metadata_buffer,
sizeof(crypto_metadata_buffer), packet_buffer,
sizeof(packet_buffer),
dtls_server_connect_notify,
dtls_server_receive_notify);
/* Check for errors. */
/* Initialize local server identity certificate with key and add to server. */
status = nx_secure_x509_certificate_initialize(&certificate,
certificate_der_data,
sizeof(certificate_der_data),
NX_NULL, 0, certificate_key_der_data,
sizeof(certificate_key_der_data),
NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);
/* Add local server identity certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_server_local_certificate_add(&dtls_server,
&certificate, 1);
/* Start server. */
status = nx_secure_dtls_server_start(&dtls_server);
/* Process client requests, etc… */
/* Stop the server before removing a certificate. */
Status = nx_secure_dtls_server_stop(&dtls_server);
/* At some point in the future we decide to remove the certificate we added.
We can use the certificate identifier we passed into the call to
nx_secure_dtls_local_certificate_add (value = 1); */
status = nx_secure_dtls_server_local_certificate_remove(&dtls_server,
NX_NULL, 0, 1);
}
Assign optional notification callback routines to a NetX Duo Secure DTLS Server
UINT nx_secure_dtls_server_notify_set(
NX_SECURE_DTLS_SERVER *server_ptr,
UINT (*disconnect_notify)(NX_SECURE_DTLS_SESSION *dtls_session),
UINT (*error_notify)(
NX_SECURE_DTLS_SESSION *dtls_session,
UINT error_code));
This service can be used to add optional notification callback routines to a DTLS server. Either callback parameter may be passed as NX_NULL if only one callback is desired.
The disconnect_notify callback is invoked when a remote client ends a DTLS session. The dtls_session parameter is the session instance that was closed. The callback should generally return NX_SUCCESS.
The error_notify callback is invoked whenever a DTLS error or timeout occurs. The dtls_session parameter is the session instance for which the error occurred, and error_code is the numeric status code for the error that caused the issue (see Appendix A)
NetX Duo Secure Return/Error Codes for a list of error codes that may be returned). The callback should generally return NX_SUCCESS.
Threads
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SERVER dtls_server;
UINT disconnect_notify(NX_SECURE_DTLS_SESSION *dtls_session)
{
NXD_ADDRESS client_ip_addr;
UINT client_port;
UINT local_port;
/* We have received a disconnection notice (CloseNotify message) from a
remote client. Application can use the dtls_session parameter for any
desired processing. */
/* See what client disconnected by extracting its IP address and port.
NOTE: depending on how the session ended, the client information may
no longer be available. */
status = nx_secure_dtls_session_client_info_get(dtls_session,
&ip_addr,
&client_port,
&local_port);
return(NX_SUCCESS);
}
UINT error_notify(NX_SECURE_DTLS_SESSION *dtls_session, UINT error_code)
{
/* The DTLS server has encountered an error or timeout condition. We
can use the error_code parameter to determine the error and we
can insect the dtls_session for more information. */
return(NX_SUCCESS);
}
/* Primary application thread for handling DTLS server operations. */
void dtls_server_thread(void)
{
UINT status;
/* Setup DTLS Server instance. */
status = nx_secure_dtls_server_create(&dtls_server, &ip_instance,
LOCAL_SERVER_PORT,
NX_IP_PERIODIC_RATE,
dtls_server_session_buffer,
sizeof(dtls_server_session_buffer),
&tls_crypto_table,
crypto_metadata_buffer,
sizeof(crypto_metadata_buffer),
packet_buffer,
sizeof(packet_buffer),
dtls_server_connect_notify,
dtls_server_receive_notify);
/* Check for errors. */
/* Other setup (e.g. certificates) goes here … */
status = nx_secure_dtls_server_notify_set(&dtls_server, disconnect_notify,
error_notify);
/* Start server. */
status = nx_secure_dtls_server_start(&dtls_server);
/* Process client requests, etc… */
}
Add a Pre-Shared Key to a NetX Duo Secure DTLS Server
UINT nx_secure_dtls_server_psk_add(
NX_SECURE_DTLS_SERVER *server_ptr,
UCHAR *pre_shared_key,
UINT psk_length,
UCHAR *psk_identity,
UINT identity_length,
UCHAR *hint,
UINT hint_length);
This service adds a Pre-Shared Key (PSK), its identity string, and an identity hint to a DTLS Server control block. The PSK is used in place of a digital certificate when PSK ciphersuites are enabled and used.
The PSK that is added is replicated across all the DTLS sessions assigned to the DTLS Server (via the session buffer given in the call to nx_secure_dtls_server_create).
Threads
/* PSK value. */
UCHAR psk[] = { 0x1a, 0x2b, 0x3c, 0x4d };
/* Add PSK to DTLS session. */
status = nx_secure_dtls_server_psk_add(&dtls_server, psk, sizeof(psk), "psk_1",
4, "Client_identity", 15);
/* If status is NX_SUCCESS the PSK was successfully added. */
Send data over a DTLS session established with a NetX Duo Secure DTLS Server
UINT nx_secure_dtls_server_session_send(
NX_SECURE_DTLS_SESSION *session_ptr,
NX_PACKET *packet_ptr);
This service sends a packet of data over an established DTLS Server session to a remote DTLS Client host. The session used is obtained in the receive_notify callback routine provided to nx_secure_dtls_session_create.
The data provided in the packet, which must be allocated using nx_secure_dtls_packet_allocate, is encrypted using the DTLS session cryptographic parameters and routines and then sent to the remote host over the DTLS Server internal UDP port to the attached client’s IP address and port (stored in the DTLS Session).
Threads
#define DTLS_SERVER_SESSION (3)
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SERVER dtls_server;
/* Flag used to indicate application data reception. */
UINT receive_flag = 0;
/* Pointer to session for application data receive.
NOTE: Should be an array or list as
with new_dtls_session */
NX_SECURE_DTLS_SESSION *receive_dtls_session;
/* Receive notify callback routine invoked when DTLS application data is received
on an existing DTLS server session. */
UINT dtls_server_receive_notify(NX_SECURE_DTLS_SESSION *dtls_session)
{
/* Receive and process DTLS record.
NOTE: Mutex handling omitted for clarity. */
receive_flag = 1;
receive_dtls_session = dtls_session;
return(NX_SUCCESS);
}
/* Primary application thread for handling DTLS server operations. */
void dtls_server_thread(void)
{
NX_PACKET *send_packet;
NX_PACKET *receive_packet;
UINT status;
/* Setup DTLS Server instance. */
status = nx_secure_dtls_server_create(&dtls_server, &ip_instance,
LOCAL_SERVER_PORT,
NX_IP_PERIODIC_RATE,
dtls_server_session_buffer,
sizeof(dtls_server_session_buffer),
&tls_crypto_table,
crypto_metadata_buffer,
sizeof(crypto_metadata_buffer),
packet_buffer,
sizeof(packet_buffer),
dtls_server_connect_notify,
dtls_server_receive_notify);
/* Check for errors. */
/* Initialize local server identity certificate with key
and add to server. */
status = nx_secure_x509_certificate_initialize(&certificate,
device_cert_der,
device_cert_der_len,
NX_NULL,
0, device_cert_key_der,
device_cert_key_der_len,
NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);
/* Add local server identity certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_server_local_certificate_add(&dtls_server,
&certificate, 1);
/* Start server. */
status = nx_secure_dtls_server_start(&dtls_server);
/* Loop continuously to handle incoming data. */
while(1)
{
/* Check for new connections. Muxtex handling omitted for clarity. */
if(connect_flag)
{
/* We have a new connection attempt, start the DTLS session. */
status = nx_secure_dtls_server_session_start(new_dtls_session,
NX_IP_PERIODIC_RATE);
/* Check for errors. */
}
/* Check for received application data. */
if(receive_flag)
{
/* We have received data over a previously-established DTLS session.
Mutex handling omitted for clarity. */
Status = nx_secure_dtls_session_receive(receive_dtls_session,
&receive_packet,
NX_IP_PERIODIC_RATE);
/* Process received data… */
/* Prepare and send response to client. */
status = nx_secure_dtls_packet_allocate(receive_dtls_session,
&packet_pool,
&send_packet,
NX_IP_PERIODIC_RATE);
/* Check for errors and prepare response data
(e.g. nx_packet_data_append). */
/* Send response to client. */
status = nx_secure_dtls_server_session_send(receive_dtls_session,
send_packet);
}
/* If not processing connections or received data, let the thread sleep. */
if(!connect_flag && !receive_flag)
{
tx_thread_sleep(100);
}
}
/* Server processing is done, stop the server instance
from accepting requests. */
status = nx_secure_dtls_server_stop(&dtls_server);
/* If we exit the processing loop, clean up the server. */
status = nx_secure_dtls_server_delete(&dtls_server);
}
Start a DTLS Session from a NetX Duo Secure DTLS Server
UINT nx_secure_dtls_server_session_start(
NX_SECURE_DTLS_SESSION *session_ptr,
UINT wait_option);
This service starts a DTLS Server session by performing the server-side DTLS handshake when a remote DTLS Client has connected to the server and requested a DTLS connection.
The DTLS Session is obtained in the connect_notify callback routine provided to nx_secure_dtls_server_create.
Threads
#define DTLS_SERVER_SESSION (3)
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SERVER dtls_server;
/* Allocate space for DTLS sessions in the DTLS server. */
UCHAR dtls_server_session_buffer[sizeof(NX_SECURE_DTLS_SESSION)
* DTLS_SERVER_SESSIONS];
/* Flag used to indicate that a DTLS Client has connected. */
UINT connect_flag = 0;
/* Flag used to indicate application data reception. */
UINT receive_flag = 0;
/* Pointer to newly-connected DTLS session.
NOTE: In practice this should be an array or list in case a new connection is
attempted while a previous session is being started. */
NX_SECURE_DTLS_SESSION *new_dtls_session;
/* Pointer to session for application data receive.
NOTE: Should be an array or list as
with new_dtls_session */
NX_SECURE_DTLS_SESSION *receive_dtls_session;
/* Connect notify callback routine. */
UINT dtls_server_connect_notify(NX_SECURE_DTLS_SESSION *dtls_session,
NXD_ADDRESS *ip_address, UINT port)
{
/* NOTE: proper inter-thread communication procedures (e.g. mutex handling)
Omitted for clarity. */
/* Notify application thread that a connection request has been received. */
connect_flag = 1;
new_dtls_session = dtls_session;
return(NX_SUCCESS);
}
/* Receive notify callback routine invoked when DTLS application data is received
on an existing DTLS server session. */
UINT dtls_server_receive_notify(NX_SECURE_DTLS_SESSION *dtls_session)
{
/* Receive and process DTLS record.
NOTE: Mutex handling omitted for clarity. */
receive_flag = 1;
receive_dtls_session = dtls_session;
return(NX_SUCCESS);
}
/* Primary application thread for handling DTLS server operations. */
void dtls_server_thread(void)
{
NX_PACKET *send_packet;
NX_PACKET *receive_packet;
UINT status;
/* Setup DTLS Server instance. */
status = nx_secure_dtls_server_create(&dtls_server, &ip_instance,
LOCAL_SERVER_PORT, NX_IP_PERIODIC_RATE,
dtls_server_session_buffer,
sizeof(dtls_server_session_buffer),
&tls_crypto_table, crypto_metadata_buffer,
sizeof(crypto_metadata_buffer), packet_buffer,
sizeof(packet_buffer),
dtls_server_connect_notify,
dtls_server_receive_notify);
/* Initialize local server identity certificate with key and add to server. */
status = nx_secure_x509_certificate_initialize(&certificate, device_cert_der,
device_cert_der_len, NX_NULL, 0,
device_cert_key_der,
device_cert_key_der_len,
NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);
/* Add local server identity certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_server_local_certificate_add(&dtls_server,
&certificate, 1);
/* Start server. */
status = nx_secure_dtls_server_start(&dtls_server);
/* Loop continuously to handle incoming data. */
while(1)
{
/* Check for new connections. Muxtex handling omitted for clarity. */
if(connect_flag)
{
/* We have a new connection attempt, start the DTLS session. */
status = nx_secure_dtls_server_session_start(new_dtls_session,
NX_IP_PERIODIC_RATE);
}
/* Check for received application data. */
if(receive_flag)
{
/* We have received data over a previously-established DTLS session.
Mutex handling omitted for clarity. */
Status = nx_secure_dtls_session_receive(receive_dtls_session,
&receive_packet,
NX_IP_PERIODIC_RATE);
/* Process received data… */
/* Prepare and send response to client. */
status = nx_secure_dtls_packet_allocate(receive_dtls_session,
&packet_pool, &send_packet,
NX_IP_PERIODIC_RATE);
/* Check for errors and prepare response data
(e.g. nx_packet_data_append). */
/* Send response to client. */
status = nx_secure_dtls_server_session_send(receive_dtls_session,
send_packet);
}
/* If not processing connections or received data, let the thread sleep. */
if(!connect_flag && !receive_flag)
{
tx_thread_sleep(100);
}
}
/* Server processing is done,
stop the server instance from accepting requests. */
status = nx_secure_dtls_server_stop(&dtls_server);
/* If we exit the processing loop, clean up the server. */
status = nx_secure_dtls_server_delete(&dtls_server);
}
Start a NetX Duo Secure DTLS Server instance listening on the configured UDP port
UINT nx_secure_dtls_server_start(NX_SECURE_DTLS_SERVER *server_ptr);
This service starts a DTLS Server. After the call returns, the server is active and will begin processing incoming requests from DTLS clients. The server instance must have been configured with the service nx_secure_dtls_server_create.
Note: This service binds the internal DTLS Server UDP port to the configured local port so most issues encountered will have to do with UDP communications and network configuration.
Threads
#define DTLS_SERVER_SESSION (3)
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SERVER dtls_server;
/* Allocate space for DTLS sessions in the DTLS server. */
UCHAR dtls_server_session_buffer[sizeof(NX_SECURE_DTLS_SESSION)
* DTLS_SERVER_SESSIONS];
/* Flag used to indicate that a DTLS Client has connected. */
UINT connect_flag = 0;
/* Flag used to indicate application data reception. */
UINT receive_flag = 0;
/* Pointer to newly-connected DTLS session.
NOTE: In practice this should be an array or list in case a new connection is
attempted while a previous session is being started. */
NX_SECURE_DTLS_SESSION *new_dtls_session;
/* Pointer to session for application data receive.
NOTE: Should be an array or list as
with new_dtls_session */
NX_SECURE_DTLS_SESSION *receive_dtls_session;
/* Connect notify callback routine. */
UINT dtls_server_connect_notify(NX_SECURE_DTLS_SESSION *dtls_session,
NXD_ADDRESS *ip_address, UINT port)
{
/* NOTE: proper inter-thread communication procedures (e.g. mutex handling)
Omitted for clarity. */
/* Notify application thread that a connection request has been received. */
connect_flag = 1;
new_dtls_session = dtls_session;
return(NX_SUCCESS);
}
/* Receive notify callback routine invoked when DTLS application data is received
on an existing DTLS server session. */
UINT dtls_server_receive_notify(NX_SECURE_DTLS_SESSION *dtls_session)
{
/* Receive and process DTLS record.
NOTE: Mutex handling omitted for clarity. */
receive_flag = 1;
receive_dtls_session = dtls_session;
return(NX_SUCCESS);
}
/* Primary application thread for handling DTLS server operations. */
void dtls_server_thread(void)
{
NX_PACKET *send_packet;
NX_PACKET *receive_packet;
UINT status;
/* Setup DTLS Server instance. */
status = nx_secure_dtls_server_create(&dtls_server, &ip_instance,
LOCAL_SERVER_PORT,
NX_IP_PERIODIC_RATE,
dtls_server_session_buffer,
sizeof(dtls_server_session_buffer),
&tls_crypto_table,
crypto_metadata_buffer,
sizeof(crypto_metadata_buffer),
packet_buffer,
sizeof(packet_buffer),
dtls_server_connect_notify,
dtls_server_receive_notify);
/* Initialize local server identity certificate with key and add to server. */
status = nx_secure_x509_certificate_initialize(&certificate, device_cert_der,
device_cert_der_len,
NX_NULL, 0,
device_cert_key_der,
device_cert_key_der_len,
NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);
/* Add local server identity certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_server_local_certificate_add(&dtls_server,
&certificate, 1);
/* Start server. */
status = nx_secure_dtls_server_start(&dtls_server);
/* Loop continuously to handle incoming data. */
while(1)
{
/* Check for new connections. Muxtex handling omitted for clarity. */
if(connect_flag)
{
/* We have a new connection attempt, start the DTLS session. */
status = nx_secure_dtls_server_session_start(new_dtls_session,
NX_IP_PERIODIC_RATE);
/* Check for errors. */
}
/* Check for received application data. */
if(receive_flag)
{
/* We have received data over a previously-established DTLS session.
Mutex handling omitted for clarity. */
Status = nx_secure_dtls_session_receive(receive_dtls_session,
&receive_packet,
NX_IP_PERIODIC_RATE);
/* Process received data… */
/* Prepare and send response to client. */
status = nx_secure_dtls_packet_allocate(receive_dtls_session, &packet_pool,
&send_packet, NX_IP_PERIODIC_RATE);
/* Check for errors and prepare response data
(e.g. nx_packet_data_append). */
/* Send response to client. */
status = nx_secure_dtls_server_session_send(receive_dtls_session,
send_packet);
}
/* If not processing connections or received data, let the thread sleep. */
if(!connect_flag && !receive_flag)
{
tx_thread_sleep(100);
}
}
/* If we exit the processing loop, clean up the server. */
status = nx_secure_dtls_server_delete(&dtls_server);
}
Stop an active NetX Duo Secure DTLS Server instance
UINT nx_secure_dtls_server_stop(NX_SECURE_DTLS_SERVER *server_ptr);
This service stops a DTLS Server from listening on the configure UDP port and resets all the associated DTLS sessions, halting any in-progress DTLS communications.
Threads
#define DTLS_SERVER_SESSION (3)
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SERVER dtls_server;
/* Allocate space for DTLS sessions in the DTLS server. */
UCHAR dtls_server_session_buffer[sizeof(NX_SECURE_DTLS_SESSION)
* DTLS_SERVER_SESSIONS];
/* Flag used to indicate that a DTLS Client has connected. */
UINT connect_flag = 0;
/* Flag used to indicate application data reception. */
UINT receive_flag = 0;
/* Pointer to newly-connected DTLS session.
NOTE: In practice this should be an array or list in case a new connection is
attempted while a previous session is being started. */
NX_SECURE_DTLS_SESSION *new_dtls_session;
/* Pointer to session for application data receive.
NOTE: Should be an array or list as
with new_dtls_session */
NX_SECURE_DTLS_SESSION *receive_dtls_session;
/* Connect notify callback routine. */
UINT dtls_server_connect_notify(NX_SECURE_DTLS_SESSION *dtls_session,
NXD_ADDRESS *ip_address, UINT port)
{
/* NOTE: proper inter-thread communication procedures (e.g. mutex handling)
Omitted for clarity. */
/* Notify application thread that a connection request has been received. */
connect_flag = 1;
new_dtls_session = dtls_session;
return(NX_SUCCESS);
}
/* Receive notify callback routine invoked when DTLS application data is received
on an existing DTLS server session. */
UINT dtls_server_receive_notify(NX_SECURE_DTLS_SESSION *dtls_session)
{
/* Receive and process DTLS record.
NOTE: Mutex handling omitted for clarity. */
receive_flag = 1;
receive_dtls_session = dtls_session;
return(NX_SUCCESS);
}
/* Primary application thread for handling DTLS server operations. */
void dtls_server_thread(void)
{
NX_PACKET *send_packet;
NX_PACKET *receive_packet;
UINT status;
/* Setup DTLS Server instance. */
status = nx_secure_dtls_server_create(&dtls_server, &ip_instance,
LOCAL_SERVER_PORT,
NX_IP_PERIODIC_RATE,
dtls_server_session_buffer,
sizeof(dtls_server_session_buffer),
&tls_crypto_table,
crypto_metadata_buffer,
sizeof(crypto_metadata_buffer),
packet_buffer,
sizeof(packet_buffer),
dtls_server_connect_notify,
dtls_server_receive_notify);
/* Check for errors. */
/* Initialize local server identity certificate with key and add to server. */
status = nx_secure_x509_certificate_initialize(&certificate, device_cert_der,
device_cert_der_len,
NX_NULL, 0,
device_cert_key_der,
device_cert_key_der_len,
NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);
/* Add local server identity certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_server_local_certificate_add(&dtls_server,
&certificate, 1);
/* Start server. */
status = nx_secure_dtls_server_start(&dtls_server);
/* Loop continuously to handle incoming data. */
while(1)
{
/* Check for new connections. Muxtex handling omitted for clarity. */
if(connect_flag)
{
/* We have a new connection attempt, start the DTLS session. */
status = nx_secure_dtls_server_session_start(new_dtls_session,
NX_IP_PERIODIC_RATE);
/* Check for errors. */
}
/* Check for received application data. */
if(receive_flag)
{
/* We have received data over a previously-established DTLS session.
Mutex handling omitted for clarity. */
Status = nx_secure_dtls_session_receive(receive_dtls_session,
&receive_packet,
NX_IP_PERIODIC_RATE);
/* Process received data… */
/* Prepare and send response to client. */
status = nx_secure_dtls_packet_allocate(receive_dtls_session,
&packet_pool,
&send_packet,
NX_IP_PERIODIC_RATE);
/* Check for errors and prepare response data
(e.g. nx_packet_data_append). */
/* Send response to client. */
status = nx_secure_dtls_server_session_send(receive_dtls_session,
send_packet);
}
/* If not processing connections or received data, let the thread sleep. */
if(!connect_flag && !receive_flag)
{
tx_thread_sleep(100);
}
}
/* We have exited the processing loop, stop the server. */
status = nx_secure_dtls_server_stop(&dtls_server);
/* If we exit the processing loop, clean up the server. */
status = nx_secure_dtls_server_delete(&dtls_server);
}
Add a trusted CA certificate to a NetX Duo Secure DTLS Server
UINT nx_secure_dtls_server_trusted_certificate_add(
NX_SECURE_DTLS_SERVER *server_ptr,
NX_SECURE_X509_CERT *certificate,
UINT cert_id);
This service adds a trusted CA or intermediate CA certificate to a DTLS Server instance and assigned to all the internal DTLS server sessions. This is only necessary if X.509 Client certificate authentication is enabled using nx_secure_dtls_server_x509_client_verify_configure. The added certificate will be used to verify incoming Client X.509 certificates.
The cert_id parameter is a numeric, non-zero identifier for the certificate. This enables the certificate to be easily removed or found in the event there are multiple identity certificates with the same X.509 Common Name present in the DTLS server store. See the NetX Duo Secure TLS User Guide for more information about X.509 server certificates.
Threads
See reference for *nx_secure_dtls_server_create for a more complete example.
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SERVER dtls_server;
/* Certificate control block and data. */
NX_SECURE_X509_CERT trusted_ca_certificate;
UCHAR certificate_der_data[] = { … };
/* Primary application thread for handling DTLS server operations. */
void dtls_server_thread(void)
{
UINT status;
/* Setup DTLS Server instance. */
status = nx_secure_dtls_server_create(&dtls_server, &ip_instance,
LOCAL_SERVER_PORT,
NX_IP_PERIODIC_RATE,
dtls_server_session_buffer,
sizeof(dtls_server_session_buffer),
&tls_crypto_table,
crypto_metadata_buffer,
sizeof(crypto_metadata_buffer),
packet_buffer,
sizeof(packet_buffer),
dtls_server_connect_notify,
dtls_server_receive_notify);
/* Check for errors. */
/* Initialize trusted certificate with key and add to server. */
status = nx_secure_x509_certificate_initialize(&trusted_ca_certificate,
certificate_der_data,
sizeof(certificate_der_data),
NX_NULL, 0, NX_NULL,
0, NX_SECURE_X509_KEY_TYPE_NONE);
/* Add trusted CA certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_server_trusted_certificate_add(&dtls_server,
&trusted_ca_certificate, 1);
/* Start server. */
status = nx_secure_dtls_server_start(&dtls_server);
/* Loop continuously to handle incoming data. */
while(1)
{
/* Process incoming requests and data. */
}
}
Remove a trusted CA certificate from a NetX Duo Secure DTLS Server
UINT nx_secure_dtls_server_trusted_certificate_remove(
NX_SECURE_DTLS_SERVER *server_ptr,
UCHAR *common_name,
UINT common_name_length,
UINT cert_id);
This service removes a trusted CA certificate from a DTLS Server instance. Trusted CA certificates are only necessary for a DTLS Server for which X.509 Client certificate verification has been enabled by calling nx_secure_dtls_server_x509_client_verify_configure.
The certificate to be removed can be identified either by its X.509 Common Name or by the numeric cert_id that was assigned in the call to nx_secure_dtls_server_trusted_certificate_add. The cert_id is only used to identify the certificate and is maintained by the application. If the Common Name is used instead of the numeric certificate identifier, the cert_id parameter should be set to 0.
Note: Removing a certificate while a DTLS handshake is being processed may result in unexpected behavior. The service nx_secure_dtls_server_stop should be called before removing certificates.
Threads
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SERVER dtls_server;
/* Certificate control block and data. */
NX_SECURE_X509_CERT trusted_ca_certificate;
UCHAR certificate_der_data[] = { … };
/* Primary application thread for handling DTLS server operations. */
void dtls_server_thread(void)
{
UINT status;
/* Setup DTLS Server instance. */
status = nx_secure_dtls_server_create(&dtls_server, &ip_instance,
LOCAL_SERVER_PORT,
NX_IP_PERIODIC_RATE,
dtls_server_session_buffer,
sizeof(dtls_server_session_buffer),
&tls_crypto_table,
crypto_metadata_buffer,
sizeof(crypto_metadata_buffer),
packet_buffer,
sizeof(packet_buffer),
dtls_server_connect_notify,
dtls_server_receive_notify);
/* Check for errors. */
/* Initialize trusted certificate with key and add to server. */
status = nx_secure_x509_certificate_initialize(&trusted_ca_certificate,
certificate_der_data,
sizeof(certificate_der_data),
NX_NULL, 0, NX_NULL, 0,
NX_SECURE_X509_KEY_TYPE_NONE);
/* Add local server identity certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_server_trusted_certificate_add(&dtls_server,
&trusted_ca_certificate, 1);
/* Start server. */
status = nx_secure_dtls_server_start(&dtls_server);
/* Process client requests, etc… */
/* Stop the server before removing a certificate. */
Status = nx_secure_dtls_server_stop(&dtls_server);
/* At some point in the future we decide to remove the certificate we added. We can
use the certificate identifier we passed into the call to
nx_secure_dtls_trusted_certificate_add (value = 1); */
status = nx_secure_dtls_server_trusted_certificate_remove(&dtls_server,
NX_NULL, 0, 1);
}
Configure a NetX Duo Secure DTLS Server to request and verify client certificates
UINT nx_secure_dtls_server_x509_client_verify_configure(
NX_SECURE_DTLS_SERVER *server_ptr,
UINT certs_per_session,
UCHAR *certs_buffer,
ULONG buffer_size);
This service configures a DTLS Server to request and verify DTLS Client certificates. This optional feature is used when X.509 certificates are desired for client authentication in place of other mechanisms (e.g. a Pre-Shared Key).
Important: When a DTLS Server is configured to verify client certificates using this service, at least one trusted CA certificate must be added to the server using nx_secure_dtls_server_trusted_certificate_add or the server will reject all incoming client connections because it will be unable to verify client certificates against the trusted store.
Upon calling this service, the DTLS Server instance will (once started) request client certificates as part of the DTLS handshake. Assuming the client is properly configured with an identity certificate (and associated certificate chain when applicable), the DTLS Server requires memory to be allocated to process the client certificate data. This memory is passed in as the certs_buffer parameter.
The certs_buffer must be sized to accommodate the largest expected certificate chain from a DTLS client, times the number of DTLS server sessions. The buffer is divided amongst the available sessions using the certs_per_session parameter which represents the maximum expected number of certificates in a Client certificate chain. The buffer also needs to provide space for the NX_SECURE_X509_CERT data structure which is used to parse the certificate data.
Calculating the proper buffer size can be done with the following formula:
buffer_size = (# of DTLS sessions in server) *
(certs_per_session) *
( maximum expected certificate size +
sizeof(NX_SECURE_X509_CERT) )
Threads
/* Configure number of sessions per server. */
#define DTLS_SERVER_SESSIONS 3
/* Define parameters for X.509 client verification. */
#define MAX_CERT_SIZE (2000) /* 2KB expected maximum certificate size. */
#define CERTS_PER_SESSION (3) /* Assume maximum chain length of 3 certificates. */
#define CERT_BUFFER_SIZE (DTLS_SERVER_SESSIONS * CERTS_PER_SESSION * \
(MAX_CERT_SIZE + sizeof(NX_SECURE_X509_CERT))
/* Define our incoming certificate buffer. */
UCHAR client_certs_buffer[CERT_BUFFER_SIZE];
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SERVER dtls_server;
/* Certificate control block and data. */
NX_SECURE_X509_CERT trusted_ca_certificate;
UCHAR certificate_der_data[] = { … };
/* Primary application thread for handling DTLS server operations. */
void dtls_server_thread(void)
{
UINT status;
/* Setup DTLS Server instance. */
status = nx_secure_dtls_server_create(&dtls_server, &ip_instance,
LOCAL_SERVER_PORT,
NX_IP_PERIODIC_RATE,
dtls_server_session_buffer,
sizeof(dtls_server_session_buffer),
&tls_crypto_table,
crypto_metadata_buffer,
sizeof(crypto_metadata_buffer),
packet_buffer,
sizeof(packet_buffer),
dtls_server_connect_notify,
dtls_server_receive_notify);
/* Check for errors. */
/* Initialize trusted certificate with key and add to server. */
status = nx_secure_x509_certificate_initialize(&trusted_ca_certificate,
certificate_der_data,
sizeof(certificate_der_data),
NX_NULL, 0,
NX_NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE);
/* Add local server identity certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_server_trusted_certificate_add(&dtls_server,
&trusted_ca_certificate, 1);
/* Configure client X.509 authentication and verification. */
status = nx_secure_dtls_server_x509_client_verify_configure(&dtls_server,
CERTS_PER_SESSION,
client_certs_buffer,
sizeof(client_certs_buffer));
/* Start server. */
status = nx_secure_dtls_server_start(&dtls_server);
/* Process client requests, etc… */
}
Disables client X.509 certificate verification for a NetX Duo Secure DTLS Server
UINT nx_secure_dtls_server_x509_client_verify_disable(NX_SECURE_DTLS_SERVER *server_ptr);
This service disables X.509 Client certificate verification on a DTLS Server. The service has no effect if X.509 Client certificate verification is not enabled.
Note: Disabling client authentication on an active DTLS Server instance may result in unpredictable behavior. The nx_secure_dtls_server_stop service should be called before changing server state.
Threads
/* Configure number of sessions per server. */
#define DTLS_SERVER_SESSIONS 3
/* Define parameters for X.509 client verification. */
#define MAX_CERT_SIZE (2000) /* 2KB expected maximum certificate size. */
#define CERTS_PER_SESSION (3) /* Assume maximum chain length of 3 certificates. */
#define CERT_BUFFER_SIZE (DTLS_SERVER_SESSIONS * CERTS_PER_SESSION * \
(MAX_CERT_SIZE + sizeof(NX_SECURE_X509_CERT))
/* Define our incoming certificate buffer. */
UCHAR client_certs_buffer[CERT_BUFFER_SIZE];
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SERVER dtls_server;
/* Certificate control block and data. */
NX_SECURE_X509_CERT trusted_ca_certificate;
UCHAR certificate_der_data[] = { … };
/* Primary application thread for handling DTLS server operations. */
void dtls_server_thread(void)
{
UINT status;
/* Setup DTLS Server instance. */
status = nx_secure_dtls_server_create(&dtls_server, &ip_instance,
LOCAL_SERVER_PORT,
NX_IP_PERIODIC_RATE,
dtls_server_session_buffer,
sizeof(dtls_server_session_buffer),
&tls_crypto_table,
crypto_metadata_buffer,
sizeof(crypto_metadata_buffer),
packet_buffer,
sizeof(packet_buffer),
dtls_server_connect_notify,
dtls_server_receive_notify);
/* Check for errors. */
/* Initialize trusted certificate with key and add to server. */
status = nx_secure_x509_certificate_initialize(&trusted_ca_certificate,
certificate_der_data,
sizeof(certificate_der_data), NX_NULL, 0,
NX_NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE);
/* Add local server identity certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_server_trusted_certificate_add(&dtls_server,
&trusted_ca_certificate, 1);
/* Configure client X.509 authentication and verification. */
status = nx_secure_dtls_server_x509_client_verify_configure(&dtls_server,
CERTS_PER_SESSION,
client_certs_buffer,
sizeof(client_certs_buffer));
/* Start server. */
status = nx_secure_dtls_server_start(&dtls_server);
/* Process client requests, etc… */
/* Stop the server before changing state. */
status = nx_secure_dtls_server_stop(&dtls_server);
/* Disable X.509 authentication and verification. */
status = nx_secure_dtls_server_x509_client_verify_disable(&dtls_server);
}
Get remote client information from a DTLS Server session
UINT nx_secure_dtls_session_client_info_get(
NX_SECURE_DTLS_SESSION *session_ptr,
NXD_ADDRESS *client_ip_address,
UINT *client_port,
UINT *local_port);
This service returns the network information about a DTLS Client that is connected to a particular DTLS Server session. The information returned consists of the remote client’s IP address and UDP port, as well as the local server port to which the client is connected.
In general, the DTLS session instance will be the one obtained in the invocation of one of the DTLS notification callback routines (e.g. the connect_notify or receive_notify callbacks passed into nx_secure_dtls_server_create).
Threads
#define DTLS_SERVER_SESSION (3)
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SERVER dtls_server;
/* Allocate space for DTLS sessions in the DTLS server. */
UCHAR dtls_server_session_buffer[sizeof(NX_SECURE_DTLS_SESSION)
* DTLS_SERVER_SESSIONS];
/* Flag used to indicate that a DTLS Client has connected. */
UINT connect_flag = 0;
/* Flag used to indicate application data reception. */
UINT receive_flag = 0;
/* Pointer to newly-connected DTLS session.
NOTE: In practice this should be an array
or list in case a new connection is
attempted while a previous session is being started. */
NX_SECURE_DTLS_SESSION *new_dtls_session;
/* Pointer to session for application data receive.
NOTE: Should be an array or list as
with new_dtls_session */
NX_SECURE_DTLS_SESSION *receive_dtls_session;
/* Connect notify callback routine. */
UINT dtls_server_connect_notify(NX_SECURE_DTLS_SESSION *dtls_session, NXD_ADDRESS
*ip_address, UINT port)
{
/* NOTE: proper inter-thread communication procedures (e.g. mutex handling)
Omitted for clarity. */
/* Notify application thread that a connection request has been received. */
connect_flag = 1;
new_dtls_session = dtls_session;
return(NX_SUCCESS);
}
/* Receive notify callback routine invoked when DTLS application data is received
on an existing DTLS server session. */
UINT dtls_server_receive_notify(NX_SECURE_DTLS_SESSION *dtls_session)
{
NXD_ADDRESS client_ip;
UINT client_port, server_port;
/* Get DTLS client information which can be used in filtering or associating
the DTLS session with application data (e.g. a session pointer table). */
status = nx_secure_dtls_session_client_info_get(dtls_session, &client_ip,
&client_port, &server_port);
/* Receive and process DTLS record.
NOTE: Mutex handling omitted for clarity. */
receive_flag = 1;
receive_dtls_session = dtls_session;
return(NX_SUCCESS);
}
/* Primary application thread for handling DTLS server operations. */
void dtls_server_thread(void)
{
NX_PACKET *send_packet;
NX_PACKET *receive_packet;
UINT status;
/* Setup DTLS Server instance. */
status = nx_secure_dtls_server_create(&dtls_server, &ip_instance,
LOCAL_SERVER_PORT,
NX_IP_PERIODIC_RATE,
dtls_server_session_buffer,
sizeof(dtls_server_session_buffer),
&tls_crypto_table,
crypto_metadata_buffer,
sizeof(crypto_metadata_buffer),
packet_buffer,
sizeof(packet_buffer),
dtls_server_connect_notify,
dtls_server_receive_notify);
/* Check for errors. */
/* Initialize local server identity certificate with key and add to server. */
status = nx_secure_x509_certificate_initialize(&certificate,
device_cert_der,
device_cert_der_len,
NX_NULL, 0,
device_cert_key_der,
device_cert_key_der_len,
NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);
/* Add local server identity certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_server_local_certificate_add(&dtls_server,
&certificate, 1);
/* Start server. */
status = nx_secure_dtls_server_start(&dtls_server);
/* Loop continuously to handle incoming data. */
while(1)
{
/* Check for new connections. Muxtex handling omitted for clarity. */
if(connect_flag)
{
/* We have a new connection attempt, start the DTLS session. */
status = nx_secure_dtls_server_session_start(new_dtls_session,
NX_IP_PERIODIC_RATE);
/* Check for errors. */
}
/* Check for received application data. */
if(receive_flag)
{
/* We have received data over a previously-established DTLS session.
Mutex handling omitted for clarity. */
Status = nx_secure_dtls_session_receive(receive_dtls_session,
&receive_packet,
NX_IP_PERIODIC_RATE);
/* Process received data… */
/* Prepare and send response to client. */
status = nx_secure_dtls_packet_allocate(receive_dtls_session,
&packet_pool,
&send_packet,
NX_IP_PERIODIC_RATE);
/* Check for errors and prepare response data
(e.g. nx_packet_data_append). */
/* Send response to client. */
status = nx_secure_dtls_server_session_send(receive_dtls_session,
send_packet);
}
/* If not processing connections or received data, let the thread sleep. */
if(!connect_flag && !receive_flag)
{
tx_thread_sleep(100);
}
}
/* If we exit the processing loop, clean up the server. */
status = nx_secure_dtls_server_delete(&dtls_server);
}
Create and configure a NetX Duo Secure DTLS Session
UINT nx_secure_dtls_session_create(
NX_SECURE_DTLS_SESSION *dtls_session,
const NX_SECURE_TLS_CRYPTO *crypto_table,
VOID *metadata_buffer, ULONG metadata_size,
UCHAR *packet_reassembly_buffer,
UINT packet_reassembly_buffer_size,
UINT certs_number,
UCHAR *remote_certificate_buffer,
ULONG remote_certificate_buffer_size));
This service creates and configures a DTLS session. Generally, this will be used to create DTLS Client sessions as DTLS Server sessions are managed with the DTLS Server mechanism (see nx_secure_dtls_server_create), but there may be instances where an application needs to create a single stand-alone DTLS Server session instance in which case this service may be used7.
The parameters configure the information and memory allocation needed to instantiate a DTLS session. The crypto_table parameter is a TLS table containing all of the cryptographic routines needed for TLS/DTLS encryption and authentication. The metadata_buffer is used for encryption calculations (see nx_secure_tls_metadata_size_calculate in the NetX Duo Secure TLS User Guide), and the packet_reassembly_buffer is used to reassemble UDP datagrams into a complete DTLS record for decryption.
The certs_number and remote_certificate_buffer are required for DTLS Clients which need space to store and process the incoming DTLS Server certificate chain. The buffer must be able to accommodate the maximum expected size of the certificate chain for any server to which it will connect. The buffer is divided up by the number of expected certificates (certs_number parameter) and must also be large enough to hold one NX_SECURE_X509_CERT structure per certificate. The buffer size can be determined using the following formula:
remote_certificate_buffer_size = (certs_number) *
(maximum cert size + sizeof(NX_SECURE_X509_CERT))
7 Creating DTLS Server sessions with this routine is not recommended and comes with some limitations. The primary issue is that the session will not handle additional client connections gracefully – since UDP is connectionless a second client can legally send data to the server’s UDP port when a previous DTLS session is still active which would cause the server session to end with an error.
Threads
/* Sockets, sessions, certificates defined in global static space to preserve
application stack. */
NX_SECURE_DTLS_SESSION client_dtls_session;
/* Trusted certificate structure and raw data. */
NX_SECURE_X509_CERT trusted_cert;
const UCHAR trusted_cert_der = { … };
/* Cryptography routines and crypto work buffers. */
extern const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers;
UCHAR crypto_metadata[9000];
/* Packet reassembly buffer for decryption. */
UCHAR packet_buffer[4000];
/* Remote certificate buffer for incoming certificates. */
#define REMOTE_CERT_SIZE (sizeof(NX_SECURE_X509_CERT) + 2000)
#define REMOTE_CERT_NUMBER (3)
UCHAR remote_certs_buffer[REMOTE_CERT_SIZE * REMOTE_CERT_NUMBER];
/* Application thread where TLS session is started. */
void application_thread()
{
NXD_ADDRESS server_ip;
/* Create a TLS session for our socket. Ciphers and metadata defined
elsewhere. See nx_secure_tls_session_create reference for more
information. */
status = nx_secure_dtls_session_create(&client_dtls_session,
&nx_crypto_tls_ciphers,
crypto_metadata,
sizeof(crypto_metadata),
packet_buffer,
sizeof(packet_buffer),
REMOTE_CERT_NUMBER,
remote_certs_buffer,
sizeof(remote_certs_buffer));
/* Check for error. */
if(status)
{
printf("Error in function nx_secure_dtls_session_create: 0x%x\n", status);
}
/* Initialize our trusted certificate. See section "Importing X.509
Certificates into NetX Duo Secure" for more information. */
nx_secure_x509_certificate_initialize(&trusted_certificate,
trusted_cert_der,
trusted_cert_der_len,
NX_NULL, 0, NX_NULL, 0,
NX_SECURE_X509_KEY_TYPE_NONE);
/* Add the certificate to the local store using a numeric ID. */
nx_secure_dtls_session_trusted_certificate_add(&client_dtls_session,
&certificate, 1);
/* Set up IP address of remote host. */
server_ip.nxd_ip_version = NX_IP_VERSION_V4;
server_ip.nxd_ip_address.v4 = IP_ADDRESS(192, 168, 1, 150);
/* Now we can start the DTLS session as normal. */
status = nx_secure_dtls_client_session_start(&client_dtls_session,
&udp_socket, &server_ip,
4443,
NX_IP_PERIODIC_RATE);
if(status != NX_SUCCESS)
{
/* Error! */
return(status);
}
/* Add data to send packet as usual for NX_PACKET and send to server. */
status = nx_secure_dtls_session_send(&client_dtls_session,
&send_packet,
&server_ip, 4443);
/* Receive response from server. */
status = nx_secure_dtls_session_receive(&client_dtls_session,
&receive_packet,
NX_IP_PERIODIC_RATE);
/* Process response. */
/* Shut down DTLS session. */
status = nx_secure_dtls_session_end(&client_dtls_session,
NX_IP_PERIODIC_RATE);
/* Clean up. */
status = nx_secure_dtls_session_delete(&client_dtls_session);
}
Free up resources used by a NetX Duo Secure DTLS Session
UINT nx_secure_dtls_session_delete(NX_SECURE_DTLS_SESSION *dtls_session);
This service deletes a DTLS session, freeing up any resources that were allocated when it was created.
Threads
/* Sockets, sessions, certificates defined in global static space to preserve
application stack. */
NX_SECURE_DTLS_SESSION client_dtls_session;
/* Trusted certificate structure and raw data. */
NX_SECURE_X509_CERT trusted_cert;
const UCHAR trusted_cert_der = { … };
/* Cryptography routines and crypto work buffers. */
extern const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers;
UCHAR crypto_metadata[9000];
/* Packet reassembly buffer for decryption. */
UCHAR packet_buffer[4000];
/* Remote certificate buffer for incoming certificates. */
#define REMOTE_CERT_SIZE (sizeof(NX_SECURE_X509_CERT) + 2000)
#define REMOTE_CERT_NUMBER (3)
UCHAR remote_certs_buffer[REMOTE_CERT_SIZE * REMOTE_CERT_NUMBER];
/* Application thread where TLS session is started. */
void application_thread()
{
NXD_ADDRESS server_ip;
/* Create a TLS session for our socket. Ciphers and metadata defined
elsewhere. See nx_secure_tls_session_create reference for more
information. */
status = nx_secure_dtls_session_create(&client_dtls_session,
&nx_crypto_tls_ciphers,
crypto_metadata,
sizeof(crypto_metadata),
packet_buffer,
sizeof(packet_buffer),
REMOTE_CERT_NUMBER,
remote_certs_buffer,
sizeof(remote_certs_buffer));
/* Check for error. */
if(status)
{
printf("Error in function nx_secure_dtls_session_create: 0x%x\n", status);
}
/* Initialize our trusted certificate. See section "Importing X.509
Certificates into NetX Duo Secure" for more information. */
nx_secure_x509_certificate_initialize(&trusted_certificate,
trusted_cert_der,
trusted_cert_der_len,
NX_NULL, 0, NX_NULL, 0,
NX_SECURE_X509_KEY_TYPE_NONE);
/* Add the certificate to the local store using a numeric ID. */
nx_secure_dtls_session_trusted_certificate_add(&client_dtls_session,
&certificate, 1);
/* Set up IP address of remote host. */
server_ip.nxd_ip_version = NX_IP_VERSION_V4;
server_ip.nxd_ip_address.v4 = IP_ADDRESS(192, 168, 1, 150);
/* Now we can start the DTLS session as normal. */
status = nx_secure_dtls_client_session_start(&client_dtls_session,
&udp_socket,
&server_ip, 4443,
NX_IP_PERIODIC_RATE);
if(status != NX_SUCCESS)
{
/* Error! */
return(status);
}
/* Add data to send packet as usual for NX_PACKET and send to server. */
status = nx_secure_dtls_session_send(&client_dtls_session, &send_packet,
&server_ip, 4443);
/* Receive response from server. */
status = nx_secure_dtls_session_receive(&client_dtls_session,
&receive_packet,
NX_IP_PERIODIC_RATE);
/* Process response. */
/* Shut down DTLS session. */
status = nx_secure_dtls_session_end(&client_dtls_session,
NX_IP_PERIODIC_RATE);
/* Clean up. */
status = nx_secure_dtls_session_delete(&client_dtls_session);
}
Shut down an active NetX Duo Secure DTLS Session
UINT nx_secure_dtls_session_end(
NX_SECURE_DTLS_SESSION *dtls_session,
UINT wait_option);
This service ends an active DTLS session by sending a TLS/DTLS CloseNotify alert to the remote host. The IP address and port used are those used in the previous call to nx_secure_dtls_session_send.
Threads
/* Sockets, sessions, certificates defined in global static space to preserve
application stack. */
NX_SECURE_DTLS_SESSION client_dtls_session;
/* Trusted certificate structure and raw data. */
NX_SECURE_X509_CERT trusted_cert;
const UCHAR trusted_cert_der = { … };
/* Cryptography routines and crypto work buffers. */
extern const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers;
UCHAR crypto_metadata[9000];
/* Packet reassembly buffer for decryption. */
UCHAR packet_buffer[4000];
/* Remote certificate buffer for incoming certificates. */
#define REMOTE_CERT_SIZE (sizeof(NX_SECURE_X509_CERT) + 2000)
#define REMOTE_CERT_NUMBER (3)
UCHAR remote_certs_buffer[REMOTE_CERT_SIZE * REMOTE_CERT_NUMBER];
/* Application thread where TLS session is started. */
void application_thread()
{
NXD_ADDRESS server_ip;
/* Create a TLS session for our socket. Ciphers and metadata defined
elsewhere. See nx_secure_tls_session_create reference for more
information. */
status = nx_secure_dtls_session_create(&client_dtls_session,
&nx_crypto_tls_ciphers,
crypto_metadata,
sizeof(crypto_metadata),
packet_buffer,
sizeof(packet_buffer),
REMOTE_CERT_NUMBER,
remote_certs_buffer,
sizeof(remote_certs_buffer));
/* Check for error. */
if(status)
{
printf("Error in function nx_secure_dtls_session_create: 0x%x\n", status);
}
/* Initialize our trusted certificate. See section "Importing X.509
Certificates into NetX Duo Secure" for more information. */
nx_secure_x509_certificate_initialize(&trusted_certificate,
trusted_cert_der,
trusted_cert_der_len, NX_NULL,
0, NX_NULL, 0,
NX_SECURE_X509_KEY_TYPE_NONE);
/* Add the certificate to the local store using a numeric ID. */
nx_secure_dtls_session_trusted_certificate_add(&client_dtls_session,
&certificate, 1);
/* Set up IP address of remote host. */
server_ip.nxd_ip_version = NX_IP_VERSION_V4;
server_ip.nxd_ip_address.v4 = IP_ADDRESS(192, 168, 1, 150);
/* Now we can start the DTLS session as normal. */
status = nx_secure_dtls_client_session_start(&client_dtls_session,
&udp_socket, &server_ip, 4443,
NX_IP_PERIODIC_RATE);
if(status != NX_SUCCESS)
{
/* Error! */
return(status);
}
/* Add data to send packet as usual for NX_PACKET and send to server. */
status = nx_secure_dtls_session_send(&client_dtls_session,
&send_packet,
&server_ip, 4443);
/* Receive response from server. */
status = nx_secure_dtls_session_receive(&client_dtls_session,
&receive_packet,
NX_IP_PERIODIC_RATE);
/* Process response. */
/* Shut down DTLS session. */
status = nx_secure_dtls_session_end(&client_dtls_session,
NX_IP_PERIODIC_RATE);
/* Clean up. */
status = nx_secure_dtls_session_delete(&client_dtls_session);
}
Add a local identity certificate to a NetX Duo Secure DTLS Session
UINT nx_secure_dtls_session_local_certificate_add(
NX_SECURE_DTLS_SESSION *session_ptr,
NX_SECURE_X509_CERT *certificate,
UINT cert_id);
This service adds a local identity certificate to a DTLS Session instance. In general, this service will be used when a DTLS Client session needs to provide an identity certificate to a remote server host. This is an optional configuration for DTLS so a certificate is not generally required for DTLS Clients. An identity certificate requires an associated private key.
The cert_id parameter is a numeric, non-zero identifier for the certificate. This enables the certificate to be easily removed or found in the event there are multiple identity certificates with the same X.509 Common Name present in the DTLS certificate store. See the NetX Duo Secure TLS User Guide for more information about X.509 certificates.
Threads
See reference for *nx_secure_dtls_session_create for a more complete example.
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SESSION dtls_client;
/* Certificate control block and data. Identity
certificates require a private key. */
NX_SECURE_X509_CERT certificate;
UCHAR certificate_der_data[] = { … };
UCHAR certificate_key_der_data[] = { … };
/* Application thread where TLS session is started. */
void application_thread()
{
NXD_ADDRESS server_ip;
/* Create a TLS session for our socket. Ciphers and metadata defined
elsewhere. See nx_secure_tls_session_create reference for more
information. */
status = nx_secure_dtls_session_create(&client_dtls_session,
&nx_crypto_tls_ciphers,
crypto_metadata,
sizeof(crypto_metadata),
packet_buffer,
sizeof(packet_buffer),
REMOTE_CERT_NUMBER,
remote_certs_buffer,
sizeof(remote_certs_buffer));
/* Check for error. */
if(status)
{
printf("Error in function nx_secure_dtls_session_create: 0x%x\n", status);
}
/* Initialize our trusted certificate. See section "Importing X.509
Certificates into NetX Duo Secure" for more information. */
nx_secure_x509_certificate_initialize(&trusted_certificate,
trusted_cert_der,
trusted_cert_der_len,
NX_NULL, 0, NX_NULL, 0,
NX_SECURE_X509_KEY_TYPE_NONE);
/* Add the certificate to the local store using a numeric ID. */
nx_secure_dtls_session_trusted_certificate_add(&client_dtls_session,
&certificate, 1);
/* Initialize local server identity certificate with key and
add to server. */
status = nx_secure_x509_certificate_initialize(&certificate,
certificate_der_data,
sizeof(certificate_der_data),
NX_NULL, 0,
certificate_key_der_data,
sizeof(certificate_key_der_data),
NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);
/* Add local server identity certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_session_local_certificate_add(&dtls_client,
&certificate, 1);
/* Set up IP address of remote host. */
server_ip.nxd_ip_version = NX_IP_VERSION_V4;
server_ip.nxd_ip_address.v4 = IP_ADDRESS(192, 168, 1, 150);
/* Now we can start the DTLS session as normal. */
status = nx_secure_dtls_client_session_start(&client_dtls_session,
&udp_socket, &server_ip, 4443,
NX_IP_PERIODIC_RATE);
/* Process responses, etc…*/
}
Remove a local identity certificate from a NetX Duo Secure DTLS Session
UINT nx_secure_dtls_session_local_certificate_remove(
NX_SECURE_DTLS_SESSION *session_ptr,
UCHAR *common_name,
UINT common_name_length,
UINT cert_id);
This service removes a local identity certificate from a DTLS Session instance using either a certificate ID number (assigned when the certificate was added with nx_secure_dtls_session_local_certificate_add) or the X.509 CommonName field.
If the common_name is used to match the certificate, the cert_id parameter should be set to 0. If cert_id is used, common_name should be passed a value of NX_NULL.
The cert_id parameter is a numeric, non-zero identifier for the certificate. This enables the certificate to be easily removed or found in the event there are multiple identity certificates with the same X.509 Common Name present in the DTLS certificate store. See the NetX Duo Secure TLS User Guide for more information about X.509 certificates.
Threads
See reference for *nx_secure_dtls_session_create for a more complete example.
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SESSION dtls_client;
/* Certificate control block and data.
Identity certificates require a private key. */
NX_SECURE_X509_CERT certificate;
UCHAR certificate_der_data[] = { … };
UCHAR certificate_key_der_data[] = { … };
/* Application thread where TLS session is started. */
void application_thread()
{
NXD_ADDRESS server_ip;
/* Create a TLS session for our socket. Ciphers and metadata defined
elsewhere. See nx_secure_tls_session_create reference for more
information. */
status = nx_secure_dtls_session_create(&client_dtls_session,
&nx_crypto_tls_ciphers,
crypto_metadata,
sizeof(crypto_metadata),
packet_buffer,
sizeof(packet_buffer),
REMOTE_CERT_NUMBER,
remote_certs_buffer,
sizeof(remote_certs_buffer));
/* Check for error. */
if(status)
{
printf("Error in function nx_secure_dtls_session_create: 0x%x\n", status);
}
/* Initialize our trusted certificate. See section "Importing X.509
Certificates into NetX Duo Secure" for more information. */
nx_secure_x509_certificate_initialize(&trusted_certificate,
trusted_cert_der,
trusted_cert_der_len, NX_NULL,
0, NX_NULL, 0,
NX_SECURE_X509_KEY_TYPE_NONE);
/* Add the certificate to the local store using a numeric ID. */
nx_secure_dtls_session_trusted_certificate_add(&client_dtls_session,
&certificate, 1);
/* Initialize local server identity certificate with key
and add to server. */
status = nx_secure_x509_certificate_initialize(&certificate,
certificate_der_data,
sizeof(certificate_der_data),
NX_NULL, 0,
certificate_key_der_data,
sizeof(certificate_key_der_data),
NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);
/* Add local server identity certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_session_local_certificate_add(&dtls_client,
&certificate, 1);
/* Set up IP address of remote host. */
server_ip.nxd_ip_version = NX_IP_VERSION_V4;
server_ip.nxd_ip_address.v4 = IP_ADDRESS(192, 168, 1, 150);
/* Now we can start the DTLS session as normal. */
status = nx_secure_dtls_client_session_start(&client_dtls_session,
&udp_socket, &server_ip, 4443,
NX_IP_PERIODIC_RATE);
/* Process responses, etc…*/
/* At some point in the future,
we decide to remove the certificate using the ID of 1
when it was added to the session. */
status = nx_secure_dtls_session_local_certificate_remove(&client_dtls_session,
NX_NULL, 0, 1);
}
Receive application data over an established NetX Duo Secure DTLS Session
UINT nx_secure_dtls_session_receive(
NX_SECURE_DTLS_SESSION *dtls_session,
NX_PACKET **packet_ptr_ptr,
UINT wait_option);
This service returns application data received by an active DTLS Session. The DTLS Session may be either a DTLS Server session (managed by a DTLS Server instance) or a DTLS Client session. The returned packet may be processed using any of the NX_PACKET API services. See the NetX Duo documentation for more information).
Threads
/* Sockets, sessions, certificates defined in global static space to preserve
application stack. */
NX_SECURE_DTLS_SESSION client_dtls_session;
/* Trusted certificate structure and raw data. */
NX_SECURE_X509_CERT trusted_cert;
const UCHAR trusted_cert_der = { … };
/* Cryptography routines and crypto work buffers. */
extern const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers;
UCHAR crypto_metadata[9000];
/* Packet reassembly buffer for decryption. */
UCHAR packet_buffer[4000];
/* Remote certificate buffer for incoming certificates. */
#define REMOTE_CERT_SIZE (sizeof(NX_SECURE_X509_CERT) + 2000)
#define REMOTE_CERT_NUMBER (3)
UCHAR remote_certs_buffer[REMOTE_CERT_SIZE * REMOTE_CERT_NUMBER];
/* Application thread where TLS session is started. */
void application_thread()
{
NXD_ADDRESS server_ip;
/* Create a TLS session for our socket. Ciphers and metadata defined
elsewhere. See nx_secure_tls_session_create reference for more
information. */
status = nx_secure_dtls_session_create(&client_dtls_session,
&nx_crypto_tls_ciphers,
crypto_metadata,
sizeof(crypto_metadata),
packet_buffer,
sizeof(packet_buffer),
REMOTE_CERT_NUMBER,
remote_certs_buffer,
sizeof(remote_certs_buffer));
/* Check for error. */
if(status)
{
printf("Error in function nx_secure_dtls_session_create: 0x%x\n", status);
}
/* Initialize our trusted certificate. See section "Importing X.509
Certificates into NetX Duo Secure" for more information. */
nx_secure_x509_certificate_initialize(&trusted_certificate,
trusted_cert_der,
trusted_cert_der_len, NX_NULL,
0, NX_NULL, 0,
NX_SECURE_X509_KEY_TYPE_NONE);
/* Add the certificate to the local store using a numeric ID. */
nx_secure_dtls_session_trusted_certificate_add(&client_dtls_session,
&certificate, 1);
/* Set up IP address of remote host. */
server_ip.nxd_ip_version = NX_IP_VERSION_V4;
server_ip.nxd_ip_address.v4 = IP_ADDRESS(192, 168, 1, 150);
/* Now we can start the DTLS session as normal. */
status = nx_secure_dtls_client_session_start(&client_dtls_session,
&udp_socket, &server_ip, 4443,
NX_IP_PERIODIC_RATE);
if(status != NX_SUCCESS)
{
/* Error! */
return(status);
}
/* Add data to send packet as usual for NX_PACKET and send to server. */
status = nx_secure_dtls_session_send(&client_dtls_session, &send_packet,
&server_ip, 4443);
/* Receive response from server. */
status = nx_secure_dtls_session_receive(&client_dtls_session, &receive_packet,
NX_IP_PERIODIC_RATE);
/* Process response. */
/* Shut down DTLS session. */
status = nx_secure_dtls_session_end(&client_dtls_session, NX_IP_PERIODIC_RATE);
/* Clean up. */
status = nx_secure_dtls_session_delete(&client_dtls_session);
}
Clear data in an NetX Duo Secure DTLS Session instance
UINT nx_secure_dtls_session_reset(NX_SECURE_DTLS_SESSION *dtls_session);
This service resets a DTLS session, clearing all ephemeral cryptographic data and allowing the structure to be re-used for a new session. Persistent data (e.g. certificate stores) are maintained so that nx_secure_dtls_session_create need not be called repeatedly.
Threads
/* Sockets, sessions, certificates defined in global static space to preserve
application stack. */
NX_SECURE_DTLS_SESSION client_dtls_session;
/* Trusted certificate structure and raw data. */
NX_SECURE_X509_CERT trusted_cert;
const UCHAR trusted_cert_der = { … };
/* Cryptography routines and crypto work buffers. */
extern const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers;
UCHAR crypto_metadata[9000];
/* Packet reassembly buffer for decryption. */
UCHAR packet_buffer[4000];
/* Remote certificate buffer for incoming certificates. */
#define REMOTE_CERT_SIZE (sizeof(NX_SECURE_X509_CERT) + 2000)
#define REMOTE_CERT_NUMBER (3)
UCHAR remote_certs_buffer[REMOTE_CERT_SIZE * REMOTE_CERT_NUMBER];
/* Application thread where TLS session is started. */
void application_thread()
{
NXD_ADDRESS server_ip;
/* Create a TLS session for our socket. Ciphers and metadata defined
elsewhere. See nx_secure_tls_session_create reference for more
information. */
status = nx_secure_dtls_session_create(&client_dtls_session,
&nx_crypto_tls_ciphers,
crypto_metadata,
sizeof(crypto_metadata),
packet_buffer,
sizeof(packet_buffer),
REMOTE_CERT_NUMBER,
remote_certs_buffer,
sizeof(remote_certs_buffer));
/* Check for error. */
if(status)
{
printf("Error in function nx_secure_dtls_session_create: 0x%x\n", status);
}
/* Initialize our trusted certificate. See section "Importing X.509
Certificates into NetX Duo Secure" for more information. */
nx_secure_x509_certificate_initialize(&trusted_certificate,
trusted_cert_der,
trusted_cert_der_len, NX_NULL,
0, NX_NULL, 0,
NX_SECURE_X509_KEY_TYPE_NONE);
/* Add the certificate to the local store using a numeric ID. */
nx_secure_dtls_session_trusted_certificate_add(&client_dtls_session,
&certificate, 1);
/* Set up IP address of remote host. */
server_ip.nxd_ip_version = NX_IP_VERSION_V4;
server_ip.nxd_ip_address.v4 = IP_ADDRESS(192, 168, 1, 150);
/* Now we can start the DTLS session as normal. */
status = nx_secure_dtls_client_session_start(&client_dtls_session,
&udp_socket, &server_ip, 4443,
NX_IP_PERIODIC_RATE);
if(status != NX_SUCCESS)
{
/* Error! */
return(status);
}
/* Add data to send packet as usual for NX_PACKET and send to server. */
status = nx_secure_dtls_session_send(&client_dtls_session, &send_packet,
&server_ip, 4443);
/* Receive response from server. */
status = nx_secure_dtls_session_receive(&client_dtls_session,
&receive_packet,
NX_IP_PERIODIC_RATE);
/* Process response. */
/* Shut down DTLS session. */
status = nx_secure_dtls_session_reset(&client_dtls_session);
/* A new session can now be started using the same structure. */
status = nx_secure_dtls_client_session_start(&client_dtls_session,
/* Clean up. */
status = nx_secure_dtls_session_delete(&client_dtls_session);
}
Send data over a DTLS session
UINT nx_secure_dtls_session_send(
NX_SECURE_DTLS_SESSION *session_ptr,
NX_PACKET *packet_ptr,
NXD_ADDRESS *ip_address,
UINT port);
This service sends a packet of data over an established DTLS Session to a remote DTLS host at the given IP address and port. The session used is an active DTLS Client session. Note that the IP address and port are provided due to the stateless nature of UDP but should generally match the address and port used to start the session in nx_secure_dtls_session_start.
The data provided in the packet, which must be allocated using nx_secure_dtls_packet_allocate, is encrypted using the DTLS session cryptographic parameters and routines and then sent to the remote host over the DTLS Session’s UDP socket.
Threads
/* Sockets, sessions, certificates defined in global static space to preserve
application stack. */
NX_SECURE_DTLS_SESSION client_dtls_session;
/* Trusted certificate structure and raw data. */
NX_SECURE_X509_CERT trusted_cert;
const UCHAR trusted_cert_der = { … };
/* Cryptography routines and crypto work buffers. */
extern const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers;
UCHAR crypto_metadata[9000];
/* Packet reassembly buffer for decryption. */
UCHAR packet_buffer[4000];
/* Remote certificate buffer for incoming certificates. */
#define REMOTE_CERT_SIZE (sizeof(NX_SECURE_X509_CERT) + 2000)
#define REMOTE_CERT_NUMBER (3)
UCHAR remote_certs_buffer[REMOTE_CERT_SIZE * REMOTE_CERT_NUMBER];
/* Application thread where TLS session is started. */
void application_thread()
{
NXD_ADDRESS server_ip;
/* Create a TLS session for our socket. Ciphers and metadata defined
elsewhere. See nx_secure_tls_session_create reference for more
information. */
status = nx_secure_dtls_session_create(&client_dtls_session,
&nx_crypto_tls_ciphers,
crypto_metadata,
sizeof(crypto_metadata),
packet_buffer,
sizeof(packet_buffer),
REMOTE_CERT_NUMBER,
remote_certs_buffer,
sizeof(remote_certs_buffer));
/* Check for error. */
if(status)
{
printf("Error in function nx_secure_dtls_session_create: 0x%x\n", status);
}
/* Initialize our trusted certificate. See section "Importing X.509
Certificates into NetX Duo Secure" for more information. */
nx_secure_x509_certificate_initialize(&trusted_certificate,
trusted_cert_der,
trusted_cert_der_len, NX_NULL,
0, NX_NULL, 0,
NX_SECURE_X509_KEY_TYPE_NONE);
/* Add the certificate to the local store using a numeric ID. */
nx_secure_dtls_session_trusted_certificate_add(&client_dtls_session,
&certificate, 1);
/* Set up IP address of remote host. */
server_ip.nxd_ip_version = NX_IP_VERSION_V4;
server_ip.nxd_ip_address.v4 = IP_ADDRESS(192, 168, 1, 150);
/* Now we can start the DTLS session as normal. */
status = nx_secure_dtls_client_session_start(&client_dtls_session,
&udp_socket, &server_ip, 4443,
NX_IP_PERIODIC_RATE);
if(status != NX_SUCCESS)
{
/* Error! */
return(status);
}
/* Add data to send packet as usual for NX_PACKET and send to server. */
status = nx_secure_dtls_session_send(&client_dtls_session, &send_packet,
&server_ip, 4443);
/* Receive response from server. */
status = nx_secure_dtls_session_receive(&client_dtls_session,
&receive_packet,
NX_IP_PERIODIC_RATE);
/* Process response. */
/* Shut down DTLS session. */
status = nx_secure_dtls_session_end(&client_dtls_session,
NX_IP_PERIODIC_RATE);
/* Clean up. */
status = nx_secure_dtls_session_delete(&client_dtls_session);
}
Add a trusted CA certificate to a NetX Duo Secure DTLS Session
UINT nx_secure_dtls_session_trusted_certificate_add(
NX_SECURE_DTLS_SESSION *session_ptr,
NX_SECURE_X509_CERT *certificate,
UINT cert_id);
This service adds a trusted CA or intermediate CA X.509 certificate to a DTLS Session instance. A DTLS Client requires at least one trusted certificate in order to validate remote server certificates unless an alternative authentication mechanism is used (e.g. Pre-Shared Keys). A trusted certificate does not usually have a private key.
The cert_id parameter is a numeric, non-zero identifier for the certificate. This enables the certificate to be easily removed or found in the event there are multiple identity certificates with the same X.509 Common Name present in the DTLS certificate store. See the NetX Duo Secure TLS User Guide for more information about X.509 certificates.
Threads
See reference for *nx_secure_dtls_session_create for a more complete example.
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SESSION dtls_client;
/* Certificate control block and data.
Identity certificates require a private key. */
NX_SECURE_X509_CERT certificate;
UCHAR certificate_der_data[] = { … };
UCHAR certificate_key_der_data[] = { … };
/* Application thread where TLS session is started. */
void application_thread()
{
NXD_ADDRESS server_ip;
/* Create a TLS session for our socket. Ciphers and metadata defined
elsewhere. See nx_secure_tls_session_create reference for more
information. */
status = nx_secure_dtls_session_create(&client_dtls_session,
&nx_crypto_tls_ciphers,
crypto_metadata,
sizeof(crypto_metadata),
packet_buffer,
sizeof(packet_buffer),
REMOTE_CERT_NUMBER,
remote_certs_buffer,
sizeof(remote_certs_buffer));
/* Check for error. */
if(status)
{
printf("Error in function nx_secure_dtls_session_create: 0x%x\n", status);
}
/* Initialize our trusted certificate. See section "Importing X.509
Certificates into NetX Duo Secure" for more information. */
nx_secure_x509_certificate_initialize(&trusted_certificate,
trusted_cert_der,
trusted_cert_der_len,
NX_NULL, 0, NX_NULL, 0,
NX_SECURE_X509_KEY_TYPE_NONE);
/* Add the certificate to the trusted store using a numeric ID. */
nx_secure_dtls_session_trusted_certificate_add(&client_dtls_session,
&certificate, 1);
/* Initialize local server identity certificate with key and add to server. */
status = nx_secure_x509_certificate_initialize(&certificate,
certificate_der_data,
sizeof(certificate_der_data),
NX_NULL, 0,
certificate_key_der_data,
sizeof(certificate_key_der_data),
NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);
/* Add local server identity certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_session_local_certificate_add(&dtls_client,
&certificate, 1);
/* Set up IP address of remote host. */
server_ip.nxd_ip_version = NX_IP_VERSION_V4;
server_ip.nxd_ip_address.v4 = IP_ADDRESS(192, 168, 1, 150);
/* Now we can start the DTLS session as normal. */
status = nx_secure_dtls_client_session_start(&client_dtls_session,
&udp_socket, &server_ip, 4443,
NX_IP_PERIODIC_RATE);
/* Process responses, etc…*/
}
Remove a trusted CA certificate from a NetX Duo Secure DTLS Session
UINT nx_secure_dtls_session_trusted_certificate_remove(
NX_SECURE_DTLS_SESSION *session_ptr,
UCHAR *common_name,
UINT common_name_length,
UINT cert_id);
This service removes a trusted CA certificate from a DTLS Session instance using either a certificate ID number (assigned when the certificate was added with nx_secure_dtls_session_trusted_certificate_add) or the X.509 CommonName field.
If the common_name is used to match the certificate, the cert_id parameter should be set to 0. If cert_id is used, common_name should be passed a value of NX_NULL.
The cert_id parameter is a numeric, non-zero identifier for the certificate. This enables the certificate to be easily removed or found in the event there are multiple identity certificates with the same X.509 Common Name present in the DTLS certificate store. See the NetX Duo Secure TLS User Guide for more information about X.509 certificates.
Threads
See reference for *nx_secure_dtls_session_create for a more complete example.
/* Our DTLS Server instance. */
NX_SECURE_DTLS_SESSION dtls_client;
/* Certificate control block and data. Identity certificates require a private key. */
NX_SECURE_X509_CERT certificate;
UCHAR certificate_der_data[] = { … };
UCHAR certificate_key_der_data[] = { … };
/* Application thread where TLS session is started. */
void application_thread()
{
NXD_ADDRESS server_ip;
/* Create a TLS session for our socket. Ciphers and metadata defined
elsewhere. See nx_secure_tls_session_create reference for more
information. */
status = nx_secure_dtls_session_create(&client_dtls_session,
&nx_crypto_tls_ciphers,
crypto_metadata,
sizeof(crypto_metadata),
packet_buffer,
sizeof(packet_buffer),
REMOTE_CERT_NUMBER,
remote_certs_buffer,
sizeof(remote_certs_buffer));
/* Check for error. */
if(status)
{
printf("Error in function nx_secure_dtls_session_create: 0x%x\n", status);
}
/* Initialize our trusted certificate. See section "Importing X.509
Certificates into NetX Duo Secure" for more information. */
nx_secure_x509_certificate_initialize(&trusted_certificate,
trusted_cert_der,
trusted_cert_der_len, NX_NULL, 0,
NX_NULL, 0,
NX_SECURE_X509_KEY_TYPE_NONE);
/* Add the certificate to the local store using a numeric ID. */
nx_secure_dtls_session_trusted_certificate_add(&client_dtls_session,
&certificate, 1);
/* Initialize local server identity certificate with key and add to server. */
status = nx_secure_x509_certificate_initialize(&certificate,
certificate_der_data,
sizeof(certificate_der_data),
NX_NULL, 0,
certificate_key_der_data,
sizeof(certificate_key_der_data),
NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);
/* Add local server identity certificate to DTLS server with ID of 1. */
status = nx_secure_dtls_session_local_certificate_add(&dtls_client,
&certificate, 1);
/* Set up IP address of remote host. */
server_ip.nxd_ip_version = NX_IP_VERSION_V4;
server_ip.nxd_ip_address.v4 = IP_ADDRESS(192, 168, 1, 150);
/* Now we can start the DTLS session as normal. */
status = nx_secure_dtls_client_session_start(&client_dtls_session,
&udp_socket, &server_ip, 4443,
NX_IP_PERIODIC_RATE);
/* Process responses, etc…*/
/* At some point in the future,
we decide to remove the certificate using the ID of 1
when it was added to the session. */
status = nx_secure_dtls_session_trusted_certificate_remove(&client_dtls_session,
NX_NULL, 0, 1);
}