diff mbox

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

Message ID CAO7y9i_Kw+g1twc8NZ+BpQxhqPMRwkVXsF4ZXVvP5GG_=7j8aA@mail.gmail.com
State New
Headers show

Commit Message

Jacob Trimble June 25, 2018, 5:59 p.m. UTC
Rebased and updated to handle multiple PSSH atoms.  PTAL.

On Tue, Jan 9, 2018 at 10:28 AM Jacob Trimble <modmaker@google.com> wrote:

> On Mon, Jan 8, 2018 at 5:23 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com>
> wrote:
> > 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.
>
> Done
>
> >
> > Thank you, Carl Eugen
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>

Comments

Jacob Trimble July 2, 2018, 4:55 p.m. UTC | #1
On Mon, Jun 25, 2018 at 10:59 AM Jacob Trimble <modmaker@google.com> wrote:
>
> Rebased and updated to handle multiple PSSH atoms.  PTAL.
>
> On Tue, Jan 9, 2018 at 10:28 AM Jacob Trimble <modmaker@google.com> wrote:
>>
>> On Mon, Jan 8, 2018 at 5:23 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
>> > 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.
>>
>> Done
>>
>> >
>> > Thank you, Carl Eugen
>> > _______________________________________________
>> > ffmpeg-devel mailing list
>> > ffmpeg-devel@ffmpeg.org
>> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Ping.
Michael Niedermayer July 3, 2018, 10:26 p.m. UTC | #2
On Mon, Jul 02, 2018 at 09:55:08AM -0700, Jacob Trimble wrote:
> On Mon, Jun 25, 2018 at 10:59 AM Jacob Trimble <modmaker@google.com> wrote:
> >
> > Rebased and updated to handle multiple PSSH atoms.  PTAL.
> >
> > On Tue, Jan 9, 2018 at 10:28 AM Jacob Trimble <modmaker@google.com> wrote:
> >>
> >> On Mon, Jan 8, 2018 at 5:23 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
> >> > 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.
> >>
> >> Done
> >>
> >> >
> >> > Thank you, Carl Eugen
> >> > _______________________________________________
> >> > ffmpeg-devel mailing list
> >> > ffmpeg-devel@ffmpeg.org
> >> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> Ping.

will apply

[...]
diff mbox

Patch

From 2c2c6386432678ea485a84f90a02991f481324e1 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 | 120 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 119 insertions(+), 1 deletion(-)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index 1011763641..1346ffe480 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -6198,6 +6198,114 @@  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, *old_init_info;
+    uint8_t **key_ids;
+    AVStream *st;
+    uint8_t *side_data, *extra_data, *old_side_data;
+    size_t side_data_size;
+    int ret = 0, old_side_data_size;
+    unsigned int version, kid_count, extra_data_size, alloc_size = 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);
+        if (kid_count >= INT_MAX / sizeof(*key_ids))
+            return AVERROR(ENOMEM);
+
+        for (unsigned int i = 0; i < kid_count && !pb->eof_reached; i++) {
+            unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 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;
+
+    // If there is existing initialization data, append to the list.
+    old_side_data = av_stream_get_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO, &old_side_data_size);
+    if (old_side_data) {
+        old_init_info = av_encryption_init_info_get_side_data(old_side_data, old_side_data_size);
+        if (old_init_info) {
+            // Append to the end of the list.
+            for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
+                if (!cur->next) {
+                    cur->next = info;
+                    break;
+                }
+            }
+            info = old_init_info;
+        } else {
+            // Assume existing side-data will be valid, so the only error we could get is OOM.
+            ret = AVERROR(ENOMEM);
+            goto finish;
+        }
+    }
+
+    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_INFO,
+                                  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;
@@ -6398,7 +6506,7 @@  static int cenc_filter(MOVContext *mov, MOVStreamContext *sc, AVPacket *pkt, int
     MOVFragmentStreamInfo *frag_stream_info;
     MOVEncryptionIndex *encryption_index;
     AVEncryptionInfo *encrypted_sample;
-    int encrypted_index;
+    int encrypted_index, ret;
 
     frag_stream_info = get_current_frag_stream_info(&mov->frag_index);
     encrypted_index = current_index;
@@ -6442,6 +6550,15 @@  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);
+            ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
+            if (ret < 0)
+                av_free(side_data);
+            return ret;
         }
     }
 
@@ -6575,6 +6692,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.18.0.rc2.346.g013aa6912e-goog