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_initdtlslib* 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_freevoid dtlslib_free(dtlslib* lib)
Frees resources associated with use of OpenSSL.
dtlslib_create_certdtlslib_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_fingerprintint 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_certvoid dtlslib_free_cert(dtlslib_cert* c)
Frees memory resources associated with certificate.
dtlslib_create_sessiondtlslib_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_sessionvoid dtlslib_free_session(dtlslib_session* sess)
Frees resources and memory associated with DTLS session.
dtlslib_start_handshakeint 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_continueint 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_msint 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_fingerprintint 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_keysint 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.