[FFmpeg-devel,3/3] avformat/mov: Expose encryption info to the app.

Submitted by Jacob Trimble on Jan. 8, 2018, 11:22 p.m.

Details

Message ID CAO7y9i8S3950KMO5whS2KQd+0f1SHEhH7TKPVXKci8LX=ZWsMQ@mail.gmail.com
State New
Headers show

Commit Message

Jacob Trimble Jan. 8, 2018, 11:22 p.m.
On Fri, Jan 5, 2018 at 12:55 PM, Jacob Trimble <modmaker@google.com> wrote:
> On Fri, Jan 5, 2018 at 12:43 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
>> 2018-01-05 20:49 GMT+01:00 Jacob Trimble <modmaker-at-google.com@ffmpeg.org>:
>>
>>> +    AV_WB32(side_data, size);
>>> +    AV_WL32(side_data + 4, MKTAG('p','s','s','h'));
>>
>> I didn't check:
>> Is this what applications on both big- and little-endian expect?
>
> Yes.  This should match the MP4 atom, so the size and 'pssh' string
> should be big-endian.
>
>>
>> Carl Eugen
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Updated with the new design for the side data and applied the realloc
fix to avoid large allocations.

Comments

Carl Eugen Hoyos Jan. 9, 2018, 1:23 a.m.
2018-01-09 0:22 GMT+01:00 Jacob Trimble <modmaker-at-google.com@ffmpeg.org>:

> Updated with the new design for the side data and applied the realloc
> fix to avoid large allocations.

> +        kid_count = avio_rb32(pb);

Missing check here ...

> +        for (; i < kid_count && !pb->eof_reached; i++) {
> +            unsigned int min_kid_count = FFMIN(FFMAX(i, 1024), kid_count);
> +            key_ids = av_fast_realloc(info->key_ids, &alloc_size,

> +                                      min_kid_count * sizeof(*key_ids));

... for an overflow here.

Thank you, Carl Eugen

Patch hide | download patch | download mbox

From da01baef5ead8194a991470de6b477ab59424617 Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modmaker@google.com>
Date: Wed, 6 Dec 2017 16:17:54 -0800
Subject: [PATCH] avformat/mov: Expose encryption info to the app.

This exposes encryption info from the container to the app.  This
includes key ID, IV, and subsample byte ranges.  The info is passed
using the new side-data AV_PKT_DATA_ENCRYPTION_DATA and
AV_PKT_DATA_ENCRYPTION_INIT_DATA.

Signed-off-by: Jacob Trimble <modmaker@google.com>
---
 libavformat/mov.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index 71cc9a3af3..30165e6dc5 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -6080,6 +6080,91 @@  static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     return 0;
 }
 
+static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+    AVEncryptionInitInfo *info;
+    uint8_t **key_ids;
+    AVStream *st;
+    uint8_t *side_data, *extra_data;
+    size_t side_data_size;
+    int ret = 0;
+    unsigned int version, kid_count, extra_data_size, alloc_size = 0, i = 0;
+
+    if (c->fc->nb_streams < 1)
+        return 0;
+    st = c->fc->streams[c->fc->nb_streams-1];
+
+    version = avio_r8(pb); /* version */
+    avio_rb24(pb);  /* flags */
+
+    info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
+                                         /* key_id_size */ 16, /* data_size */ 0);
+    if (!info)
+        return AVERROR(ENOMEM);
+
+    if (avio_read(pb, info->system_id, 16) != 16) {
+        av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
+        ret = AVERROR_INVALIDDATA;
+        goto finish;
+    }
+
+    if (version > 0) {
+        kid_count = avio_rb32(pb);
+        for (; i < kid_count && !pb->eof_reached; i++) {
+            unsigned int min_kid_count = FFMIN(FFMAX(i, 1024), kid_count);
+            key_ids = av_fast_realloc(info->key_ids, &alloc_size,
+                                      min_kid_count * sizeof(*key_ids));
+            if (!key_ids) {
+                ret = AVERROR(ENOMEM);
+                goto finish;
+            }
+            info->key_ids = key_ids;
+
+            info->key_ids[i] = av_mallocz(16);
+            if (!info->key_ids[i]) {
+                ret = AVERROR(ENOMEM);
+                goto finish;
+            }
+            info->num_key_ids = i + 1;
+
+            if (avio_read(pb, info->key_ids[i], 16) != 16) {
+                av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
+                ret = AVERROR_INVALIDDATA;
+                goto finish;
+            }
+        }
+
+        if (pb->eof_reached) {
+            av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
+            ret = AVERROR_INVALIDDATA;
+            goto finish;
+        }
+    }
+
+    extra_data_size = avio_rb32(pb);
+    ret = mov_try_read_block(pb, extra_data_size, &extra_data);
+    if (ret < 0)
+        goto finish;
+
+    av_freep(&info->data);  // malloc(0) may still allocate something.
+    info->data = extra_data;
+    info->data_size = extra_data_size;
+
+    side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
+    if (!side_data) {
+        ret = AVERROR(ENOMEM);
+        goto finish;
+    }
+    ret = av_stream_add_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_DATA,
+                                  side_data, side_data_size);
+    if (ret < 0)
+        av_free(side_data);
+
+finish:
+    av_encryption_init_info_free(info);
+    return ret;
+}
+
 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 {
     AVStream *st;
@@ -6319,6 +6404,12 @@  static int cenc_filter(MOVContext *mov, MOVStreamContext *sc, AVPacket *pkt, int
 
         if (mov->decryption_key) {
             return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
+        } else {
+            size_t size;
+            uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
+            if (!side_data)
+                return AVERROR(ENOMEM);
+            return av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
         }
     }
 
@@ -6452,6 +6543,7 @@  static const MOVParseTableEntry mov_default_parse_table[] = {
 { MKTAG('s','e','n','c'), mov_read_senc },
 { MKTAG('s','a','i','z'), mov_read_saiz },
 { MKTAG('s','a','i','o'), mov_read_saio },
+{ MKTAG('p','s','s','h'), mov_read_pssh },
 { MKTAG('s','c','h','m'), mov_read_schm },
 { MKTAG('s','c','h','i'), mov_read_default },
 { MKTAG('t','e','n','c'), mov_read_tenc },
-- 
2.16.0.rc0.223.g4a4ac83678-goog