The Prosody DTLS library contains source code which can be integrated into an application and used in combination with Prosody and an OpenSSL library installed on the system to obtain cipher keys for encrypting/authenticating audio conveyed in SRTP packets.
The DTLS protocol and its use with SRTP is described in: IETF RFC 5764 and IETF RFC 4347.
Use of DTLS is a UDP based alternative to the coneyance of cipher keys within SIP/SDP sent over a TLS session. Use of DTLS for this purpose is normal for WebRTC sessions.
A sequence of Prosody DTLS library calls will invoke a DTLS handshake with a peer entity and on successful completion will result in two 240 bit (30 octet) vectors of combined master key and salt being made available to the application. These buffers can be passed to TiNG RTP authenication/encryption API calls (which will use a key derivation function to extract HMAC and AES keys from this data).
The API is made up of the following calls:
dtlslib_init
Initialise use of OpenSSL/DTLS framework for use by application
dtlslib_free
Terminate use of OpenSSL by application
dtlslib_create_cert
Create a certificate to be used in handshake
dtlslib_get_cert_fingerprint
Get a fingerprint for certificate
dtlslib_free_cert
Terminate use of certificate
dtlslib_create_session
Configure and prepare resources for DTLS handshake
dtlslib_free_session
Release resourcers associated with handshake
dtlslib_start_handshake
Initiate handshake packet exchange
dtlslib_continue
On packet arrival or timeout, perform next protocol action
dtlslib_get_timeout_ms
Determine how long to await response to last packet sent
dtlslib_get_remote_fingerprint
Obtain fingerprint of peer entity's certificate
dtlslib_extract_srtp_keys
Upon handshake completion, obtain cipher key data
A typical application sequence would be:
dtlslib_init
.
dtlslib_create_cert
.
dtlslib_get_cert_fingerprint
.
dtlslib_create_session
.
dtlslib_start_handshake
.
dtlslib_continue
until completed or maximum permitted time has elapsed.
dtlslib_get_remote_fingerprint
and verify it matches that received in SDP for peer.
dtlslib_extract_srtp_keys
and setup VMPTx/VMPRx with this key material.
dtlslib_free_session
and
dtlslib_free_cert
when no longer required.
dtlslib_free
.
A non-blocking UDP endpoint is required. Typically it would provide a packet arrival notification
mechanism that could be used with a timeout or timer queue. Two callback functions, as described below, must be provided to be passed to dtlslib_create_session
.
typedef int (*dtlslib_send_data_cb)(void* ctx, const char* data, unsigned len)
This callback is used by the Prosody DTLS library to implement the underlying BIO_write primitive of the OpenSSL protocol stack.
The ctx
context parameter is that supplied by the application upon invoking dtlslib_create_session
and identifies the UDP endpoint.
The callback should queue a UDP for transmission to the peer DTLS entity associated with the endpoint, having for payload the len
octets
pointed at by data
, and return the value len
to indicate the number of octets sent in the UDP.
typedef int (*dtlslib_read_data_cb)(void* ctx, char* data, unsigned max_len)
This callback is used by the Prosody DTLS library to implement the underlying BIO_read primitive of the OpenSSL protocol stack.
The ctx
context parameter is that supplied by the application upon invoking dtlslib_create_session
and identifies the UDP endpoint.
If a UDP packet is immediately available, its payload should be copied into the buffer pointed at by data
.
A maximum of max_len
octets may be copied. The length of data actually copied should be returned.
If no UDP packet is immediately available, zero should be returned.
The TiNG primitives described in Prosody DTLS processing API provide functions to collect DTLS UDPs arriving at a Prosody managed RTP port and pass down DTLS UDPs to be transmitted by a Prosody module. Example UDP packet handling functions built over these primitives are provided in "dtlslib/udp". The following entry points are provided:
psDTLSSocketInitLib
Initialise library
psDTLSSocketDtorLib
Indicate use of library finished
psDTLSSocketCreate
Gain access to UDP socket in Prosody module
psDTLSSocketDestroy
Release access to UDP socket in Prosody module
psDTLSSocketConfigIPv4
Set IPv4 target address for UDP socket
psDTLSSocketConfigIPv6
Set IPv6 target address for UDP socket
psDTLSSocketSetLimitTime
Set time limit for whole DTLS handshake
psDTLSSocketPoll
Routine to await DTLS packet or indicate timeout
psDTLSSocketSend
A UDP sender that can passed to dtlslib_create_session
psDTLSSocketRcv
A UDP receiver that can be passed to dtlslib_create_session
if "dtlslib.c" is compiled with PRINT_ERRORS defined, then errors from OpenSSL error queue will be written to stdout.
If "dtlslib.c" is compiled with LOG_ERRORS defined, then errors from OpenSSL error queue and the Prosody DTLS library are reported through logging functions:
LogModuleError
Log an error from SSL error queue or other serious error preventing handshake from proceeding
LogModuleWarning
Log a warning
LogModuleDebugMax
Low level debugging output
LogModuleInfo
Informational message
if "dtlslib.c" is compiled with DTLSLIB_SSL_DEBUG defined then OpenSSL packet read and write calls will be dumped to stdout.
dtlslib_init
dtlslib* dtlslib_init(unsigned char* session_context, unsigned int session_context_len)
Initialises OpenSSL library and create new SSL_CTX framework for DTLS connections with profile set up for SRTP_AES128_CM_SHA1_80 or SRTP_AES128_CM_SHA1_32.
pointer to allocated dtlslib if call completed successfully, otherwise NULL pointer.
dtlslib_free
void dtlslib_free(dtlslib* lib)
Frees resources associated with use of OpenSSL.
dtlslib_create_cert
dtlslib_cert* dtlslib_create_cert(enum dtlslib_hash_type ht, int bits, int serial, long lifetime_seconds, const unsigned char* country, const unsigned char* common_name)
Creates public/private keypair and encodes public key as X.509 certificate to be conveyed to peer in DTLS handshakes. The bits parameter determines the strength of encryption used for handshake - typically set to 2048 for WebRTC use. The ht parameter would typically be set to sign the certificate using SHA256 algorithm (dtlslib_hash_type_sha_256).
Pointer to allocated dtlslib_cert if call completed successfully, NULL otherwise.
dtlslib_get_cert_fingerprint
int dtlslib_get_cert_fingerprint(dtlslib_cert* c, char* dest, unsigned int dest_len)
Writes a zero terminated text fingerprint string, suitable for inclusion into SDP, of public key in supplied X.509 certificate.
Length of fingerprint text (excluding terminating zero), or 0 if supplied buffer not long enough to hold fingerprint, or -1 if fingerprint could not be generated.
dtlslib_free_cert
void dtlslib_free_cert(dtlslib_cert* c)
Frees memory resources associated with certificate.
dtlslib_create_session
dtlslib_session* dtlslib_create_session(dtlslib* lib, dtlslib_cert* c, dtlslib_send_data_cb send_cb, void* send_ctx, dtlslib_read_data_cb read_cb, void* read_ctx)
Initialises resources to be used in DTLS handshake using supplied certificate and UDP send/receive instance. The peer port and IP address are transparent to library (normally stored in a send UDP packet context to be used by sender callback).
Pointer to newly allocated DTLS session structure containing a session cookie and other DTLS related items.
dtlslib_free_session
void dtlslib_free_session(dtlslib_session* sess)
Frees resources and memory associated with DTLS session.
dtlslib_start_handshake
int dtlslib_start_handshake(dtlslib_session* sess, int is_server)
If application is client, invoking this call will initiate handshake through sending of first client hello.
If application is server, invoking this call will wait for and respond to first received DTLS packet of a handshake (should be DTLS client hello).
-1 if error stopped handshake from being initiated. 0 if handshake underway. 1 if handshake now complete.
dtlslib_continue
int dtlslib_continue(dtlslib_session* sess)
This function is invoked by an application subsequent to dtlslib_start_handshake upon event of new packet arrival (or non arrival timeout). It processes this event and performs the next action of the DTLS handshake.
-1 if error stopped handshake from being completed. 0 if handshake underway. 1 if handshake now complete.
dtlslib_get_timeout_ms
int dtlslib_get_timeout_ms(dtlslib_session* sess)
This function is invoked by an application subsequent to dtlslib_start_handshake
or dtlslib_continue in order to determine the time within which a response packet is expected.
The returned millisecond count should be used to generate a timeout event in case of non-arrival
of a packet.
If -1 is returned, this indicates an indefinite timeout. Otherwise return value is timeout in milliseconds.
dtlslib_get_remote_fingerprint
int dtlslib_get_remote_fingerprint(dtlslib_session* sess, enum dtlslib_hash_type ht, char* dest, unsigned int dest_len)
Writes a zero terminated text fingerprint string, suitable for comparing with that received in SDP, of public key in certificate received from peer during DTLS handshake. The hash type of the peer certificate will have been indicated in received SDP.
Length of fingerprint text (excluding terminating zero), or 0 if supplied buffer not long enough to hold fingerprint, or -1 if fingerprint could not be generated.
dtlslib_extract_srtp_keys
int dtlslib_extract_srtp_keys(dtlslib_session* sess, enum dtlslib_srtp_mode* mode, char* srtp_tx_key, char* srtp_rx_key)
Writes a value into mode indicating type of authentication tag associated with cipher keys:
0 if cipher key material written, -1 otherwise.
The DTLS library is distributed with Prosody.