PR #23394 opened by ThomasDevoogdt
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23394
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23394.patch

Add a minimal MIKEY (RFC 3830) PSK-INIT decoder (ff_mikey_parse) that
extracts SRTP master key and salt from SDP a=key-mgmt:mikey attributes
(RFC 4567).

Only the subset required for RTSPS is implemented: PSK-INIT messages
(data_type 0) with NULL encryption and NULL MAC inside the KEMAC
payload, carrying a TEK or TEK+SALT key data sub-payload (RFC 3830
s6.13).  Any unsupported variant returns AVERROR_PATCHWELCOME so
unhandled configurations are never silently ignored.

The decoded key material is fed into ff_srtp_set_crypto() via the
existing crypto_suite/crypto_params fields on RTSPStream, following the
same path as RFC 4568 a=crypto:.

Also fix the RTSPS handler unconditionally forcing
lower_transport_mask to TCP.  RTSPS secures only the RTSP signalling
channel; the RTP/SRTP media transport is negotiated independently.
Forcing TCP interleaved prevents UDP-based SRTP streams from being
established.  Leave lower_transport_mask untouched so the normal
negotiation order applies and an explicit -rtsp_transport flag is
honoured.

Fixes: #10871

Signed-off-by: Thomas Devoogdt <[email protected]>



>From f441dd99bc5749901e89cf3fc4d57614481cddba Mon Sep 17 00:00:00 2001
From: Thomas Devoogdt <[email protected]>
Date: Fri, 5 Jun 2026 23:28:22 +0200
Subject: [PATCH] avformat/rtsp: add MIKEY PSK-INIT key management for SRTP
 over RTSPS

Add a minimal MIKEY (RFC 3830) PSK-INIT decoder (ff_mikey_parse) that
extracts SRTP master key and salt from SDP a=key-mgmt:mikey attributes
(RFC 4567).

Only the subset required for RTSPS is implemented: PSK-INIT messages
(data_type 0) with NULL encryption and NULL MAC inside the KEMAC
payload, carrying a TEK or TEK+SALT key data sub-payload (RFC 3830
s6.13).  Any unsupported variant returns AVERROR_PATCHWELCOME so
unhandled configurations are never silently ignored.

The decoded key material is fed into ff_srtp_set_crypto() via the
existing crypto_suite/crypto_params fields on RTSPStream, following the
same path as RFC 4568 a=crypto:.

Also fix the RTSPS handler unconditionally forcing
lower_transport_mask to TCP.  RTSPS secures only the RTSP signalling
channel; the RTP/SRTP media transport is negotiated independently.
Forcing TCP interleaved prevents UDP-based SRTP streams from being
established.  Leave lower_transport_mask untouched so the normal
negotiation order applies and an explicit -rtsp_transport flag is
honoured.

Fixes: #10871

Signed-off-by: Thomas Devoogdt <[email protected]>
---
 libavformat/Makefile |   2 +-
 libavformat/mikey.c  | 412 +++++++++++++++++++++++++++++++++++++++++++
 libavformat/mikey.h  |  44 +++++
 libavformat/rtsp.c   |  25 ++-
 4 files changed, 479 insertions(+), 4 deletions(-)
 create mode 100644 libavformat/mikey.c
 create mode 100644 libavformat/mikey.h

diff --git a/libavformat/Makefile b/libavformat/Makefile
index 0db0c7c2a9..12da915688 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -546,7 +546,7 @@ OBJS-$(CONFIG_RTP_MUXER)                 += rtp.o         \
                                             rtpenc_vp8.o  \
                                             rtpenc_vp9.o                \
                                             rtpenc_xiph.o
-OBJS-$(CONFIG_RTSP_DEMUXER)              += rtsp.o rtspdec.o httpauth.o
+OBJS-$(CONFIG_RTSP_DEMUXER)              += rtsp.o rtspdec.o httpauth.o mikey.o
 OBJS-$(CONFIG_RTSP_MUXER)                += rtsp.o rtspenc.o httpauth.o
 OBJS-$(CONFIG_S337M_DEMUXER)             += s337m.o spdif.o
 OBJS-$(CONFIG_SAMI_DEMUXER)              += samidec.o subtitles.o
diff --git a/libavformat/mikey.c b/libavformat/mikey.c
new file mode 100644
index 0000000000..93af635048
--- /dev/null
+++ b/libavformat/mikey.c
@@ -0,0 +1,412 @@
+/*
+ * MIKEY (RFC 3830) PSK-INIT key management for SRTP
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * Minimal MIKEY PSK-INIT decoder (RFC 3830).
+ *
+ * Only the subset needed to extract SRTP master key and salt from a
+ * PSK-INIT message carried over RTSPS is implemented:
+ *   - data_type 0  (PSK-INIT)
+ *   - payload chain: HDR -> T -> RAND -> KEMAC
+ *   - KEMAC encryption: NULL (ENC_NULL = 0)
+ *   - KEMAC MAC:        NULL (MAC_NULL = 0)
+ *   - KEY_DATA type:    TEK (2) or TEK+salt (3), KV = NULL (0)
+ *
+ * Any field value outside this subset is logged at AV_LOG_ERROR and
+ * causes the parser to return AVERROR_PATCHWELCOME so that unsupported
+ * configurations are never silently ignored.
+ *
+ * Wire format is byte-aligned (each logical field occupies one or more
+ * full octets).  See the field layout notes beside each parse step.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "libavutil/base64.h"
+#include "libavutil/error.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/log.h"
+
+#include "mikey.h"
+
+/* RFC 3830 6.1 Table 6.1.b - next-payload type identifiers */
+#define MIKEY_PT_LAST   0
+#define MIKEY_PT_KEMAC  1
+#define MIKEY_PT_T      5
+#define MIKEY_PT_RAND   11
+
+/* RFC 3830 6.1 Table 6.1.a - data_type values */
+#define MIKEY_TYPE_PSK_INIT 0
+
+/* RFC 3830 6.1 Table 6.1.c - PRF function */
+#define MIKEY_PRF_MIKEY_1   0
+
+/* RFC 3830 6.1 Table 6.1.d - CS ID map type */
+#define MIKEY_MAP_TYPE_SRTP 0
+
+/* RFC 3830 6.2 Table 6.2.a - KEMAC encryption algorithm */
+#define MIKEY_ENC_NULL  0
+
+/* RFC 3830 6.2 Table 6.2.b - KEMAC MAC algorithm */
+#define MIKEY_MAC_NULL  0
+
+/* RFC 3830 6.6 Table 6.6 - timestamp type */
+#define MIKEY_TS_NTP_UTC    0
+
+/* RFC 3830 6.13 Table 6.13.a - KEY_DATA Type (upper nibble of byte 1).
+ * TGK (0) and TGK+SALT (1) require TEK derivation (Section 4.1.3),
+ * which is not implemented.  Only TEK (2) and TEK+SALT (3) are accepted. */
+#define MIKEY_KD_TEK            2
+#define MIKEY_KD_TEK_WITH_SALT  3
+
+/* Fixed sizes */
+#define MIKEY_HDR_SIZE          10  /* common header without CS ID map */
+#define MIKEY_CS_SRTP_SIZE       9  /* per-CS SRTP map: 
policy(1)+SSRC(4)+ROC(4) */
+#define MIKEY_RAND_MIN_LEN      16  /* RFC 3830 6.11: RAND SHOULD be >= 16 
bytes */
+#define MIKEY_T_NTP_SIZE         8  /* RFC 3830 6.6: NTP-UTC timestamp */
+
+/* Maximum supported key/salt sizes (AES-128-CM) */
+#define MIKEY_MAX_KEY_LEN   16
+#define MIKEY_MAX_SALT_LEN  14
+
+int ff_mikey_parse(const char *mikey_b64,
+                   char *suite_out, int suite_size,
+                   char *params_out, int params_size,
+                   void *logctx)
+{
+    uint8_t raw[512];
+    uint8_t key[MIKEY_MAX_KEY_LEN];
+    uint8_t salt[MIKEY_MAX_SALT_LEN];
+    uint8_t combined[MIKEY_MAX_KEY_LEN + MIKEY_MAX_SALT_LEN];
+    const uint8_t *d;
+    int raw_len, remaining, key_len, salt_len, n_cs, saw_t, saw_rand;
+    uint8_t next_payload;
+
+    raw_len = av_base64_decode(raw, mikey_b64, sizeof(raw));
+    if (raw_len < 0) {
+        av_log(logctx, AV_LOG_ERROR, "MIKEY: base64 decode failed\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    if (raw_len < MIKEY_HDR_SIZE) {
+        av_log(logctx, AV_LOG_ERROR,
+               "MIKEY: message too short (%d bytes)\n", raw_len);
+        return AVERROR_INVALIDDATA;
+    }
+
+    d         = raw;
+    remaining = raw_len;
+    key_len   = 0;
+    salt_len  = 0;
+    saw_t     = 0;
+    saw_rand  = 0;
+
+    /* RFC 3830 6.1: common header
+     *   [0]   version      (must be 1)
+     *   [1]   data_type    (0 = PSK-INIT)
+     *   [2]   next_payload (type of first payload after header)
+     *   [3]   V(1b) | PRF_func(7b)
+     *   [4-7] CSB_ID       (32-bit big-endian, not needed for key extraction)
+     *   [8]   #CS          (number of crypto sessions)
+     *   [9]   CS_ID_map_type
+     */
+    if (d[0] != 1) {
+        av_log(logctx, AV_LOG_ERROR,
+               "MIKEY: unsupported version %u\n", d[0]);
+        return AVERROR_INVALIDDATA;
+    }
+
+    if (d[1] != MIKEY_TYPE_PSK_INIT) {
+        av_log(logctx, AV_LOG_ERROR,
+               "MIKEY: unsupported data_type %u; only PSK-INIT (%u) 
supported\n",
+               d[1], MIKEY_TYPE_PSK_INIT);
+        return AVERROR_PATCHWELCOME;
+    }
+
+    next_payload = d[2];
+
+    /* RFC 3830 6.1: V flag means the initiator expects a verification-response
+     * message.  It has no bearing on key extraction; ignore it. */
+
+    if ((d[3] & 0x7F) != MIKEY_PRF_MIKEY_1) {
+        av_log(logctx, AV_LOG_ERROR,
+               "MIKEY: unsupported PRF function %u\n", d[3] & 0x7F);
+        return AVERROR_PATCHWELCOME;
+    }
+
+    n_cs = d[8];
+
+    if (d[9] != MIKEY_MAP_TYPE_SRTP) {
+        av_log(logctx, AV_LOG_ERROR,
+               "MIKEY: unsupported CS ID map type %u\n", d[9]);
+        return AVERROR_PATCHWELCOME;
+    }
+
+    if (n_cs != 1) {
+        av_log(logctx, AV_LOG_ERROR,
+               "MIKEY: only single-CS messages supported (got %d)\n", n_cs);
+        return AVERROR_PATCHWELCOME;
+    }
+
+    if (remaining < MIKEY_HDR_SIZE + n_cs * MIKEY_CS_SRTP_SIZE) {
+        av_log(logctx, AV_LOG_ERROR,
+               "MIKEY: message truncated in CS ID map\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    /*
+     * RFC 3830 6.1.1: SRTP CS ID map entry (9 bytes per CS):
+     *   [0]   policy_no
+     *   [1-4] SSRC (32-bit big-endian, not used here)
+     *   [5-8] ROC  (32-bit big-endian, not used here)
+     */
+    d         += MIKEY_HDR_SIZE + n_cs * MIKEY_CS_SRTP_SIZE;
+    remaining -= MIKEY_HDR_SIZE + n_cs * MIKEY_CS_SRTP_SIZE;
+
+    /* RFC 3830 5.3: walk the payload chain */
+    while (next_payload != MIKEY_PT_LAST && remaining > 0) {
+        uint8_t pt = next_payload;
+
+        switch (pt) {
+
+        case MIKEY_PT_T: {
+            /*
+             * RFC 3830 6.6: timestamp payload
+             *   [0] next_payload
+             *   [1] TS_type (0 = NTP-UTC)
+             *   [2-9] 8-byte NTP-UTC timestamp
+             */
+            if (remaining < 2)
+                goto err_truncated;
+            next_payload = d[0];
+            if (d[1] != MIKEY_TS_NTP_UTC) {
+                av_log(logctx, AV_LOG_ERROR,
+                       "MIKEY: unsupported timestamp type %u\n", d[1]);
+                return AVERROR_PATCHWELCOME;
+            }
+            if (remaining < 2 + MIKEY_T_NTP_SIZE)
+                goto err_truncated;
+            saw_t      = 1;
+            d         += 2 + MIKEY_T_NTP_SIZE;
+            remaining -= 2 + MIKEY_T_NTP_SIZE;
+            break;
+        }
+
+        case MIKEY_PT_RAND: {
+            /*
+             * RFC 3830 6.11: RAND payload
+             *   [0] next_payload
+             *   [1] rand_len
+             *   [2 .. 2+rand_len-1] random bytes
+             */
+            uint8_t rand_len;
+            if (remaining < 2)
+                goto err_truncated;
+            next_payload = d[0];
+            rand_len     = d[1];
+            if (rand_len < MIKEY_RAND_MIN_LEN)
+                av_log(logctx, AV_LOG_WARNING,
+                       "MIKEY: RAND too short (%u < %u)\n",
+                       rand_len, MIKEY_RAND_MIN_LEN);
+            if (remaining < 2 + (int)rand_len)
+                goto err_truncated;
+            saw_rand   = 1;
+            d         += 2 + rand_len;
+            remaining -= 2 + rand_len;
+            break;
+        }
+
+        case MIKEY_PT_KEMAC: {
+            /*
+             * RFC 3830 6.2: KEMAC payload
+             *   [0]          next_payload (must be PT_LAST for PSK-INIT)
+             *   [1]          enc_alg      (must be ENC_NULL)
+             *   [2-3]        enc_len      (length of encrypted data, BE16)
+             *   [4 .. 4+enc_len-1]  encrypted key-data region
+             *   [4+enc_len]  mac_alg      (must be MAC_NULL)
+             *
+             * RFC 3830 6.13: KEY_DATA sub-payload inside the encrypted region
+             *   [0]    Next payload (0 = last; only one sub-payload supported)
+             *   [1]    Type(4b) | KV(4b)
+             *   [2-3]  Key data len (BE16)
+             *   [4 .. 4+key_len-1]  Key data
+             *   if type == MIKEY_KD_TEK_WITH_SALT:
+             *     [4+key_len .. 4+key_len+1]  salt_len (BE16)
+             *     [4+key_len+2 .. ...]         salt bytes
+             */
+            const uint8_t *enc_data;
+            uint8_t enc_alg, mac_alg, sub_next, type_kv, kd_type, kv_type;
+            uint16_t enc_len, kd_key_len;
+            int has_salt, pos;
+
+            if (remaining < 5)
+                goto err_truncated;
+
+            /* RFC 3830 3.1: PSK-INIT ordering requires T and RAND before 
KEMAC */
+            if (!saw_t || !saw_rand) {
+                av_log(logctx, AV_LOG_ERROR,
+                       "MIKEY: T and RAND payloads must precede KEMAC\n");
+                return AVERROR_INVALIDDATA;
+            }
+
+            enc_alg = d[1];
+            enc_len = AV_RB16(d + 2);
+
+            /* RFC 3830 4.2.3: assert NULL encryption */
+            if (enc_alg != MIKEY_ENC_NULL) {
+                av_log(logctx, AV_LOG_ERROR,
+                       "MIKEY: KEMAC encryption alg %u not supported; "
+                       "only NULL (%u) is accepted over RTSPS\n",
+                       enc_alg, MIKEY_ENC_NULL);
+                return AVERROR_PATCHWELCOME;
+            }
+
+            if (remaining < 5 + (int)enc_len)
+                goto err_truncated;
+
+            mac_alg = d[4 + enc_len];
+
+            /* RFC 3830 4.2.4: assert NULL MAC */
+            if (mac_alg != MIKEY_MAC_NULL) {
+                av_log(logctx, AV_LOG_ERROR,
+                       "MIKEY: KEMAC MAC alg %u not supported; "
+                       "only NULL (%u) is accepted over RTSPS\n",
+                       mac_alg, MIKEY_MAC_NULL);
+                return AVERROR_PATCHWELCOME;
+            }
+
+            if (d[0] != MIKEY_PT_LAST) {
+                av_log(logctx, AV_LOG_ERROR,
+                       "MIKEY: additional payloads after KEMAC not 
supported\n");
+                return AVERROR_PATCHWELCOME;
+            }
+
+            /* Parse KEY_DATA sub-payload */
+            enc_data = d + 4;
+            if (enc_len < 4)
+                goto err_truncated;
+
+            sub_next = enc_data[0];
+            if (sub_next != MIKEY_PT_LAST) {
+                av_log(logctx, AV_LOG_ERROR,
+                       "MIKEY: multiple KEY_DATA sub-payloads not 
supported\n");
+                return AVERROR_PATCHWELCOME;
+            }
+
+            type_kv = enc_data[1];
+            kd_type = (type_kv >> 4) & 0x0F;
+            kv_type =  type_kv       & 0x0F;
+
+            if (kv_type != 0) {
+                av_log(logctx, AV_LOG_ERROR,
+                       "MIKEY: KEY_DATA KV type %u not supported; "
+                       "only NULL (0)\n", kv_type);
+                return AVERROR_PATCHWELCOME;
+            }
+
+            if (kd_type != MIKEY_KD_TEK && kd_type != MIKEY_KD_TEK_WITH_SALT) {
+                av_log(logctx, AV_LOG_ERROR,
+                       "MIKEY: unsupported KEY_DATA type %u\n", kd_type);
+                return AVERROR_PATCHWELCOME;
+            }
+
+            has_salt   = (kd_type == MIKEY_KD_TEK_WITH_SALT);
+            kd_key_len = AV_RB16(enc_data + 2);
+
+            if (!kd_key_len || (int)enc_len < 4 + (int)kd_key_len)
+                goto err_truncated;
+
+            if (kd_key_len > MIKEY_MAX_KEY_LEN) {
+                av_log(logctx, AV_LOG_ERROR,
+                       "MIKEY: key too large (%u > %d)\n",
+                       kd_key_len, MIKEY_MAX_KEY_LEN);
+                return AVERROR_INVALIDDATA;
+            }
+
+            key_len = kd_key_len;
+            memcpy(key, enc_data + 4, key_len);
+            pos = 4 + key_len;
+
+            if (has_salt) {
+                uint16_t kd_salt_len;
+                if ((int)enc_len < pos + 2)
+                    goto err_truncated;
+                kd_salt_len = AV_RB16(enc_data + pos);
+                pos += 2;
+                if (!kd_salt_len || (int)enc_len < pos + (int)kd_salt_len)
+                    goto err_truncated;
+                if (kd_salt_len > MIKEY_MAX_SALT_LEN) {
+                    av_log(logctx, AV_LOG_ERROR,
+                           "MIKEY: salt too large (%u > %d)\n",
+                           kd_salt_len, MIKEY_MAX_SALT_LEN);
+                    return AVERROR_INVALIDDATA;
+                }
+                salt_len = kd_salt_len;
+                memcpy(salt, enc_data + pos, salt_len);
+            } else {
+                av_log(logctx, AV_LOG_WARNING,
+                       "MIKEY: no salt in KEY_DATA, using zero salt\n");
+                salt_len = MIKEY_MAX_SALT_LEN;
+                memset(salt, 0, salt_len);
+            }
+
+            goto done;
+        }
+
+        default:
+            av_log(logctx, AV_LOG_ERROR,
+                   "MIKEY: unknown payload type %u\n", pt);
+            return AVERROR_INVALIDDATA;
+        }
+    }
+
+    av_log(logctx, AV_LOG_ERROR, "MIKEY: no KEMAC payload found\n");
+    return AVERROR_INVALIDDATA;
+
+err_truncated:
+    av_log(logctx, AV_LOG_ERROR, "MIKEY: message truncated\n");
+    return AVERROR_INVALIDDATA;
+
+done:
+    /* Derive SRTP suite name from key length */
+    if (key_len == 16) {
+        snprintf(suite_out, suite_size, "AES_CM_128_HMAC_SHA1_80");
+    } else {
+        av_log(logctx, AV_LOG_ERROR,
+               "MIKEY: unsupported key length %d\n", key_len);
+        return AVERROR_PATCHWELCOME;
+    }
+
+    /*
+     * ff_srtp_set_crypto() expects params as base64(master_key || 
master_salt),
+     * i.e. 16 + 14 = 30 raw bytes -> 40 base64 characters.
+     */
+    memcpy(combined, key,  key_len);
+    memcpy(combined + key_len, salt, salt_len);
+
+    if (!av_base64_encode(params_out, params_size, combined, key_len + 
salt_len)) {
+        av_log(logctx, AV_LOG_ERROR,
+               "MIKEY: params output buffer too small\n");
+        return AVERROR(EINVAL);
+    }
+
+    return 0;
+}
diff --git a/libavformat/mikey.h b/libavformat/mikey.h
new file mode 100644
index 0000000000..069acabf94
--- /dev/null
+++ b/libavformat/mikey.h
@@ -0,0 +1,44 @@
+/*
+ * MIKEY (RFC 3830) PSK-INIT key management for SRTP
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVFORMAT_MIKEY_H
+#define AVFORMAT_MIKEY_H
+
+/**
+ * Parse a base64-encoded MIKEY PSK-INIT message from an SDP a=key-mgmt:mikey
+ * attribute and extract SRTP key material for ff_srtp_set_crypto().
+ *
+ * Supported: PSK-INIT (data_type 0), NULL encryption, NULL MAC (RFC 3830).
+ * Any other variant returns AVERROR_PATCHWELCOME.
+ *
+ * @param mikey_b64   NUL-terminated base64 MIKEY PDU.
+ * @param suite_out   Output buffer for the SRTP suite name (e.g. 
"AES_CM_128_HMAC_SHA1_80").
+ * @param suite_size  Size of suite_out in bytes.
+ * @param params_out  Output buffer for the base64-encoded key || salt string.
+ * @param params_size Size of params_out in bytes.
+ * @param logctx      Logging context (may be NULL).
+ * @return 0 on success, negative AVERROR on failure.
+ */
+int ff_mikey_parse(const char *mikey_b64,
+                   char *suite_out, int suite_size,
+                   char *params_out, int params_size,
+                   void *logctx);
+
+#endif /* AVFORMAT_MIKEY_H */
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 45b62c4188..8a4ae7600f 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -56,6 +56,7 @@
 #include "tls.h"
 #include "rtpenc.h"
 #include "mpegts.h"
+#include "mikey.h"
 #include "version.h"
 
 /* Default timeout values for read packet in seconds  */
@@ -691,6 +692,25 @@ static void sdp_parse_line(AVFormatContext *s, 
SDPParseState *s1,
             p += strspn(p, SPACE_CHARS);
             if (av_strstart(p, "inline:", &p))
                 get_word(rtsp_st->crypto_params, 
sizeof(rtsp_st->crypto_params), &p);
+        } else if (av_strstart(p, "key-mgmt:", &p) && s->nb_streams > 0) {
+            // RFC 4567
+            char keymgmt_b64[512];
+            rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
+            p += strspn(p, SPACE_CHARS);
+            if (av_strstart(p, "mikey", &p)) {
+                p += strspn(p, SPACE_CHARS);
+                get_word(keymgmt_b64, sizeof(keymgmt_b64), &p);
+                if (ff_mikey_parse(keymgmt_b64,
+                                   rtsp_st->crypto_suite,
+                                   sizeof(rtsp_st->crypto_suite),
+                                   rtsp_st->crypto_params,
+                                   sizeof(rtsp_st->crypto_params), s) < 0)
+                    av_log(s, AV_LOG_WARNING,
+                           "Failed to parse MIKEY key-mgmt attribute\n");
+            } else {
+                av_log(s, AV_LOG_WARNING,
+                       "Unsupported key-mgmt protocol in SDP: %.20s\n", p);
+            }
         } else if (av_strstart(p, "source-filter:", &p)) {
             int exclude = 0;
             get_word(buf1, sizeof(buf1), &p);
@@ -1914,9 +1934,8 @@ redirect:
                  host, sizeof(host), &port, path, sizeof(path), s->url);
 
     if (!strcmp(proto, "rtsps")) {
-        lower_rtsp_proto         = "tls";
-        default_port             = RTSPS_DEFAULT_PORT;
-        rt->lower_transport_mask = 1 << RTSP_LOWER_TRANSPORT_TCP;
+        lower_rtsp_proto = "tls";
+        default_port     = RTSPS_DEFAULT_PORT;
     } else if (!strcmp(proto, "satip")) {
         av_strlcpy(proto, "rtsp", sizeof(proto));
         rt->server_type = RTSP_SERVER_SATIP;
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to