Ticket #2018 (closed enhancement: fixed)

Opened 7 weeks ago

Last modified 2 weeks ago

Support DTLS for SRTP keying

Reported by: nanang Owned by: nanang
Priority: normal Milestone: release-2.7
Component: pjmedia Version: trunk
Keywords: Cc:
Backport to 1.x milestone: Backported: no

Description (last modified by nanang) (diff)

DTLS-SRTP is an SRTP keying method that uses media channel for SRTP key negotiation which is secured using TLS. As SRTP key negotiation is done in media channel, confidentiality in SIP signaling is not required, but it needs SIP message integrity for authentication. Peer authentication is done by matching TLS certificate fingerprint (sent via SIP signaling) to actual TLS certificate received in DTLS-SRTP handshake (sent via media channel), so SIP message integrity will guarantee that the TLS certificate fingerprint is not altered from end to end.

DTLS handshake in DTLS-SRTP is basically very similar to TLS handshake, it is just done on UDP socket so it has retransmission mechanism and using a TLS extension for attaching SRTP keying materials (e.g: SRTP crypto profile and key).


  • SDES (the only SRTP keying mechanism currently available in PJMEDIA) and DTLS-SRTP may coexist, any of them may be disabled (at run-time or compile-time).
  • As currently best effort media encryption via SDP capability negotiation is not supported yet, it should be configurable which SRTP keying method to be used in generating offer. And for generating answer, it should detect and use the keying method used by the offer.
  • Support DTLS-SRTP handshake before SDP answer is sent/received.

How to build


  1. OpenSSL version 1.1.0 or newer. DTLS with SRTP extension seems to be available since OpenSSL 1.0.1, but we haven't tried it ourselves.


  1. Set macro PJMEDIA_SRTP_HAS_DTLS to 1 in config_site.h:
    To disable DTLS-SRTP, just set macro PJMEDIA_SRTP_HAS_DTLS to 0 (by default it is currently disabled). To disable SDES, set macro PJMEDIA_SRTP_HAS_SDES to 0 (by default it is currently enabled).
  1. Build PJSIP with TLS enabled using OpenSSL backend.

Sample code for PJSUA app

In generating SDP answer, SRTP will automatically detect and match the keying method to the SDP offer's, e.g: if remote sends offer using DTLS-SRTP, we will start DTLS nego immediately and answer using DTLS-SRTP too. However, in generating SDP offer, SRTP will use SDES by default. So to generate SDP offer using DTLS-SRTP, application needs to implement PJSUA callback on_create_media_transport_srtp and sets the priority of DTLS-SRTP higher than SDES from that callback, e.g:

void on_create_media_transport_srtp(pjsua_call_id call_id,
                                    unsigned media_idx,
                                    pjmedia_srtp_setting *srtp_opt)
    srtp_opt->keying_count = 2;
    srtp_opt->keying[0] = PJMEDIA_SRTP_KEYING_DTLS_SRTP;
    srtp_opt->keying[1] = PJMEDIA_SRTP_KEYING_SDES;

To enable only one keying method at run-time, just set keying_count to 1 and keying[0] to the preferred keying method from the same PJSUA callback, e.g:

void on_create_media_transport_srtp(pjsua_call_id call_id,
                                    unsigned media_idx,
                                    pjmedia_srtp_setting *srtp_opt)
    srtp_opt->keying_count = 1;
    srtp_opt->keying[0] = PJMEDIA_SRTP_KEYING_DTLS_SRTP; /* enable only DTLS-SRTP */


This ticket will only implement the core part of DTLS-SRTP, i.e: SRTP key negotiation via DTLS, while DTLS-SRTP itself also depends on other features that we haven't supported yet:

  1. SIP signaling integrity protection, this may be provided by any of these extensions:
    1. SIP Identity, specified by RFC4474 and RFC4916, only Authentication Service is needed.
    2. S/MIME, specified by RFC3261 section 23.
    3. SIPS, actually we already support this, but as SIPS can't guarantee that all proxies are trusted, the security provided by SIPS is considered weaker.
  2. Best effort media encryption via SDP capability negotiation, to offer media channel with multiple configurations (e.g: offering SRTP but also accept plain RTP), this seems to be a MUST.

Behavior change

  1. Media transport UDP can now be attached multiple times, any old attachment will be silently replaced by the latest. This change is done because DTLS nego needs to access the real transport (UDP/ICE) before stream is created (or SDP nego is completed). After SDP nego is completed, stream will invoke media transport attach() again.
  2. Media transport UDP & ICE is equipped with auto-switching RTP/RTCP target address to the address it receives RTP/RTCP from, and there is probation period (i.e: 10 packets) before switching to the new target address, during this probation period all packets from the candidate target address will be discarded. Now those packets will be no longer discarded as long as we have not received any packet from the current known source address (if any). Without this change, any incoming 'TLS hello' will be discarded until probation period is reached or SDP answer is received (which tell us about remote RTP address).


Change History

comment:1 Changed 7 weeks ago by nanang

  • Description modified (diff)

comment:2 Changed 7 weeks ago by nanang

In 5597:

Re #2018: Initial version of DTLS-SRTP implementation.

comment:3 Changed 7 weeks ago by nanang

In 5598:

Re #2018: Fixed compile error due to a silly mistake.

comment:4 Changed 6 weeks ago by ming

In 5602:

Re #2018: fixed build failure due to undefined function "get_libsrtp_errstr" in transport_srtp_sdes.c

comment:5 Changed 2 weeks ago by nanang

In 5621:

Re #2018: Added API pjmedia_transport_srtp_dtls_start_nego() to start DTLS-SRTP nego without SDP offer/answer.

comment:6 Changed 2 weeks ago by nanang

  • Status changed from new to closed
  • Resolution set to fixed
Note: See TracTickets for help on using tickets.