Browse code

rtsp: Support decryption of SRTP signalled via RFC 4568 (SDES)

This only takes care of decrypting incoming packets; the outgoing
RTCP packets are not encrypted. This is enough for some use cases,
and signalling crypto keys for use with outgoing RTCP packets
doesn't fit as simply into the API. If the SDP demuxer is hooked
up with custom IO, the return packets can be encrypted e.g. via the
SRTP protocol.

If the SRTP keys aren't available within the SDP, the decryption
can be handled externally as well (when using custom IO).

Signed-off-by: Martin Storsjö <martin@martin.st>

Martin Storsjö authored on 2012/10/21 05:18:01
Showing 7 changed files
... ...
@@ -5,6 +5,7 @@ version 9:
5 5
 - av_basename and av_dirname
6 6
 - adobe and limelight publisher authentication in RTMP
7 7
 - VDPAU hardware acceleration through normal hwaccel
8
+- SRTP support
8 9
 
9 10
 
10 11
 version 9_beta3:
... ...
@@ -40,7 +40,8 @@ OBJS-$(CONFIG_RTPDEC)                    += rdt.o                       \
40 40
                                             rtpdec_qt.o                 \
41 41
                                             rtpdec_svq3.o               \
42 42
                                             rtpdec_vp8.o                \
43
-                                            rtpdec_xiph.o
43
+                                            rtpdec_xiph.o               \
44
+                                            srtp.o
44 45
 OBJS-$(CONFIG_RTPENC_CHAIN)              += rtpenc_chain.o rtp.o
45 46
 
46 47
 # muxers/demuxers
... ...
@@ -26,6 +26,7 @@
26 26
 #include "avformat.h"
27 27
 #include "mpegts.h"
28 28
 #include "network.h"
29
+#include "srtp.h"
29 30
 #include "url.h"
30 31
 #include "rtpdec.h"
31 32
 #include "rtpdec_formats.h"
... ...
@@ -543,6 +544,13 @@ void ff_rtp_parse_set_dynamic_protocol(RTPDemuxContext *s, PayloadContext *ctx,
543 543
     s->handler                  = handler;
544 544
 }
545 545
 
546
+void ff_rtp_parse_set_crypto(RTPDemuxContext *s, const char *suite,
547
+                             const char *params)
548
+{
549
+    if (!ff_srtp_set_crypto(&s->srtp, suite, params))
550
+        s->srtp_enabled = 1;
551
+}
552
+
546 553
 /**
547 554
  * This was the second switch in rtp_parse packet.
548 555
  * Normalizes time, if required, sets stream_index, etc.
... ...
@@ -876,7 +884,10 @@ static int rtp_parse_one_packet(RTPDemuxContext *s, AVPacket *pkt,
876 876
 int ff_rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
877 877
                         uint8_t **bufptr, int len)
878 878
 {
879
-    int rv = rtp_parse_one_packet(s, pkt, bufptr, len);
879
+    int rv;
880
+    if (s->srtp_enabled && bufptr && ff_srtp_decrypt(&s->srtp, *bufptr, &len) < 0)
881
+        return -1;
882
+    rv = rtp_parse_one_packet(s, pkt, bufptr, len);
880 883
     s->prev_ret = rv;
881 884
     while (rv == AVERROR(EAGAIN) && has_next_packet(s))
882 885
         rv = rtp_parse_queued_packet(s, pkt);
... ...
@@ -889,6 +900,7 @@ void ff_rtp_parse_close(RTPDemuxContext *s)
889 889
     if (!strcmp(ff_rtp_enc_name(s->payload_type), "MP2T")) {
890 890
         ff_mpegts_parse_close(s->ts);
891 891
     }
892
+    ff_srtp_free(&s->srtp);
892 893
     av_free(s);
893 894
 }
894 895
 
... ...
@@ -27,6 +27,7 @@
27 27
 #include "avformat.h"
28 28
 #include "rtp.h"
29 29
 #include "url.h"
30
+#include "srtp.h"
30 31
 
31 32
 typedef struct PayloadContext PayloadContext;
32 33
 typedef struct RTPDynamicProtocolHandler RTPDynamicProtocolHandler;
... ...
@@ -43,6 +44,8 @@ RTPDemuxContext *ff_rtp_parse_open(AVFormatContext *s1, AVStream *st,
43 43
                                    int payload_type, int queue_size);
44 44
 void ff_rtp_parse_set_dynamic_protocol(RTPDemuxContext *s, PayloadContext *ctx,
45 45
                                        RTPDynamicProtocolHandler *handler);
46
+void ff_rtp_parse_set_crypto(RTPDemuxContext *s, const char *suite,
47
+                             const char *params);
46 48
 int ff_rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
47 49
                         uint8_t **buf, int len);
48 50
 void ff_rtp_parse_close(RTPDemuxContext *s);
... ...
@@ -163,6 +166,9 @@ struct RTPDemuxContext {
163 163
     /* used to send back RTCP RR */
164 164
     char hostname[256];
165 165
 
166
+    int srtp_enabled;
167
+    struct SRTPContext srtp;
168
+
166 169
     /** Statistics for this stream (used by RTCP receiver reports) */
167 170
     RTPStatistics statistics;
168 171
 
... ...
@@ -479,6 +479,14 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
479 479
                    s->nb_streams > 0) {
480 480
             st = s->streams[s->nb_streams - 1];
481 481
             st->codec->sample_rate = atoi(p);
482
+        } else if (av_strstart(p, "crypto:", &p) && s->nb_streams > 0) {
483
+            // RFC 4568
484
+            rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
485
+            get_word(buf1, sizeof(buf1), &p); // ignore tag
486
+            get_word(rtsp_st->crypto_suite, sizeof(rtsp_st->crypto_suite), &p);
487
+            p += strspn(p, SPACE_CHARS);
488
+            if (av_strstart(p, "inline:", &p))
489
+                get_word(rtsp_st->crypto_params, sizeof(rtsp_st->crypto_params), &p);
482 490
         } else {
483 491
             if (rt->server_type == RTSP_SERVER_WMS)
484 492
                 ff_wms_parse_sdp_a_line(s, p);
... ...
@@ -652,6 +660,10 @@ int ff_rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
652 652
                                               rtsp_st->dynamic_protocol_context,
653 653
                                               rtsp_st->dynamic_handler);
654 654
         }
655
+        if (rtsp_st->crypto_suite[0])
656
+            ff_rtp_parse_set_crypto(rtsp_st->transport_priv,
657
+                                    rtsp_st->crypto_suite,
658
+                                    rtsp_st->crypto_params);
655 659
     }
656 660
 
657 661
     return 0;
... ...
@@ -440,6 +440,9 @@ typedef struct RTSPStream {
440 440
 
441 441
     /** Enable sending RTCP feedback messages according to RFC 4585 */
442 442
     int feedback;
443
+
444
+    char crypto_suite[40];
445
+    char crypto_params[100];
443 446
 } RTSPStream;
444 447
 
445 448
 void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf,
... ...
@@ -31,7 +31,7 @@
31 31
 
32 32
 #define LIBAVFORMAT_VERSION_MAJOR 54
33 33
 #define LIBAVFORMAT_VERSION_MINOR 20
34
-#define LIBAVFORMAT_VERSION_MICRO  4
34
+#define LIBAVFORMAT_VERSION_MICRO  5
35 35
 
36 36
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
37 37
                                                LIBAVFORMAT_VERSION_MINOR, \