[FFmpeg-devel] [PATCH] libavformat/mov: Fix NULL-dereference read for some encrypted content.

2018-12-19 Thread Jacob Trimble
When reading frames, we need to use the fragment for the correct
stream.  Sometimes the "current" fragment is not the same as the one
the frame is for.

Found by Chromium's ClusterFuzz:
https://crbug.com/906392 and https://crbug.com/915524

Signed-off-by: Jacob Trimble 
---
 libavformat/mov.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index fb95fd2fef..cefdedb1bd 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -6561,14 +6561,14 @@ static int cenc_decrypt(MOVContext *c, MOVStreamContext 
*sc, AVEncryptionInfo *s
 return 0;
 }
 
-static int cenc_filter(MOVContext *mov, MOVStreamContext *sc, AVPacket *pkt, 
int current_index)
+static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, 
AVPacket *pkt, int current_index)
 {
 MOVFragmentStreamInfo *frag_stream_info;
 MOVEncryptionIndex *encryption_index;
 AVEncryptionInfo *encrypted_sample;
 int encrypted_index, ret;
 
-frag_stream_info = get_current_frag_stream_info(>frag_index);
+frag_stream_info = get_frag_stream_info(>frag_index, 
mov->frag_index.current, st->id);
 encrypted_index = current_index;
 encryption_index = NULL;
 if (frag_stream_info) {
@@ -7798,7 +7798,7 @@ static int mov_read_packet(AVFormatContext *s, AVPacket 
*pkt)
 if (mov->aax_mode)
 aax_filter(pkt->data, pkt->size, mov);
 
-ret = cenc_filter(mov, sc, pkt, current_index);
+ret = cenc_filter(mov, st, sc, pkt, current_index);
 if (ret < 0)
 return ret;
 
-- 
2.20.1.415.g653613c723-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/utils: Don't parse encrypted packets.

2018-10-23 Thread Jacob Trimble
On Mon, Oct 1, 2018 at 11:30 AM Jacob Trimble  wrote:
>
> On Mon, Sep 17, 2018 at 2:35 PM Jacob Trimble  wrote:
> >
> > On Wed, Sep 12, 2018 at 11:50 AM Michael Niedermayer
> >  wrote:
> > >
> > > On Tue, Sep 11, 2018 at 03:50:57PM -0700, Jacob Trimble wrote:
> > > > [...]
> > > >
> > > > So how about, when we see an encrypted frame, we flush the parser
> > > > before skipping the frame?  Can we just flush the parser and then
> > > > reuse it later?  Or would we need to create a new parser if we saw
> > > > clear frames later?
> > >
> > > try/test it and review the code. only way to know for sure what works
> > >
> > > thanks
> > >
> > > [...]
> > > --
> > > Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
> > >
> > > The bravest are surely those who have the clearest vision
> > > of what is before them, glory and danger alike, and yet
> > > notwithstanding go out to meet it. -- Thucydides
> > > ___
> > > ffmpeg-devel mailing list
> > > ffmpeg-devel@ffmpeg.org
> > > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >
> > Here is a new patch that flushes the parser before returning the
> > encrypted packets.  It also logs when it does this.
>
> Ping.  Is this better?

Ping.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/utils: Don't parse encrypted packets.

2018-10-01 Thread Jacob Trimble
On Mon, Sep 17, 2018 at 2:35 PM Jacob Trimble  wrote:
>
> On Wed, Sep 12, 2018 at 11:50 AM Michael Niedermayer
>  wrote:
> >
> > On Tue, Sep 11, 2018 at 03:50:57PM -0700, Jacob Trimble wrote:
> > > [...]
> > >
> > > So how about, when we see an encrypted frame, we flush the parser
> > > before skipping the frame?  Can we just flush the parser and then
> > > reuse it later?  Or would we need to create a new parser if we saw
> > > clear frames later?
> >
> > try/test it and review the code. only way to know for sure what works
> >
> > thanks
> >
> > [...]
> > --
> > Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
> >
> > The bravest are surely those who have the clearest vision
> > of what is before them, glory and danger alike, and yet
> > notwithstanding go out to meet it. -- Thucydides
> > ___
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> Here is a new patch that flushes the parser before returning the
> encrypted packets.  It also logs when it does this.

Ping.  Is this better?
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/utils: Don't parse encrypted packets.

2018-09-17 Thread Jacob Trimble
On Wed, Sep 12, 2018 at 11:50 AM Michael Niedermayer
 wrote:
>
> On Tue, Sep 11, 2018 at 03:50:57PM -0700, Jacob Trimble wrote:
> > [...]
> >
> > So how about, when we see an encrypted frame, we flush the parser
> > before skipping the frame?  Can we just flush the parser and then
> > reuse it later?  Or would we need to create a new parser if we saw
> > clear frames later?
>
> try/test it and review the code. only way to know for sure what works
>
> thanks
>
> [...]
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> The bravest are surely those who have the clearest vision
> of what is before them, glory and danger alike, and yet
> notwithstanding go out to meet it. -- Thucydides
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Here is a new patch that flushes the parser before returning the
encrypted packets.  It also logs when it does this.
From 3955dad8070c28b021afc3304939500a09c86fcd Mon Sep 17 00:00:00 2001
From: Jacob Trimble 
Date: Tue, 28 Aug 2018 10:40:29 -0700
Subject: [PATCH] avformat/utils: Don't parse encrypted packets.

If a packet is full-sample encrypted, then packet data can't be parsed
without decrypting it.  So this skips the packet parsing for those
packets.  If the packet has sub-sample encryption, it is assumed that
the headers are in the clear and the parser will only need that info.

Signed-off-by: Jacob Trimble 
---
 libavformat/utils.c | 41 -
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/libavformat/utils.c b/libavformat/utils.c
index a72f0a482e..8d84674797 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -27,6 +27,7 @@
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
 #include "libavutil/dict.h"
+#include "libavutil/encryption_info.h"
 #include "libavutil/internal.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
@@ -1576,6 +1577,9 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
 while (!got_packet && !s->internal->parse_queue) {
 AVStream *st;
 AVPacket cur_pkt;
+uint8_t *enc_side_data;
+int enc_side_data_size;
+int is_full_encrypted = 0;
 
 /* read next packet */
 ret = ff_read_packet(s, _pkt);
@@ -1643,7 +1647,23 @@ FF_ENABLE_DEPRECATION_WARNINGS
av_ts2str(cur_pkt.dts),
cur_pkt.size, cur_pkt.duration, cur_pkt.flags);
 
-if (st->need_parsing && !st->parser && !(s->flags & AVFMT_FLAG_NOPARSE)) {
+/* if the packet is full-sample encrypted, we can't parse it.  If the
+ * packet uses sub-sample encryption, assume the headers are clear and
+ * can still be parsed.
+ */
+enc_side_data = av_packet_get_side_data(
+_pkt, AV_PKT_DATA_ENCRYPTION_INFO, _side_data_size);
+if (enc_side_data) {
+AVEncryptionInfo *enc_info =
+av_encryption_info_get_side_data(enc_side_data, enc_side_data_size);
+if (enc_info) {
+is_full_encrypted = enc_info->subsample_count == 0;
+av_encryption_info_free(enc_info);
+}
+}
+
+if (st->need_parsing && !st->parser && !(s->flags & AVFMT_FLAG_NOPARSE) &&
+!is_full_encrypted) {
 st->parser = av_parser_init(st->codecpar->codec_id);
 if (!st->parser) {
 av_log(s, AV_LOG_VERBOSE, "parser not found for codec "
@@ -1659,6 +1679,25 @@ FF_ENABLE_DEPRECATION_WARNINGS
 st->parser->flags |= PARSER_FLAG_USE_CODEC_TS;
 }
 
+if (st->parser && is_full_encrypted) {
+av_log(s, AV_LOG_VERBOSE, "skipping parsing of encrypted packets.\n");
+
+/* flush any packets from the parser. */
+parse_packet(s, NULL, cur_pkt.stream_index);
+if (s->internal->parse_queue) {
+/* if we have other packets, append this packet to the end and read
+ * from the queue instead. */
+compute_pkt_fields(s, st, NULL, _pkt, AV_NOPTS_VALUE, AV_NOPTS_VALUE);
+ret = ff_packet_list_put(>internal->parse_queue,
+ >internal->parse_queue_end,
+ _pkt, 0);
+if (ret < 0)
+return ret;
+break;
+}
+av_assert2(!st->parser);
+}
+
 if (!st->need_parsing || !st->parser) {
 /* no parsing needed: we just output the packet as is */
 *pkt = cur_pkt;
-- 
2.19.0.397.gdd90340f6a-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/utils: Don't parse encrypted packets.

2018-09-11 Thread Jacob Trimble
On Tue, Sep 11, 2018 at 1:48 PM Michael Niedermayer
 wrote:
>
> On Thu, Aug 30, 2018 at 08:43:25AM -0700, Jacob Trimble wrote:
> > On Wed, Aug 29, 2018 at 4:37 PM Michael Niedermayer
> >  wrote:
> > >
> > > On Wed, Aug 29, 2018 at 03:30:39PM -0700, Jacob Trimble wrote:
> > > > On Wed, Aug 29, 2018 at 3:20 PM James Almer  wrote:
> > > > >
> > > > > On 8/29/2018 7:07 PM, Michael Niedermayer wrote:
> > > > > > On Tue, Aug 28, 2018 at 10:58:43AM -0700, Jacob Trimble wrote:
> > > > > >> If a packet is full-sample encrypted, then packet data can't be 
> > > > > >> parsed
> > > > > >> without decrypting it.  So this skips the packet parsing for those
> > > > > >> packets.  If the packet has sub-sample encryption, it is assumed 
> > > > > >> that
> > > > > >> the headers are in the clear and the parser will only need that 
> > > > > >> info.
> > > > > >>
> > > > > >> Signed-off-by: Jacob Trimble 
> > > > > >> ---
> > > > > >>  libavformat/utils.c | 21 -
> > > > > >>  1 file changed, 20 insertions(+), 1 deletion(-)
> > > > > >
> > > > > > Hmm, please correct me if iam wrong but IIUC
> > > > > > 1. The demuxer has set need_parsing, indicating that it _requires_ 
> > > > > > a parser
> > > >
> > > > There isn't a flag for "try parsing and ignore errors".  So my choice
> > > > (from an app) is to either require parsing or don't do parsing at all
> > > > (which can result in incorrect timestamps).
> > > >
> > > > > > 2. Parsing cannot be done before decrypting
> > > > > >
> > > > > > If all this and the set values are correct, logically, the fix 
> > > > > > would be
> > > > > > to decrypt the packet before the parser not to skip the parser.
> > > >
> > >
> > > > There are cases where the packet can't be decrypted before getting to
> > > > this point.
> > >
> > > Can you elaborate on these cases ? I dont think its obvious what these
> > > cases are, at least its not obvious to me what exactly you are thinking
> > > of here. And i think its not helpfull if i guess what you mean and then
> > > argue/comment on that because maybe you meant something entirely 
> > > different ...
> >
> > Fair warning, I am working on a DRM solution.  I know many of you may
> > not agree with DRM, but it is a requirement imposed by content
> > creators.  FFmpeg doesn't have to support DRM itself, but you should
> > still consider its usages.
> >
> > At that point in the code, the packet can only be decrypted by the
> > demuxer.  For example, in MP4 this can be done by passing the
> > -decryption_key parameter.  But that requires that FFmpeg handle the
> > decryption.  In my case, we are passing the packet to a CDM (content
> > decryption module) to handle the decryption and that might be a
> > hardware-secure decryptor.  In most DRM situations, we can't get the
> > raw key at all, all we can do is say "decrypt this block of memory".
> > So the only way to have the packet decrypted before this point would
> > be to introduce a callback to the app to decrypt the packet.
>
> 1. If the demuxer sets need_parsing it requires parsing
> 2. If the demuxer requires parsing then parsing should be done
> 3. If parsing cannot be done but is required thats a error and should produce
>some warning or error message. It should not be part of some intended
>design
>

So would a log be enough?  That's what happens if the parser fails to
be created or can't be found.

>
> >
> > This is why I have been working on exposing the encryption info.  My
> > app (or more correctly the CDM) needs to handle the decryption and we
> > can't just give the key to libavformat so the demuxer can decrypt the
> > packet.
> >
> > >
> > >
> > > > This point is between the demuxer creating the packet and
> > > > giving to the app.  So the only way to decrypt the frame (as of now)
> > > > is for the demuxer to do this.  There is no way for the app to handle
> > > > the decryption before this point.
> > > >
> > >
> > > > From the app's perspective, I would expect the packet to remain
> > > > encrypted for as long as possib

Re: [FFmpeg-devel] [PATCH] avformat/utils: Don't parse encrypted packets.

2018-09-11 Thread Jacob Trimble
On Thu, Aug 30, 2018 at 8:43 AM Jacob Trimble  wrote:
>
> On Wed, Aug 29, 2018 at 4:37 PM Michael Niedermayer
>  wrote:
> >
> > On Wed, Aug 29, 2018 at 03:30:39PM -0700, Jacob Trimble wrote:
> > > On Wed, Aug 29, 2018 at 3:20 PM James Almer  wrote:
> > > >
> > > > On 8/29/2018 7:07 PM, Michael Niedermayer wrote:
> > > > > On Tue, Aug 28, 2018 at 10:58:43AM -0700, Jacob Trimble wrote:
> > > > >> If a packet is full-sample encrypted, then packet data can't be 
> > > > >> parsed
> > > > >> without decrypting it.  So this skips the packet parsing for those
> > > > >> packets.  If the packet has sub-sample encryption, it is assumed that
> > > > >> the headers are in the clear and the parser will only need that info.
> > > > >>
> > > > >> Signed-off-by: Jacob Trimble 
> > > > >> ---
> > > > >>  libavformat/utils.c | 21 -
> > > > >>  1 file changed, 20 insertions(+), 1 deletion(-)
> > > > >
> > > > > Hmm, please correct me if iam wrong but IIUC
> > > > > 1. The demuxer has set need_parsing, indicating that it _requires_ a 
> > > > > parser
> > >
> > > There isn't a flag for "try parsing and ignore errors".  So my choice
> > > (from an app) is to either require parsing or don't do parsing at all
> > > (which can result in incorrect timestamps).
> > >
> > > > > 2. Parsing cannot be done before decrypting
> > > > >
> > > > > If all this and the set values are correct, logically, the fix would 
> > > > > be
> > > > > to decrypt the packet before the parser not to skip the parser.
> > >
> >
> > > There are cases where the packet can't be decrypted before getting to
> > > this point.
> >
> > Can you elaborate on these cases ? I dont think its obvious what these
> > cases are, at least its not obvious to me what exactly you are thinking
> > of here. And i think its not helpfull if i guess what you mean and then
> > argue/comment on that because maybe you meant something entirely different 
> > ...
>
> Fair warning, I am working on a DRM solution.  I know many of you may
> not agree with DRM, but it is a requirement imposed by content
> creators.  FFmpeg doesn't have to support DRM itself, but you should
> still consider its usages.
>
> At that point in the code, the packet can only be decrypted by the
> demuxer.  For example, in MP4 this can be done by passing the
> -decryption_key parameter.  But that requires that FFmpeg handle the
> decryption.  In my case, we are passing the packet to a CDM (content
> decryption module) to handle the decryption and that might be a
> hardware-secure decryptor.  In most DRM situations, we can't get the
> raw key at all, all we can do is say "decrypt this block of memory".
> So the only way to have the packet decrypted before this point would
> be to introduce a callback to the app to decrypt the packet.
>
> This is why I have been working on exposing the encryption info.  My
> app (or more correctly the CDM) needs to handle the decryption and we
> can't just give the key to libavformat so the demuxer can decrypt the
> packet.
>
> >
> >
> > > This point is between the demuxer creating the packet and
> > > giving to the app.  So the only way to decrypt the frame (as of now)
> > > is for the demuxer to do this.  There is no way for the app to handle
> > > the decryption before this point.
> > >
> >
> > > From the app's perspective, I would expect the packet to remain
> > > encrypted for as long as possible.
> >
> > why ?
>
> Because the point of encryption is to ensure that nefarious parties
> don't get access to the data.  Even though the packet data is stored
> in memory, it could still be retrieved by a malicious user.  Usually
> for protected media, the frames are only decrypted when needed and in
> some cases are decrypted in a secure CPU and isn't even accessible to
> the app.  There are platforms that support what is called "direct
> render" where the app gives the platform the encrypted packets and a
> discrete hardware unit will decrypt the packet, decode it, and render
> it directly; this happens on some smart TVs.  There are also cases
> which require decrypt-decode where we give the platform an encrypted
> packet and it will decrypt and decode the packet, ensuring the
> decrypted packet data is never in main memory.  So there are cases
> w

Re: [FFmpeg-devel] [PATCH] avformat/matroskadec: Parse encryption init info from streams.

2018-09-06 Thread Jacob Trimble
On Tue, Aug 28, 2018 at 12:56 PM Jacob Trimble  wrote:
>
> On Mon, Aug 20, 2018 at 11:39 AM Jacob Trimble  wrote:
> >
> > On Thu, Aug 9, 2018 at 9:14 AM Jacob Trimble  wrote:
> > >
> > > On Wed, Aug 1, 2018 at 1:46 PM Jacob Trimble  wrote:
> > > >
> > > > On Mon, Jul 23, 2018 at 2:01 PM Jacob Trimble  
> > > > wrote:
> > > > >
> > > > > On Thu, Jul 12, 2018 at 5:05 PM Jacob Trimble  
> > > > > wrote:
> > > > > >
> > > > > > Signed-off-by: Jacob Trimble 
> > > > > > ---
> > > > > >  libavformat/matroskadec.c | 43 
> > > > > > +--
> > > > > >  1 file changed, 32 insertions(+), 11 deletions(-)
> > > > > >
> > > > > > diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
> > > > > > index 1ded431b80..bfef329e59 100644
> > > > > > --- a/libavformat/matroskadec.c
> > > > > > +++ b/libavformat/matroskadec.c
> > > > > > @@ -2080,7 +2080,8 @@ static int 
> > > > > > matroska_parse_tracks(AVFormatContext *s)
> > > > > >  int extradata_offset = 0;
> > > > > >  uint32_t fourcc = 0;
> > > > > >  AVIOContext b;
> > > > > > -char* key_id_base64 = NULL;
> > > > > > +char* key_id = NULL;
> > > > > > +int key_id_size = 0;
> > > > > >  int bit_depth = -1;
> > > > > >
> > > > > >  /* Apply some sanity checks. */
> > > > > > @@ -2133,14 +2134,8 @@ static int 
> > > > > > matroska_parse_tracks(AVFormatContext *s)
> > > > > >  if (encodings[0].encryption.key_id.size > 0) {
> > > > > >  /* Save the encryption key id to be stored 
> > > > > > later as a
> > > > > > metadata tag. */
> > > > > > -const int b64_size = 
> > > > > > AV_BASE64_SIZE(encodings[0].encryption.key_id.size);
> > > > > > -key_id_base64 = av_malloc(b64_size);
> > > > > > -if (key_id_base64 == NULL)
> > > > > > -return AVERROR(ENOMEM);
> > > > > > -
> > > > > > -av_base64_encode(key_id_base64, b64_size,
> > > > > > - 
> > > > > > encodings[0].encryption.key_id.data,
> > > > > > - 
> > > > > > encodings[0].encryption.key_id.size);
> > > > > > +key_id = encodings[0].encryption.key_id.data;
> > > > > > +key_id_size = 
> > > > > > encodings[0].encryption.key_id.size;
> > > > > >  } else {
> > > > > >  encodings[0].scope = 0;
> > > > > >  av_log(matroska->ctx, AV_LOG_ERROR,
> > > > > > @@ -2198,14 +2193,40 @@ static int 
> > > > > > matroska_parse_tracks(AVFormatContext *s)
> > > > > >
> > > > > >  st = track->stream = avformat_new_stream(s, NULL);
> > > > > >  if (!st) {
> > > > > > -av_free(key_id_base64);
> > > > > >  return AVERROR(ENOMEM);
> > > > > >  }
> > > > > >
> > > > > > -if (key_id_base64) {
> > > > > > +if (key_id) {
> > > > > > +AVEncryptionInitInfo *init_info;
> > > > > > +uint8_t *side_data;
> > > > > > +size_t side_data_size;
> > > > > > +const int b64_size = AV_BASE64_SIZE(key_id_size);
> > > > > > +char *key_id_base64 = av_malloc(b64_size);
> > > > > > +if (!key_id_base64)
> > > > > > +return AVERROR(ENOMEM);
> > > > > > +av_base64_encode(key_id_base64, b64_size, key_id, 
> > > > > > key_id_size);
> > > > > > +
> > > > > >  /* export encrypt

Re: [FFmpeg-devel] [PATCH] avformat/utils: Don't parse encrypted packets.

2018-08-30 Thread Jacob Trimble
On Wed, Aug 29, 2018 at 4:37 PM Michael Niedermayer
 wrote:
>
> On Wed, Aug 29, 2018 at 03:30:39PM -0700, Jacob Trimble wrote:
> > On Wed, Aug 29, 2018 at 3:20 PM James Almer  wrote:
> > >
> > > On 8/29/2018 7:07 PM, Michael Niedermayer wrote:
> > > > On Tue, Aug 28, 2018 at 10:58:43AM -0700, Jacob Trimble wrote:
> > > >> If a packet is full-sample encrypted, then packet data can't be parsed
> > > >> without decrypting it.  So this skips the packet parsing for those
> > > >> packets.  If the packet has sub-sample encryption, it is assumed that
> > > >> the headers are in the clear and the parser will only need that info.
> > > >>
> > > >> Signed-off-by: Jacob Trimble 
> > > >> ---
> > > >>  libavformat/utils.c | 21 -
> > > >>  1 file changed, 20 insertions(+), 1 deletion(-)
> > > >
> > > > Hmm, please correct me if iam wrong but IIUC
> > > > 1. The demuxer has set need_parsing, indicating that it _requires_ a 
> > > > parser
> >
> > There isn't a flag for "try parsing and ignore errors".  So my choice
> > (from an app) is to either require parsing or don't do parsing at all
> > (which can result in incorrect timestamps).
> >
> > > > 2. Parsing cannot be done before decrypting
> > > >
> > > > If all this and the set values are correct, logically, the fix would be
> > > > to decrypt the packet before the parser not to skip the parser.
> >
>
> > There are cases where the packet can't be decrypted before getting to
> > this point.
>
> Can you elaborate on these cases ? I dont think its obvious what these
> cases are, at least its not obvious to me what exactly you are thinking
> of here. And i think its not helpfull if i guess what you mean and then
> argue/comment on that because maybe you meant something entirely different ...

Fair warning, I am working on a DRM solution.  I know many of you may
not agree with DRM, but it is a requirement imposed by content
creators.  FFmpeg doesn't have to support DRM itself, but you should
still consider its usages.

At that point in the code, the packet can only be decrypted by the
demuxer.  For example, in MP4 this can be done by passing the
-decryption_key parameter.  But that requires that FFmpeg handle the
decryption.  In my case, we are passing the packet to a CDM (content
decryption module) to handle the decryption and that might be a
hardware-secure decryptor.  In most DRM situations, we can't get the
raw key at all, all we can do is say "decrypt this block of memory".
So the only way to have the packet decrypted before this point would
be to introduce a callback to the app to decrypt the packet.

This is why I have been working on exposing the encryption info.  My
app (or more correctly the CDM) needs to handle the decryption and we
can't just give the key to libavformat so the demuxer can decrypt the
packet.

>
>
> > This point is between the demuxer creating the packet and
> > giving to the app.  So the only way to decrypt the frame (as of now)
> > is for the demuxer to do this.  There is no way for the app to handle
> > the decryption before this point.
> >
>
> > From the app's perspective, I would expect the packet to remain
> > encrypted for as long as possible.
>
> why ?

Because the point of encryption is to ensure that nefarious parties
don't get access to the data.  Even though the packet data is stored
in memory, it could still be retrieved by a malicious user.  Usually
for protected media, the frames are only decrypted when needed and in
some cases are decrypted in a secure CPU and isn't even accessible to
the app.  There are platforms that support what is called "direct
render" where the app gives the platform the encrypted packets and a
discrete hardware unit will decrypt the packet, decode it, and render
it directly; this happens on some smart TVs.  There are also cases
which require decrypt-decode where we give the platform an encrypted
packet and it will decrypt and decode the packet, ensuring the
decrypted packet data is never in main memory.  So there are cases
where we can't even see the encoded packet and decoding is handled by
the platform.

>
>
> > My app will store the packet for a
> > while, then decrypt it right before passing it to the decoder and
> > drawing the frame.  So requiring the packet to be decrypted at this
> > point is not ideal.
> >
> > >
> > > And if that can't be done, then the demuxer could perhaps set
> > > st->need_parsing to 0 and skip parsing altogether?
> >
> > I would want to still have pars

Re: [FFmpeg-devel] [PATCH] avformat/utils: Don't parse encrypted packets.

2018-08-29 Thread Jacob Trimble
On Wed, Aug 29, 2018 at 3:20 PM James Almer  wrote:
>
> On 8/29/2018 7:07 PM, Michael Niedermayer wrote:
> > On Tue, Aug 28, 2018 at 10:58:43AM -0700, Jacob Trimble wrote:
> >> If a packet is full-sample encrypted, then packet data can't be parsed
> >> without decrypting it.  So this skips the packet parsing for those
> >> packets.  If the packet has sub-sample encryption, it is assumed that
> >> the headers are in the clear and the parser will only need that info.
> >>
> >> Signed-off-by: Jacob Trimble 
> >> ---
> >>  libavformat/utils.c | 21 -
> >>  1 file changed, 20 insertions(+), 1 deletion(-)
> >
> > Hmm, please correct me if iam wrong but IIUC
> > 1. The demuxer has set need_parsing, indicating that it _requires_ a parser

There isn't a flag for "try parsing and ignore errors".  So my choice
(from an app) is to either require parsing or don't do parsing at all
(which can result in incorrect timestamps).

> > 2. Parsing cannot be done before decrypting
> >
> > If all this and the set values are correct, logically, the fix would be
> > to decrypt the packet before the parser not to skip the parser.

There are cases where the packet can't be decrypted before getting to
this point.  This point is between the demuxer creating the packet and
giving to the app.  So the only way to decrypt the frame (as of now)
is for the demuxer to do this.  There is no way for the app to handle
the decryption before this point.

From the app's perspective, I would expect the packet to remain
encrypted for as long as possible.  My app will store the packet for a
while, then decrypt it right before passing it to the decoder and
drawing the frame.  So requiring the packet to be decrypted at this
point is not ideal.

>
> And if that can't be done, then the demuxer could perhaps set
> st->need_parsing to 0 and skip parsing altogether?

I would want to still have parsing if possible. For example, a lot of
content has a clear lead where the first few seconds are clear.  So
they could be used to adjust the starting timestamps (and whatever
parsing needs) and the encrypted content later can be deduced based on
that.

>
> >
> > Am i missing something ?
> >
> > thx
> >
> > [...]
> >
> >
> >
> > ___
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >
>
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/matroskadec: Parse encryption init info from streams.

2018-08-28 Thread Jacob Trimble
On Mon, Aug 20, 2018 at 11:39 AM Jacob Trimble  wrote:
>
> On Thu, Aug 9, 2018 at 9:14 AM Jacob Trimble  wrote:
> >
> > On Wed, Aug 1, 2018 at 1:46 PM Jacob Trimble  wrote:
> > >
> > > On Mon, Jul 23, 2018 at 2:01 PM Jacob Trimble  wrote:
> > > >
> > > > On Thu, Jul 12, 2018 at 5:05 PM Jacob Trimble  
> > > > wrote:
> > > > >
> > > > > Signed-off-by: Jacob Trimble 
> > > > > ---
> > > > >  libavformat/matroskadec.c | 43 
> > > > > +--
> > > > >  1 file changed, 32 insertions(+), 11 deletions(-)
> > > > >
> > > > > diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
> > > > > index 1ded431b80..bfef329e59 100644
> > > > > --- a/libavformat/matroskadec.c
> > > > > +++ b/libavformat/matroskadec.c
> > > > > @@ -2080,7 +2080,8 @@ static int 
> > > > > matroska_parse_tracks(AVFormatContext *s)
> > > > >  int extradata_offset = 0;
> > > > >  uint32_t fourcc = 0;
> > > > >  AVIOContext b;
> > > > > -char* key_id_base64 = NULL;
> > > > > +char* key_id = NULL;
> > > > > +int key_id_size = 0;
> > > > >  int bit_depth = -1;
> > > > >
> > > > >  /* Apply some sanity checks. */
> > > > > @@ -2133,14 +2134,8 @@ static int 
> > > > > matroska_parse_tracks(AVFormatContext *s)
> > > > >  if (encodings[0].encryption.key_id.size > 0) {
> > > > >  /* Save the encryption key id to be stored later 
> > > > > as a
> > > > > metadata tag. */
> > > > > -const int b64_size = 
> > > > > AV_BASE64_SIZE(encodings[0].encryption.key_id.size);
> > > > > -key_id_base64 = av_malloc(b64_size);
> > > > > -if (key_id_base64 == NULL)
> > > > > -return AVERROR(ENOMEM);
> > > > > -
> > > > > -av_base64_encode(key_id_base64, b64_size,
> > > > > - 
> > > > > encodings[0].encryption.key_id.data,
> > > > > - 
> > > > > encodings[0].encryption.key_id.size);
> > > > > +key_id = encodings[0].encryption.key_id.data;
> > > > > +key_id_size = 
> > > > > encodings[0].encryption.key_id.size;
> > > > >  } else {
> > > > >  encodings[0].scope = 0;
> > > > >  av_log(matroska->ctx, AV_LOG_ERROR,
> > > > > @@ -2198,14 +2193,40 @@ static int 
> > > > > matroska_parse_tracks(AVFormatContext *s)
> > > > >
> > > > >  st = track->stream = avformat_new_stream(s, NULL);
> > > > >  if (!st) {
> > > > > -av_free(key_id_base64);
> > > > >  return AVERROR(ENOMEM);
> > > > >  }
> > > > >
> > > > > -if (key_id_base64) {
> > > > > +if (key_id) {
> > > > > +AVEncryptionInitInfo *init_info;
> > > > > +uint8_t *side_data;
> > > > > +size_t side_data_size;
> > > > > +const int b64_size = AV_BASE64_SIZE(key_id_size);
> > > > > +char *key_id_base64 = av_malloc(b64_size);
> > > > > +if (!key_id_base64)
> > > > > +return AVERROR(ENOMEM);
> > > > > +av_base64_encode(key_id_base64, b64_size, key_id, 
> > > > > key_id_size);
> > > > > +
> > > > >  /* export encryption key id as base64 metadata tag */
> > > > >  av_dict_set(>metadata, "enc_key_id", key_id_base64, 
> > > > > 0);
> > > > >  av_freep(_id_base64);
> > > > > +
> > > > > +
> > > > > +/* Convert the key ID to a generic encryption init info 
> > > > > */
> > > > > +init_info = av_encryption_init_info_alloc(/* 
> > > > > system_id_size */ 0, /* num_key

[FFmpeg-devel] [PATCH] avformat/utils: Don't parse encrypted packets.

2018-08-28 Thread Jacob Trimble
If a packet is full-sample encrypted, then packet data can't be parsed
without decrypting it.  So this skips the packet parsing for those
packets.  If the packet has sub-sample encryption, it is assumed that
the headers are in the clear and the parser will only need that info.

Signed-off-by: Jacob Trimble 
---
 libavformat/utils.c | 21 -
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/libavformat/utils.c b/libavformat/utils.c
index b0b5e164a6..1107787eae 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -27,6 +27,7 @@
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
 #include "libavutil/dict.h"
+#include "libavutil/encryption_info.h"
 #include "libavutil/internal.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
@@ -1576,6 +1577,9 @@ static int read_frame_internal(AVFormatContext *s, 
AVPacket *pkt)
 while (!got_packet && !s->internal->parse_queue) {
 AVStream *st;
 AVPacket cur_pkt;
+uint8_t *enc_side_data;
+int enc_side_data_size;
+int is_full_encrypted = 0;
 
 /* read next packet */
 ret = ff_read_packet(s, _pkt);
@@ -1659,7 +1663,22 @@ FF_ENABLE_DEPRECATION_WARNINGS
 st->parser->flags |= PARSER_FLAG_USE_CODEC_TS;
 }
 
-if (!st->need_parsing || !st->parser) {
+/* if the packet is full-sample encrypted, we can't parse it.  If the
+ * packet uses sub-sample encryption, assume the headers are clear and
+ * can still be parsed.
+ */
+enc_side_data = av_packet_get_side_data(
+_pkt, AV_PKT_DATA_ENCRYPTION_INFO, _side_data_size);
+if (enc_side_data) {
+AVEncryptionInfo *enc_info =
+av_encryption_info_get_side_data(enc_side_data, 
enc_side_data_size);
+if (enc_info) {
+is_full_encrypted = enc_info->subsample_count == 0;
+av_encryption_info_free(enc_info);
+}
+}
+
+if (!st->need_parsing || !st->parser || is_full_encrypted) {
 /* no parsing needed: we just output the packet as is */
 *pkt = cur_pkt;
 compute_pkt_fields(s, st, NULL, pkt, AV_NOPTS_VALUE, 
AV_NOPTS_VALUE);
-- 
2.19.0.rc0.228.g281dcd1b4d0-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avcodec/opus_parser: Handle complete frames flag.

2018-08-20 Thread Jacob Trimble
I am not entirely sure what this flag is supposed to be, since there
is no documentation where it is defined.  But this was suggested by
James Almer as a fix for my encrypted Opus problems and several other
codec parsers do the same thing.
From 87dfe4d3d21a824c0fbe71dad2ebc8672b3fd2b4 Mon Sep 17 00:00:00 2001
From: Jacob Trimble 
Date: Mon, 20 Aug 2018 11:25:27 -0700
Subject: [PATCH] avcodec/opus_parser: Handle complete frames flag.

Signed-off-by: Jacob Trimble 
---
 libavcodec/opus_parser.c | 29 +
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/libavcodec/opus_parser.c b/libavcodec/opus_parser.c
index 28b0933900..a145fe7793 100644
--- a/libavcodec/opus_parser.c
+++ b/libavcodec/opus_parser.c
@@ -170,19 +170,24 @@ static int opus_parse(AVCodecParserContext *ctx, AVCodecContext *avctx,
 ParseContext *pc= >pc;
 int next, header_len;
 
-next = opus_find_frame_end(ctx, avctx, buf, buf_size, _len);
-
-if (s->ts_framing && next != AVERROR_INVALIDDATA &&
-ff_combine_frame(pc, next, , _size) < 0) {
-*poutbuf  = NULL;
-*poutbuf_size = 0;
-return buf_size;
-}
+if (ctx->flags & PARSER_FLAG_COMPLETE_FRAMES) {
+next = buf_size;
+header_len = 0;
+} else {
+next = opus_find_frame_end(ctx, avctx, buf, buf_size, _len);
+
+if (s->ts_framing && next != AVERROR_INVALIDDATA &&
+ff_combine_frame(pc, next, , _size) < 0) {
+*poutbuf  = NULL;
+*poutbuf_size = 0;
+return buf_size;
+}
 
-if (next == AVERROR_INVALIDDATA){
-*poutbuf  = NULL;
-*poutbuf_size = 0;
-return buf_size;
+if (next == AVERROR_INVALIDDATA){
+*poutbuf  = NULL;
+*poutbuf_size = 0;
+return buf_size;
+}
 }
 
 *poutbuf  = buf + header_len;
-- 
2.18.0.865.gffc8e1a3cd6-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/avformat.h: Add av_stream_remove_side_data.

2018-08-20 Thread Jacob Trimble
On Mon, Jul 9, 2018 at 9:57 AM Jacob Trimble  wrote:
>
> On Tue, Jul 3, 2018 at 5:59 PM Michael Niedermayer
>  wrote:
> >
> > On Tue, Jul 03, 2018 at 12:14:19PM -0700, Jacob Trimble wrote:
> > > On Mon, Jul 2, 2018 at 6:07 PM Michael Niedermayer
> > >  wrote:
> > > >
> > > > On Mon, Jun 25, 2018 at 04:03:32PM -0700, Jacob Trimble wrote:
> > > > > Signed-off-by: Jacob Trimble 
> > > > > ---
> > > > >  libavformat/avformat.h |  8 
> > > > >  libavformat/utils.c| 11 +++
> > > > >  2 files changed, 19 insertions(+)
> > > >
> > > >
> > > >
> > > >
> > > >
> > > > >
> > > > > diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> > > > > index fdaffa5bf4..434c88837e 100644
> > > > > --- a/libavformat/avformat.h
> > > > > +++ b/libavformat/avformat.h
> > > > > @@ -2167,6 +2167,14 @@ AVStream *avformat_new_stream(AVFormatContext 
> > > > > *s, const AVCodec *c);
> > > > >  int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType 
> > > > > type,
> > > > >  uint8_t *data, size_t size);
> > > > >
> > > > > +/**
> > > > > + * Removes any existing side data of the given type.
> > > > > + *
> > > > > + * @param st stream
> > > > > + * @param type side information type
> > > > > + */
> > > > > +void av_stream_remove_side_data(AVStream *st, enum 
> > > > > AVPacketSideDataType type);
> > > >
> > > > What would use this and why ?
> > > > The commit message does not explain this
> > > >
> > > > If side data is changing it probably should be put in AVPackets or 
> > > > AVFrames
> > > > not the stream.
> > > >
> > >
> > > I am using this to removing the side data that contains the
> > > AVEncryptionInitInfo objects once I handle them.  Since an MP4 file
> > > can contain multiple pssh atoms, there can be multiple
> > > AVEncryptionInitInfo structs.  To make it easier for me, I want to
> > > remove the side data that contain them once I have handled them.  This
> > > means that if the AVStream contains the side data, it is because of
> > > new init info I haven't seen.  Since the pssh atoms are more "global"
> > > it makes more sense to put them in the AVStream.
> >
> > I dont fully understand but
> > If you intend to remove things while reading the "header" of a mp4 file
> > these things probably should not be in side data to begin with but be
> > internal to the demuxer.
> >
> > otherwise, after the header or outside the demuxer removal seems a "no go"
> > but i may misunderstand what you intend to do. Please explain if iam
> > totally off here with how i interpret this
> >
> > One simple API good vs. bad test btw should be to consider that theres
> > a demuxer connected to a muxer.
> > If this does not work to produce a equivalent file the API is not good
> > for example if you change side data in the AVStream in the middle between
> > outputing packets i would not expect the muxer to see this and thus not
> > be able to reproduce this in the stored file.
> >
> > Also if you mess with the demxuers side data from outside, not only
> > will this result in undefined behavior it also might be that you still
> > need it when for example seeking back to the start
> >
> > again maybe i totally misunderstand what you intend here
> >
>
> I would expect the muxer to do what I am doing, it would remove the
> side data when it handles the data so it doesn't have to keep a copy
> of all the init data it has seen.
>
> For example, consider converting fragmented MP4 into a different
> fragmented MP4.  The pssh atoms can appear inside the fragments, so
> the muxer should see the new pssh atoms and add them to the
> current/next fragment while muxing.  The best way I see is to check if
> the side data exists, handle it, and remove the side data.  The
> alternative would be to convert the side data to the
> AVEncryptionInitInfo struct at every step, then compare each element
> against a copy the muxer has.  This is extremely slow and requires
> storing the init data several different ways.
>
> Another alternative would be to put the side data on the frames, but
> this doesn't seem right either.  The init info is "header" data, so it
> seems weird to put it on a random frame, and putting the data on every
> frame would be more duplication and require the muxer/app to compare
> them for every frame to detect new init info.
>

Does that make sense?  Is this something that could be merged?

> >
> > [...]
> > --
> > Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
> >
> > The worst form of inequality is to try to make unequal things equal.
> > -- Aristotle
> > ___
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/matroskadec: Parse encryption init info from streams.

2018-08-20 Thread Jacob Trimble
On Thu, Aug 9, 2018 at 9:14 AM Jacob Trimble  wrote:
>
> On Wed, Aug 1, 2018 at 1:46 PM Jacob Trimble  wrote:
> >
> > On Mon, Jul 23, 2018 at 2:01 PM Jacob Trimble  wrote:
> > >
> > > On Thu, Jul 12, 2018 at 5:05 PM Jacob Trimble  wrote:
> > > >
> > > > Signed-off-by: Jacob Trimble 
> > > > ---
> > > >  libavformat/matroskadec.c | 43 +--
> > > >  1 file changed, 32 insertions(+), 11 deletions(-)
> > > >
> > > > diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
> > > > index 1ded431b80..bfef329e59 100644
> > > > --- a/libavformat/matroskadec.c
> > > > +++ b/libavformat/matroskadec.c
> > > > @@ -2080,7 +2080,8 @@ static int matroska_parse_tracks(AVFormatContext 
> > > > *s)
> > > >  int extradata_offset = 0;
> > > >  uint32_t fourcc = 0;
> > > >  AVIOContext b;
> > > > -char* key_id_base64 = NULL;
> > > > +char* key_id = NULL;
> > > > +int key_id_size = 0;
> > > >  int bit_depth = -1;
> > > >
> > > >  /* Apply some sanity checks. */
> > > > @@ -2133,14 +2134,8 @@ static int matroska_parse_tracks(AVFormatContext 
> > > > *s)
> > > >  if (encodings[0].encryption.key_id.size > 0) {
> > > >  /* Save the encryption key id to be stored later 
> > > > as a
> > > > metadata tag. */
> > > > -const int b64_size = 
> > > > AV_BASE64_SIZE(encodings[0].encryption.key_id.size);
> > > > -key_id_base64 = av_malloc(b64_size);
> > > > -if (key_id_base64 == NULL)
> > > > -return AVERROR(ENOMEM);
> > > > -
> > > > -av_base64_encode(key_id_base64, b64_size,
> > > > - 
> > > > encodings[0].encryption.key_id.data,
> > > > - 
> > > > encodings[0].encryption.key_id.size);
> > > > +key_id = encodings[0].encryption.key_id.data;
> > > > +key_id_size = encodings[0].encryption.key_id.size;
> > > >  } else {
> > > >  encodings[0].scope = 0;
> > > >  av_log(matroska->ctx, AV_LOG_ERROR,
> > > > @@ -2198,14 +2193,40 @@ static int 
> > > > matroska_parse_tracks(AVFormatContext *s)
> > > >
> > > >  st = track->stream = avformat_new_stream(s, NULL);
> > > >  if (!st) {
> > > > -av_free(key_id_base64);
> > > >  return AVERROR(ENOMEM);
> > > >  }
> > > >
> > > > -if (key_id_base64) {
> > > > +if (key_id) {
> > > > +AVEncryptionInitInfo *init_info;
> > > > +uint8_t *side_data;
> > > > +size_t side_data_size;
> > > > +const int b64_size = AV_BASE64_SIZE(key_id_size);
> > > > +char *key_id_base64 = av_malloc(b64_size);
> > > > +if (!key_id_base64)
> > > > +return AVERROR(ENOMEM);
> > > > +av_base64_encode(key_id_base64, b64_size, key_id, 
> > > > key_id_size);
> > > > +
> > > >  /* export encryption key id as base64 metadata tag */
> > > >  av_dict_set(>metadata, "enc_key_id", key_id_base64, 0);
> > > >  av_freep(_id_base64);
> > > > +
> > > > +
> > > > +/* Convert the key ID to a generic encryption init info */
> > > > +init_info = av_encryption_init_info_alloc(/* 
> > > > system_id_size */ 0, /* num_key_ids */ 1,
> > > > +  /* key_id_size 
> > > > */ key_id_size, /* data_size */ 0);
> > > > +if (!init_info)
> > > > +return AVERROR(ENOMEM);
> > > > +memcpy(init_info->key_ids[0], key_id, key_id_size);
> > > > +side_data = 
> > > > av_encryption_init_info_add_side_data(init_info, _data_size);
> > > > +av_encryption_init_info_free(init_info);
> > > > +if (!side_data)
> > > > +return AVERROR(ENOMEM);
> > > > +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);
> > > > +return ret;
> > > > +}
> > > >  }
> > > >
> > > >  if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC") &&
> > > > --
> > > > 2.18.0.203.gfac676dfb9-goog
> > > >
> > >
> > > Ping.
> >
> > Ping.
>
> Ping (only 43 lines changed, in "review" for 28 days...)

Ping.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/matroska: Parse generic encryption info from packets.

2018-08-20 Thread Jacob Trimble
On Mon, Aug 13, 2018 at 9:01 PM James Almer  wrote:
>
> On 8/14/2018 12:50 AM, James Almer wrote:
> > On 7/12/2018 8:45 PM, Jacob Trimble wrote:
> >> I am currently seeing a problem with this when using Opus audio.  In
> >> read_frame_internal, it will try to parse the resulting packet.  For
> >> video, which uses subsample encryption, it is able to parse the
> >> headers; but for Opus, which uses full-sample encryption, it fails to
> >> parse the headers.  This causes the read_frame_internal to drop the
> >> packet.
> >>
> >> I have traced a workaround to opus_parse in opus_parser.c: instead of
> >> setting poutbuf to NULL, set it to the buffer and just pass the packet
> >> to the app to handle it.  The frame will be decrypted before passing
> >> to the decoder.  I can't just disable parsing in the demuxer because I
> >> want to parse the packets for clear content and when using subsample
> >> encryption.
> >>
> >> Does anyone have any other ideas to work around this?  Is there a way
> >> to allow parsing but ignore errors?
> > Try the attached diff to see if it fixes the issue (It makes the parser
> > not bother trying to assemble packets from what could be incomplete data
> > if the source is a demuxer that guarantees the propagation of complete
> > packets).
> >

Yep that fixed it, thanks.  I sent out a patch to implement that
(since other parsers do it, it seems like the correct thing to do).

In that case, this patch works well and is ready to review/merge.

> >
> > opus.diff
> >
> >
> > diff --git a/libavcodec/opus_parser.c b/libavcodec/opus_parser.c
> > index 28b0933900..e8d157356c 100644
> > --- a/libavcodec/opus_parser.c
> > +++ b/libavcodec/opus_parser.c
> > @@ -170,6 +170,9 @@ static int opus_parse(AVCodecParserContext *ctx, 
> > AVCodecContext *avctx,
> >  ParseContext *pc= >pc;
> >  int next, header_len;
>
> Err, with the change below this should be initialized to 0 now. Sorry.
>
> >
> > +if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
> > +next = buf_size;
> > +} else {
> >  next = opus_find_frame_end(ctx, avctx, buf, buf_size, _len);
> >
> >  if (s->ts_framing && next != AVERROR_INVALIDDATA &&
> > @@ -184,6 +187,7 @@ static int opus_parse(AVCodecParserContext *ctx, 
> > AVCodecContext *avctx,
> >  *poutbuf_size = 0;
> >  return buf_size;
> >  }
> > +}
> >
> >  *poutbuf  = buf + header_len;
> >  *poutbuf_size = buf_size - header_len;
> >
>
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/mov: Allow saio/saiz in clear content.

2018-08-20 Thread Jacob Trimble
On Wed, Aug 15, 2018 at 2:38 PM Michael Niedermayer
 wrote:
>
> [...]
>
> >  mov.c |6 ++
> >  1 file changed, 6 insertions(+)
> > 0e583b4ad11852ce38a2b945644e178b7f13a42f  
> > 0001-avformat-mov-Allow-saio-saiz-in-clear-content-v2.patch
> > From 256880aca517f64257eb28342a656867d90307a7 Mon Sep 17 00:00:00 2001
> > From: Jacob Trimble 
> > Date: Tue, 14 Aug 2018 10:18:55 -0700
> > Subject: [PATCH] avformat/mov: Allow saio/saiz in clear content.
>
> This code is used in saio/saiz/senc. The message only mentions the first
> 2.
>

senc shouldn't appear in clear content, so it shouldn't change
anything.  Changed the commit message to include that.

>
> [...]
>
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> Whats the most studid thing your enemy could do ? Blow himself up
> Whats the most studid thing you could do ? Give up your rights and
> freedom because your enemy blew himself up.
>
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
From 18e6aba25364b988ac52413949f62eef03d6c648 Mon Sep 17 00:00:00 2001
From: Jacob Trimble 
Date: Tue, 14 Aug 2018 10:18:55 -0700
Subject: [PATCH] avformat/mov: Allow saio/saiz in clear content.

If there is a saio/saiz in clear content, we shouldn't create the
encryption index if we don't already have one.  Otherwise it will
confuse the cenc_filter.

The changed method is also used for senc atoms, but they should not
appear in clear content.

Found by Chromium's ClusterFuzz: https://crbug.com/873432

Signed-off-by: Jacob Trimble 
---
 libavformat/mov.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index c863047d79..ee9acdb73c 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -5847,6 +5847,9 @@ static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encry
 *sc = st->priv_data;
 
 if (!frag_stream_info->encryption_index) {
+// If this stream isn't encrypted, don't create the index.
+if (!(*sc)->cenc.default_encrypted_sample)
+return 0;
 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
 if (!frag_stream_info->encryption_index)
 return AVERROR(ENOMEM);
@@ -5862,6 +5865,9 @@ static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encry
 *sc = st->priv_data;
 
 if (!(*sc)->cenc.encryption_index) {
+// If this stream isn't encrypted, don't create the index.
+if (!(*sc)->cenc.default_encrypted_sample)
+return 0;
 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
 if (!(*sc)->cenc.encryption_index)
 return AVERROR(ENOMEM);
-- 
2.18.0.865.gffc8e1a3cd6-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/mov: Allow saio/saiz in clear content.

2018-08-14 Thread Jacob Trimble
On Tue, Aug 14, 2018 at 10:39 AM Jacob Trimble  wrote:
>
> If there is a saio/saiz in clear content, we shouldn't create the
> encryption index if we don't already have one.  Otherwise it will
> confuse the cenc_filter.
>
> Found by Chromium's ClusterFuzz: https://crbug.com/873432
>
> Signed-off-by: Jacob Trimble 
> ---
>  libavformat/mov.c | 28 ++--
>  1 file changed, 18 insertions(+), 10 deletions(-)
>
> diff --git a/libavformat/mov.c b/libavformat/mov.c
> index c863047d79..50bc1cab4b 100644
> --- a/libavformat/mov.c
> +++ b/libavformat/mov.c
> @@ -5828,7 +5828,7 @@ static int mov_read_frma(MOVContext *c, AVIOContext 
> *pb, MOVAtom atom)
>   * info for this fragment; otherwise this will return the global encryption
>   * info for the current stream.
>   */
> -static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex 
> **encryption_index, MOVStreamContext **sc)
> +static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex 
> **encryption_index, MOVStreamContext **sc, int create)
>  {
>  MOVFragmentStreamInfo *frag_stream_info;
>  AVStream *st;
> @@ -5847,9 +5847,13 @@ static int get_current_encryption_info(MOVContext *c, 
> MOVEncryptionIndex **encry
>  *sc = st->priv_data;
>
>  if (!frag_stream_info->encryption_index) {
> -frag_stream_info->encryption_index = 
> av_mallocz(sizeof(*frag_stream_info->encryption_index));
> -if (!frag_stream_info->encryption_index)
> -return AVERROR(ENOMEM);
> +if (create) {
> +frag_stream_info->encryption_index = 
> av_mallocz(sizeof(*frag_stream_info->encryption_index));
> +if (!frag_stream_info->encryption_index)
> +return AVERROR(ENOMEM);
> +} else {
> +return 0;
> +}
>  }
>  *encryption_index = frag_stream_info->encryption_index;
>  return 1;
> @@ -5862,9 +5866,13 @@ static int get_current_encryption_info(MOVContext *c, 
> MOVEncryptionIndex **encry
>  *sc = st->priv_data;
>
>  if (!(*sc)->cenc.encryption_index) {
> -(*sc)->cenc.encryption_index = 
> av_mallocz(sizeof(*frag_stream_info->encryption_index));
> -if (!(*sc)->cenc.encryption_index)
> -return AVERROR(ENOMEM);
> +if (create) {
> +(*sc)->cenc.encryption_index = 
> av_mallocz(sizeof(*frag_stream_info->encryption_index));
> +if (!(*sc)->cenc.encryption_index)
> +return AVERROR(ENOMEM);
> +} else {
> +return 0;
> +}
>  }
>
>  *encryption_index = (*sc)->cenc.encryption_index;
> @@ -5931,7 +5939,7 @@ static int mov_read_senc(MOVContext *c, AVIOContext 
> *pb, MOVAtom atom)
>  int use_subsamples, ret;
>  unsigned int sample_count, i, alloc_size = 0;
>
> -ret = get_current_encryption_info(c, _index, );
> +ret = get_current_encryption_info(c, _index, , /* create 
> */ 1);
>  if (ret != 1)
>  return ret;
>
> @@ -6078,7 +6086,7 @@ static int mov_read_saiz(MOVContext *c, AVIOContext 
> *pb, MOVAtom atom)
>  int ret;
>  unsigned int sample_count, aux_info_type, aux_info_param;
>
> -ret = get_current_encryption_info(c, _index, );
> +ret = get_current_encryption_info(c, _index, , /* create 
> */ 0);
>  if (ret != 1)
>  return ret;
>
> @@ -6152,7 +6160,7 @@ static int mov_read_saio(MOVContext *c, AVIOContext 
> *pb, MOVAtom atom)
>  unsigned int version, entry_count, aux_info_type, aux_info_param;
>  unsigned int alloc_size = 0;
>
> -ret = get_current_encryption_info(c, _index, );
> +ret = get_current_encryption_info(c, _index, , /* create 
> */ 0);
>  if (ret != 1)
>  return ret;
>
> --
> 2.18.0.865.gffc8e1a3cd6-goog
>

After thinking of this more, this was the incorrect fix.  Attached is
the correct fix.
From 256880aca517f64257eb28342a656867d90307a7 Mon Sep 17 00:00:00 2001
From: Jacob Trimble 
Date: Tue, 14 Aug 2018 10:18:55 -0700
Subject: [PATCH] avformat/mov: Allow saio/saiz in clear content.

If there is a saio/saiz in clear content, we shouldn't create the
encryption index if we don't already have one.  Otherwise it will
confuse the cenc_filter.

Found by Chromium's ClusterFuzz: https://crbug.com/873432

Signed-off-by: Jacob Trimble 
---
 libavformat/mov.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index c863047d79..ee9acdb73c 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -5847,6 +5847,9 @@ s

[FFmpeg-devel] [PATCH] avformat/mov: Allow saio/saiz in clear content.

2018-08-14 Thread Jacob Trimble
If there is a saio/saiz in clear content, we shouldn't create the
encryption index if we don't already have one.  Otherwise it will
confuse the cenc_filter.

Found by Chromium's ClusterFuzz: https://crbug.com/873432

Signed-off-by: Jacob Trimble 
---
 libavformat/mov.c | 28 ++--
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index c863047d79..50bc1cab4b 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -5828,7 +5828,7 @@ static int mov_read_frma(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
  * info for this fragment; otherwise this will return the global encryption
  * info for the current stream.
  */
-static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex 
**encryption_index, MOVStreamContext **sc)
+static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex 
**encryption_index, MOVStreamContext **sc, int create)
 {
 MOVFragmentStreamInfo *frag_stream_info;
 AVStream *st;
@@ -5847,9 +5847,13 @@ static int get_current_encryption_info(MOVContext *c, 
MOVEncryptionIndex **encry
 *sc = st->priv_data;
 
 if (!frag_stream_info->encryption_index) {
-frag_stream_info->encryption_index = 
av_mallocz(sizeof(*frag_stream_info->encryption_index));
-if (!frag_stream_info->encryption_index)
-return AVERROR(ENOMEM);
+if (create) {
+frag_stream_info->encryption_index = 
av_mallocz(sizeof(*frag_stream_info->encryption_index));
+if (!frag_stream_info->encryption_index)
+return AVERROR(ENOMEM);
+} else {
+return 0;
+}
 }
 *encryption_index = frag_stream_info->encryption_index;
 return 1;
@@ -5862,9 +5866,13 @@ static int get_current_encryption_info(MOVContext *c, 
MOVEncryptionIndex **encry
 *sc = st->priv_data;
 
 if (!(*sc)->cenc.encryption_index) {
-(*sc)->cenc.encryption_index = 
av_mallocz(sizeof(*frag_stream_info->encryption_index));
-if (!(*sc)->cenc.encryption_index)
-return AVERROR(ENOMEM);
+if (create) {
+(*sc)->cenc.encryption_index = 
av_mallocz(sizeof(*frag_stream_info->encryption_index));
+if (!(*sc)->cenc.encryption_index)
+return AVERROR(ENOMEM);
+} else {
+return 0;
+}
 }
 
 *encryption_index = (*sc)->cenc.encryption_index;
@@ -5931,7 +5939,7 @@ static int mov_read_senc(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
 int use_subsamples, ret;
 unsigned int sample_count, i, alloc_size = 0;
 
-ret = get_current_encryption_info(c, _index, );
+ret = get_current_encryption_info(c, _index, , /* create */ 
1);
 if (ret != 1)
 return ret;
 
@@ -6078,7 +6086,7 @@ static int mov_read_saiz(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
 int ret;
 unsigned int sample_count, aux_info_type, aux_info_param;
 
-ret = get_current_encryption_info(c, _index, );
+ret = get_current_encryption_info(c, _index, , /* create */ 
0);
 if (ret != 1)
 return ret;
 
@@ -6152,7 +6160,7 @@ static int mov_read_saio(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
 unsigned int version, entry_count, aux_info_type, aux_info_param;
 unsigned int alloc_size = 0;
 
-ret = get_current_encryption_info(c, _index, );
+ret = get_current_encryption_info(c, _index, , /* create */ 
0);
 if (ret != 1)
 return ret;
 
-- 
2.18.0.865.gffc8e1a3cd6-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avutil/encryption_info: Fix size calculation.

2018-08-13 Thread Jacob Trimble
On Mon, Aug 13, 2018 at 3:31 PM Carl Eugen Hoyos  wrote:
>
> 2018-08-14 0:22 GMT+02:00, Jacob Trimble :
> > Fixes: 873693
>
> This does not look helpful.

Changed.

>
> Carl Eugen
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
From a822b6a1f0bba9f36314d9c8af1b9eca7c0bc406 Mon Sep 17 00:00:00 2001
From: Jacob Trimble 
Date: Mon, 13 Aug 2018 15:17:11 -0700
Subject: [PATCH] avutil/encryption_info: Fix size calculation.

Found by Chrome's ClusterFuzz: https://crbug.com/873693

Signed-off-by: Jacob Trimble 
---
 libavutil/encryption_info.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
index 3b7e16cd0c..812c704776 100644
--- a/libavutil/encryption_info.c
+++ b/libavutil/encryption_info.c
@@ -297,14 +297,14 @@ uint8_t *av_encryption_init_info_add_side_data(const AVEncryptionInitInfo *info,
 temp_side_data_size = 4;
 init_info_count = 0;
 for (cur_info = info; cur_info; cur_info = cur_info->next) {
-temp_side_data_size += (uint64_t)FF_ENCRYPTION_INIT_INFO_EXTRA + info->system_id_size + info->data_size;
+temp_side_data_size += (uint64_t)FF_ENCRYPTION_INIT_INFO_EXTRA + cur_info->system_id_size + cur_info->data_size;
 if (init_info_count == UINT32_MAX || temp_side_data_size > UINT32_MAX) {
 return NULL;
 }
 init_info_count++;
 
-if (info->num_key_ids) {
-temp_side_data_size += (uint64_t)info->num_key_ids * info->key_id_size;
+if (cur_info->num_key_ids) {
+temp_side_data_size += (uint64_t)cur_info->num_key_ids * cur_info->key_id_size;
 if (temp_side_data_size > UINT32_MAX) {
 return NULL;
 }
-- 
2.18.0.597.ga71716f1ad-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avutil/encryption_info: Fix size calculation.

2018-08-13 Thread Jacob Trimble
Fixes: 873693
Signed-off-by: Jacob Trimble 
---
 libavutil/encryption_info.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
index c3916b42c8..b399e07e66 100644
--- a/libavutil/encryption_info.c
+++ b/libavutil/encryption_info.c
@@ -300,14 +300,14 @@ uint8_t *av_encryption_init_info_add_side_data(const 
AVEncryptionInitInfo *info,
 temp_side_data_size = 4;
 init_info_count = 0;
 for (cur_info = info; cur_info; cur_info = cur_info->next) {
-temp_side_data_size += (uint64_t)FF_ENCRYPTION_INIT_INFO_EXTRA + 
info->system_id_size + info->data_size;
+temp_side_data_size += (uint64_t)FF_ENCRYPTION_INIT_INFO_EXTRA + 
cur_info->system_id_size + cur_info->data_size;
 if (init_info_count == UINT32_MAX || temp_side_data_size > UINT32_MAX) 
{
 return NULL;
 }
 init_info_count++;
 
-if (info->num_key_ids) {
-temp_side_data_size += (uint64_t)info->num_key_ids * 
info->key_id_size;
+if (cur_info->num_key_ids) {
+temp_side_data_size += (uint64_t)cur_info->num_key_ids * 
cur_info->key_id_size;
 if (temp_side_data_size > UINT32_MAX) {
 return NULL;
 }
-- 
2.18.0.597.ga71716f1ad-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/matroskadec: Parse encryption init info from streams.

2018-08-09 Thread Jacob Trimble
On Wed, Aug 1, 2018 at 1:46 PM Jacob Trimble  wrote:
>
> On Mon, Jul 23, 2018 at 2:01 PM Jacob Trimble  wrote:
> >
> > On Thu, Jul 12, 2018 at 5:05 PM Jacob Trimble  wrote:
> > >
> > > Signed-off-by: Jacob Trimble 
> > > ---
> > >  libavformat/matroskadec.c | 43 +--
> > >  1 file changed, 32 insertions(+), 11 deletions(-)
> > >
> > > diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
> > > index 1ded431b80..bfef329e59 100644
> > > --- a/libavformat/matroskadec.c
> > > +++ b/libavformat/matroskadec.c
> > > @@ -2080,7 +2080,8 @@ static int matroska_parse_tracks(AVFormatContext *s)
> > >  int extradata_offset = 0;
> > >  uint32_t fourcc = 0;
> > >  AVIOContext b;
> > > -char* key_id_base64 = NULL;
> > > +char* key_id = NULL;
> > > +int key_id_size = 0;
> > >  int bit_depth = -1;
> > >
> > >  /* Apply some sanity checks. */
> > > @@ -2133,14 +2134,8 @@ static int matroska_parse_tracks(AVFormatContext 
> > > *s)
> > >  if (encodings[0].encryption.key_id.size > 0) {
> > >  /* Save the encryption key id to be stored later as a
> > > metadata tag. */
> > > -const int b64_size = 
> > > AV_BASE64_SIZE(encodings[0].encryption.key_id.size);
> > > -key_id_base64 = av_malloc(b64_size);
> > > -if (key_id_base64 == NULL)
> > > -return AVERROR(ENOMEM);
> > > -
> > > -av_base64_encode(key_id_base64, b64_size,
> > > - encodings[0].encryption.key_id.data,
> > > - 
> > > encodings[0].encryption.key_id.size);
> > > +key_id = encodings[0].encryption.key_id.data;
> > > +key_id_size = encodings[0].encryption.key_id.size;
> > >  } else {
> > >  encodings[0].scope = 0;
> > >  av_log(matroska->ctx, AV_LOG_ERROR,
> > > @@ -2198,14 +2193,40 @@ static int matroska_parse_tracks(AVFormatContext 
> > > *s)
> > >
> > >  st = track->stream = avformat_new_stream(s, NULL);
> > >  if (!st) {
> > > -av_free(key_id_base64);
> > >  return AVERROR(ENOMEM);
> > >  }
> > >
> > > -if (key_id_base64) {
> > > +if (key_id) {
> > > +AVEncryptionInitInfo *init_info;
> > > +uint8_t *side_data;
> > > +size_t side_data_size;
> > > +const int b64_size = AV_BASE64_SIZE(key_id_size);
> > > +char *key_id_base64 = av_malloc(b64_size);
> > > +if (!key_id_base64)
> > > +return AVERROR(ENOMEM);
> > > +av_base64_encode(key_id_base64, b64_size, key_id, 
> > > key_id_size);
> > > +
> > >  /* export encryption key id as base64 metadata tag */
> > >  av_dict_set(>metadata, "enc_key_id", key_id_base64, 0);
> > >  av_freep(_id_base64);
> > > +
> > > +
> > > +/* Convert the key ID to a generic encryption init info */
> > > +init_info = av_encryption_init_info_alloc(/* system_id_size 
> > > */ 0, /* num_key_ids */ 1,
> > > +  /* key_id_size */ 
> > > key_id_size, /* data_size */ 0);
> > > +if (!init_info)
> > > +return AVERROR(ENOMEM);
> > > +memcpy(init_info->key_ids[0], key_id, key_id_size);
> > > +side_data = av_encryption_init_info_add_side_data(init_info, 
> > > _data_size);
> > > +av_encryption_init_info_free(init_info);
> > > +if (!side_data)
> > > +return AVERROR(ENOMEM);
> > > +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);
> > > +return ret;
> > > +}
> > >  }
> > >
> > >  if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC") &&
> > > --
> > > 2.18.0.203.gfac676dfb9-goog
> > >
> >
> > Ping.
>
> Ping.

Ping (only 43 lines changed, in "review" for 28 days...)
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/matroska: Parse generic encryption info from packets.

2018-08-09 Thread Jacob Trimble
On Wed, Aug 1, 2018 at 1:45 PM Jacob Trimble  wrote:
>
> On Mon, Jul 23, 2018 at 1:59 PM Jacob Trimble  wrote:
> >
> > On Thu, Jul 12, 2018 at 4:45 PM Jacob Trimble  wrote:
> > >
> > > The attached patch adds parsing for WebM encryption info into the
> > > AVEncryptionInfo side-data.  The AVEncryptionInitInfo will be handled
> > > in another patch.
> > >
> > > Spec: https://www.webmproject.org/docs/webm-encryption/
> > >
> > > I am currently seeing a problem with this when using Opus audio.  In
> > > read_frame_internal, it will try to parse the resulting packet.  For
> > > video, which uses subsample encryption, it is able to parse the
> > > headers; but for Opus, which uses full-sample encryption, it fails to
> > > parse the headers.  This causes the read_frame_internal to drop the
> > > packet.
> > >
> > > I have traced a workaround to opus_parse in opus_parser.c: instead of
> > > setting poutbuf to NULL, set it to the buffer and just pass the packet
> > > to the app to handle it.  The frame will be decrypted before passing
> > > to the decoder.  I can't just disable parsing in the demuxer because I
> > > want to parse the packets for clear content and when using subsample
> > > encryption.
> > >
> > > Does anyone have any other ideas to work around this?  Is there a way
> > > to allow parsing but ignore errors?
> >
> > Ping.
>
> Ping.

Ping (136 lindes changed, in "review" for 28 days...)
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/matroskadec: Parse encryption init info from streams.

2018-08-01 Thread Jacob Trimble
On Mon, Jul 23, 2018 at 2:01 PM Jacob Trimble  wrote:
>
> On Thu, Jul 12, 2018 at 5:05 PM Jacob Trimble  wrote:
> >
> > Signed-off-by: Jacob Trimble 
> > ---
> >  libavformat/matroskadec.c | 43 +--
> >  1 file changed, 32 insertions(+), 11 deletions(-)
> >
> > diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
> > index 1ded431b80..bfef329e59 100644
> > --- a/libavformat/matroskadec.c
> > +++ b/libavformat/matroskadec.c
> > @@ -2080,7 +2080,8 @@ static int matroska_parse_tracks(AVFormatContext *s)
> >  int extradata_offset = 0;
> >  uint32_t fourcc = 0;
> >  AVIOContext b;
> > -char* key_id_base64 = NULL;
> > +char* key_id = NULL;
> > +int key_id_size = 0;
> >  int bit_depth = -1;
> >
> >  /* Apply some sanity checks. */
> > @@ -2133,14 +2134,8 @@ static int matroska_parse_tracks(AVFormatContext *s)
> >  if (encodings[0].encryption.key_id.size > 0) {
> >  /* Save the encryption key id to be stored later as a
> > metadata tag. */
> > -const int b64_size = 
> > AV_BASE64_SIZE(encodings[0].encryption.key_id.size);
> > -key_id_base64 = av_malloc(b64_size);
> > -if (key_id_base64 == NULL)
> > -return AVERROR(ENOMEM);
> > -
> > -av_base64_encode(key_id_base64, b64_size,
> > - encodings[0].encryption.key_id.data,
> > - encodings[0].encryption.key_id.size);
> > +key_id = encodings[0].encryption.key_id.data;
> > +key_id_size = encodings[0].encryption.key_id.size;
> >  } else {
> >  encodings[0].scope = 0;
> >  av_log(matroska->ctx, AV_LOG_ERROR,
> > @@ -2198,14 +2193,40 @@ static int matroska_parse_tracks(AVFormatContext *s)
> >
> >  st = track->stream = avformat_new_stream(s, NULL);
> >  if (!st) {
> > -av_free(key_id_base64);
> >  return AVERROR(ENOMEM);
> >  }
> >
> > -if (key_id_base64) {
> > +if (key_id) {
> > +AVEncryptionInitInfo *init_info;
> > +uint8_t *side_data;
> > +size_t side_data_size;
> > +const int b64_size = AV_BASE64_SIZE(key_id_size);
> > +char *key_id_base64 = av_malloc(b64_size);
> > +if (!key_id_base64)
> > +return AVERROR(ENOMEM);
> > +av_base64_encode(key_id_base64, b64_size, key_id, key_id_size);
> > +
> >  /* export encryption key id as base64 metadata tag */
> >  av_dict_set(>metadata, "enc_key_id", key_id_base64, 0);
> >  av_freep(_id_base64);
> > +
> > +
> > +/* Convert the key ID to a generic encryption init info */
> > +init_info = av_encryption_init_info_alloc(/* system_id_size */ 
> > 0, /* num_key_ids */ 1,
> > +  /* key_id_size */ 
> > key_id_size, /* data_size */ 0);
> > +if (!init_info)
> > +return AVERROR(ENOMEM);
> > +memcpy(init_info->key_ids[0], key_id, key_id_size);
> > +side_data = av_encryption_init_info_add_side_data(init_info, 
> > _data_size);
> > +av_encryption_init_info_free(init_info);
> > +if (!side_data)
> > +return AVERROR(ENOMEM);
> > +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);
> > +return ret;
> > +}
> >  }
> >
> >  if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC") &&
> > --
> > 2.18.0.203.gfac676dfb9-goog
> >
>
> Ping.

Ping.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/matroska: Parse generic encryption info from packets.

2018-08-01 Thread Jacob Trimble
On Mon, Jul 23, 2018 at 1:59 PM Jacob Trimble  wrote:
>
> On Thu, Jul 12, 2018 at 4:45 PM Jacob Trimble  wrote:
> >
> > The attached patch adds parsing for WebM encryption info into the
> > AVEncryptionInfo side-data.  The AVEncryptionInitInfo will be handled
> > in another patch.
> >
> > Spec: https://www.webmproject.org/docs/webm-encryption/
> >
> > I am currently seeing a problem with this when using Opus audio.  In
> > read_frame_internal, it will try to parse the resulting packet.  For
> > video, which uses subsample encryption, it is able to parse the
> > headers; but for Opus, which uses full-sample encryption, it fails to
> > parse the headers.  This causes the read_frame_internal to drop the
> > packet.
> >
> > I have traced a workaround to opus_parse in opus_parser.c: instead of
> > setting poutbuf to NULL, set it to the buffer and just pass the packet
> > to the app to handle it.  The frame will be decrypted before passing
> > to the decoder.  I can't just disable parsing in the demuxer because I
> > want to parse the packets for clear content and when using subsample
> > encryption.
> >
> > Does anyone have any other ideas to work around this?  Is there a way
> > to allow parsing but ignore errors?
>
> Ping.

Ping.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/matroskadec: Parse encryption init info from streams.

2018-07-23 Thread Jacob Trimble
On Thu, Jul 12, 2018 at 5:05 PM Jacob Trimble  wrote:
>
> Signed-off-by: Jacob Trimble 
> ---
>  libavformat/matroskadec.c | 43 +--
>  1 file changed, 32 insertions(+), 11 deletions(-)
>
> diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
> index 1ded431b80..bfef329e59 100644
> --- a/libavformat/matroskadec.c
> +++ b/libavformat/matroskadec.c
> @@ -2080,7 +2080,8 @@ static int matroska_parse_tracks(AVFormatContext *s)
>  int extradata_offset = 0;
>  uint32_t fourcc = 0;
>  AVIOContext b;
> -char* key_id_base64 = NULL;
> +char* key_id = NULL;
> +int key_id_size = 0;
>  int bit_depth = -1;
>
>  /* Apply some sanity checks. */
> @@ -2133,14 +2134,8 @@ static int matroska_parse_tracks(AVFormatContext *s)
>  if (encodings[0].encryption.key_id.size > 0) {
>  /* Save the encryption key id to be stored later as a
> metadata tag. */
> -const int b64_size = 
> AV_BASE64_SIZE(encodings[0].encryption.key_id.size);
> -key_id_base64 = av_malloc(b64_size);
> -if (key_id_base64 == NULL)
> -return AVERROR(ENOMEM);
> -
> -av_base64_encode(key_id_base64, b64_size,
> - encodings[0].encryption.key_id.data,
> - encodings[0].encryption.key_id.size);
> +key_id = encodings[0].encryption.key_id.data;
> +key_id_size = encodings[0].encryption.key_id.size;
>  } else {
>  encodings[0].scope = 0;
>  av_log(matroska->ctx, AV_LOG_ERROR,
> @@ -2198,14 +2193,40 @@ static int matroska_parse_tracks(AVFormatContext *s)
>
>  st = track->stream = avformat_new_stream(s, NULL);
>  if (!st) {
> -av_free(key_id_base64);
>  return AVERROR(ENOMEM);
>  }
>
> -if (key_id_base64) {
> +if (key_id) {
> +AVEncryptionInitInfo *init_info;
> +uint8_t *side_data;
> +size_t side_data_size;
> +const int b64_size = AV_BASE64_SIZE(key_id_size);
> +char *key_id_base64 = av_malloc(b64_size);
> +if (!key_id_base64)
> +return AVERROR(ENOMEM);
> +av_base64_encode(key_id_base64, b64_size, key_id, key_id_size);
> +
>  /* export encryption key id as base64 metadata tag */
>  av_dict_set(>metadata, "enc_key_id", key_id_base64, 0);
>  av_freep(_id_base64);
> +
> +
> +/* Convert the key ID to a generic encryption init info */
> +init_info = av_encryption_init_info_alloc(/* system_id_size */ 
> 0, /* num_key_ids */ 1,
> +  /* key_id_size */ 
> key_id_size, /* data_size */ 0);
> +if (!init_info)
> +return AVERROR(ENOMEM);
> +memcpy(init_info->key_ids[0], key_id, key_id_size);
> +side_data = av_encryption_init_info_add_side_data(init_info, 
> _data_size);
> +av_encryption_init_info_free(init_info);
> +if (!side_data)
> +return AVERROR(ENOMEM);
> +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);
> +return ret;
> +}
>  }
>
>  if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC") &&
> --
> 2.18.0.203.gfac676dfb9-goog
>

Ping.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/matroska: Parse generic encryption info from packets.

2018-07-23 Thread Jacob Trimble
On Thu, Jul 12, 2018 at 4:45 PM Jacob Trimble  wrote:
>
> The attached patch adds parsing for WebM encryption info into the
> AVEncryptionInfo side-data.  The AVEncryptionInitInfo will be handled
> in another patch.
>
> Spec: https://www.webmproject.org/docs/webm-encryption/
>
> I am currently seeing a problem with this when using Opus audio.  In
> read_frame_internal, it will try to parse the resulting packet.  For
> video, which uses subsample encryption, it is able to parse the
> headers; but for Opus, which uses full-sample encryption, it fails to
> parse the headers.  This causes the read_frame_internal to drop the
> packet.
>
> I have traced a workaround to opus_parse in opus_parser.c: instead of
> setting poutbuf to NULL, set it to the buffer and just pass the packet
> to the app to handle it.  The frame will be decrypted before passing
> to the decoder.  I can't just disable parsing in the demuxer because I
> want to parse the packets for clear content and when using subsample
> encryption.
>
> Does anyone have any other ideas to work around this?  Is there a way
> to allow parsing but ignore errors?

Ping.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/matroskadec: Parse encryption init info from streams.

2018-07-12 Thread Jacob Trimble
Signed-off-by: Jacob Trimble 
---
 libavformat/matroskadec.c | 43 +--
 1 file changed, 32 insertions(+), 11 deletions(-)

diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 1ded431b80..bfef329e59 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -2080,7 +2080,8 @@ static int matroska_parse_tracks(AVFormatContext *s)
 int extradata_offset = 0;
 uint32_t fourcc = 0;
 AVIOContext b;
-char* key_id_base64 = NULL;
+char* key_id = NULL;
+int key_id_size = 0;
 int bit_depth = -1;
 
 /* Apply some sanity checks. */
@@ -2133,14 +2134,8 @@ static int matroska_parse_tracks(AVFormatContext *s)
 if (encodings[0].encryption.key_id.size > 0) {
 /* Save the encryption key id to be stored later as a
metadata tag. */
-const int b64_size = 
AV_BASE64_SIZE(encodings[0].encryption.key_id.size);
-key_id_base64 = av_malloc(b64_size);
-if (key_id_base64 == NULL)
-return AVERROR(ENOMEM);
-
-av_base64_encode(key_id_base64, b64_size,
- encodings[0].encryption.key_id.data,
- encodings[0].encryption.key_id.size);
+key_id = encodings[0].encryption.key_id.data;
+key_id_size = encodings[0].encryption.key_id.size;
 } else {
 encodings[0].scope = 0;
 av_log(matroska->ctx, AV_LOG_ERROR,
@@ -2198,14 +2193,40 @@ static int matroska_parse_tracks(AVFormatContext *s)
 
 st = track->stream = avformat_new_stream(s, NULL);
 if (!st) {
-av_free(key_id_base64);
 return AVERROR(ENOMEM);
 }
 
-if (key_id_base64) {
+if (key_id) {
+AVEncryptionInitInfo *init_info;
+uint8_t *side_data;
+size_t side_data_size;
+const int b64_size = AV_BASE64_SIZE(key_id_size);
+char *key_id_base64 = av_malloc(b64_size);
+if (!key_id_base64)
+return AVERROR(ENOMEM);
+av_base64_encode(key_id_base64, b64_size, key_id, key_id_size);
+
 /* export encryption key id as base64 metadata tag */
 av_dict_set(>metadata, "enc_key_id", key_id_base64, 0);
 av_freep(_id_base64);
+
+
+/* Convert the key ID to a generic encryption init info */
+init_info = av_encryption_init_info_alloc(/* system_id_size */ 0, 
/* num_key_ids */ 1,
+  /* key_id_size */ 
key_id_size, /* data_size */ 0);
+if (!init_info)
+return AVERROR(ENOMEM);
+memcpy(init_info->key_ids[0], key_id, key_id_size);
+side_data = av_encryption_init_info_add_side_data(init_info, 
_data_size);
+av_encryption_init_info_free(init_info);
+if (!side_data)
+return AVERROR(ENOMEM);
+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);
+return ret;
+}
 }
 
 if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC") &&
-- 
2.18.0.203.gfac676dfb9-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/matroska: Parse generic encryption info from packets.

2018-07-12 Thread Jacob Trimble
The attached patch adds parsing for WebM encryption info into the
AVEncryptionInfo side-data.  The AVEncryptionInitInfo will be handled
in another patch.

Spec: https://www.webmproject.org/docs/webm-encryption/

I am currently seeing a problem with this when using Opus audio.  In
read_frame_internal, it will try to parse the resulting packet.  For
video, which uses subsample encryption, it is able to parse the
headers; but for Opus, which uses full-sample encryption, it fails to
parse the headers.  This causes the read_frame_internal to drop the
packet.

I have traced a workaround to opus_parse in opus_parser.c: instead of
setting poutbuf to NULL, set it to the buffer and just pass the packet
to the app to handle it.  The frame will be decrypted before passing
to the decoder.  I can't just disable parsing in the demuxer because I
want to parse the packets for clear content and when using subsample
encryption.

Does anyone have any other ideas to work around this?  Is there a way
to allow parsing but ignore errors?
From 48cabb86f030bfcf1d163db2c361ab8ce743d8b3 Mon Sep 17 00:00:00 2001
From: Jacob Trimble 
Date: Wed, 11 Jul 2018 11:08:18 -0700
Subject: [PATCH] avformat/matroska: Parse generic encryption info from
 packets.

This parses the WebM generic encryption info out of the packets and
adds it to the AV_PKT_DATA_ENCRYPTION_INFO side data.  This also
changes the data/size fields in the resulting packets so they point
to the actual frame data instead of the encryption header.

Since this is a breaking change with changing the packet pointer,
this parsing is only done if a demuxer option is set.

Signed-off-by: Jacob Trimble 
---
 libavformat/matroskadec.c | 136 +-
 1 file changed, 133 insertions(+), 3 deletions(-)

diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 1ded431b80..e66e660ad4 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -367,6 +367,9 @@ typedef struct MatroskaDemuxContext {
 
 /* Bandwidth value for WebM DASH Manifest */
 int bandwidth;
+
+/* Parsing encryption info flag */
+int parse_encryption;
 } MatroskaDemuxContext;
 
 typedef struct MatroskaBlock {
@@ -3179,6 +3182,111 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska,
 return 0;
 }
 
+static int matroska_parse_webm_encryption_info(MatroskaDemuxContext *matroska, MatroskaTrackEncryption *encryption,
+   AVPacket *pkt) {
+uint8_t signal_byte;
+uint8_t *side_data;
+size_t side_data_size;
+int has_subsamples, partition_count, subsample_count, header_size, res = 0;
+AVEncryptionInfo *info;
+
+if (encryption->algo != 5) {
+av_log(matroska->ctx, AV_LOG_ERROR,
+   "Only AES encryption is supported.\n");
+return AVERROR_PATCHWELCOME;
+}
+if (encryption->key_id.size == 0) {
+av_log(matroska->ctx, AV_LOG_ERROR, "No key ID given.\n");
+return AVERROR_INVALIDDATA;
+}
+
+if (pkt->size == 0) {
+av_log(matroska->ctx, AV_LOG_ERROR,
+   "Not enough packet data for encryption header.\n");
+return AVERROR_INVALIDDATA;
+}
+
+signal_byte = pkt->data[0];
+has_subsamples = signal_byte & 0x2;
+if (signal_byte & 0xfc) {
+av_log(matroska->ctx, AV_LOG_ERROR, "Reserved bit set.\n");
+return AVERROR_PATCHWELCOME;
+}
+if (!(signal_byte & 0x1)) {
+// Frame in clear, skip signal byte.
+pkt->data++;
+pkt->size--;
+return 0;
+}
+
+if (has_subsamples) {
+partition_count = pkt->data[9];
+subsample_count = partition_count / 2 + 1;
+header_size = 10 + partition_count * 4;
+} else {
+partition_count = 0;
+subsample_count = 0;
+header_size = 9;
+}
+if (pkt->size < header_size) {
+av_log(matroska->ctx, AV_LOG_ERROR,
+   "Not enough packet data for encryption header.\n");
+return AVERROR_INVALIDDATA;
+}
+
+info = av_encryption_info_alloc(subsample_count, encryption->key_id.size,
+/* iv_size */ 16);
+if (!info)
+return AVERROR(ENOMEM);
+
+info->scheme = MKBETAG('c','e','n','c');
+// Copy the 8-byte IV into the high bytes of |info->iv|, the low bytes should already be set to 0.
+memcpy(info->iv, pkt->data + 1, 8);
+memcpy(info->key_id, encryption->key_id.data, encryption->key_id.size);
+
+if (has_subsamples) {
+uint32_t partition_offset = 0;
+for (int i = 0; i < partition_count + 1; i++) {
+const uint32_t next_partition_offset =
+i == partition_count ? pkt->size - header_size : AV_RB32(pkt->data + 10 + i * 4);
+if (next_partition_offset < partition_offse

Re: [FFmpeg-devel] [PATCH] avformat/avformat.h: Add av_stream_remove_side_data.

2018-07-09 Thread Jacob Trimble
On Tue, Jul 3, 2018 at 5:59 PM Michael Niedermayer
 wrote:
>
> On Tue, Jul 03, 2018 at 12:14:19PM -0700, Jacob Trimble wrote:
> > On Mon, Jul 2, 2018 at 6:07 PM Michael Niedermayer
> >  wrote:
> > >
> > > On Mon, Jun 25, 2018 at 04:03:32PM -0700, Jacob Trimble wrote:
> > > > Signed-off-by: Jacob Trimble 
> > > > ---
> > > >  libavformat/avformat.h |  8 
> > > >  libavformat/utils.c| 11 +++
> > > >  2 files changed, 19 insertions(+)
> > >
> > >
> > >
> > >
> > >
> > > >
> > > > diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> > > > index fdaffa5bf4..434c88837e 100644
> > > > --- a/libavformat/avformat.h
> > > > +++ b/libavformat/avformat.h
> > > > @@ -2167,6 +2167,14 @@ AVStream *avformat_new_stream(AVFormatContext 
> > > > *s, const AVCodec *c);
> > > >  int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType 
> > > > type,
> > > >  uint8_t *data, size_t size);
> > > >
> > > > +/**
> > > > + * Removes any existing side data of the given type.
> > > > + *
> > > > + * @param st stream
> > > > + * @param type side information type
> > > > + */
> > > > +void av_stream_remove_side_data(AVStream *st, enum 
> > > > AVPacketSideDataType type);
> > >
> > > What would use this and why ?
> > > The commit message does not explain this
> > >
> > > If side data is changing it probably should be put in AVPackets or 
> > > AVFrames
> > > not the stream.
> > >
> >
> > I am using this to removing the side data that contains the
> > AVEncryptionInitInfo objects once I handle them.  Since an MP4 file
> > can contain multiple pssh atoms, there can be multiple
> > AVEncryptionInitInfo structs.  To make it easier for me, I want to
> > remove the side data that contain them once I have handled them.  This
> > means that if the AVStream contains the side data, it is because of
> > new init info I haven't seen.  Since the pssh atoms are more "global"
> > it makes more sense to put them in the AVStream.
>
> I dont fully understand but
> If you intend to remove things while reading the "header" of a mp4 file
> these things probably should not be in side data to begin with but be
> internal to the demuxer.
>
> otherwise, after the header or outside the demuxer removal seems a "no go"
> but i may misunderstand what you intend to do. Please explain if iam
> totally off here with how i interpret this
>
> One simple API good vs. bad test btw should be to consider that theres
> a demuxer connected to a muxer.
> If this does not work to produce a equivalent file the API is not good
> for example if you change side data in the AVStream in the middle between
> outputing packets i would not expect the muxer to see this and thus not
> be able to reproduce this in the stored file.
>
> Also if you mess with the demxuers side data from outside, not only
> will this result in undefined behavior it also might be that you still
> need it when for example seeking back to the start
>
> again maybe i totally misunderstand what you intend here
>

I would expect the muxer to do what I am doing, it would remove the
side data when it handles the data so it doesn't have to keep a copy
of all the init data it has seen.

For example, consider converting fragmented MP4 into a different
fragmented MP4.  The pssh atoms can appear inside the fragments, so
the muxer should see the new pssh atoms and add them to the
current/next fragment while muxing.  The best way I see is to check if
the side data exists, handle it, and remove the side data.  The
alternative would be to convert the side data to the
AVEncryptionInitInfo struct at every step, then compare each element
against a copy the muxer has.  This is extremely slow and requires
storing the init data several different ways.

Another alternative would be to put the side data on the frames, but
this doesn't seem right either.  The init info is "header" data, so it
seems weird to put it on a random frame, and putting the data on every
frame would be more duplication and require the muxer/app to compare
them for every frame to detect new init info.

>
> [...]
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> The worst form of inequality is to try to make unequal things equal.
> -- Aristotle
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/avformat.h: Add av_stream_remove_side_data.

2018-07-03 Thread Jacob Trimble
On Mon, Jul 2, 2018 at 6:07 PM Michael Niedermayer
 wrote:
>
> On Mon, Jun 25, 2018 at 04:03:32PM -0700, Jacob Trimble wrote:
> > Signed-off-by: Jacob Trimble 
> > ---
> >  libavformat/avformat.h |  8 
> >  libavformat/utils.c| 11 +++
> >  2 files changed, 19 insertions(+)
>
>
>
>
>
> >
> > diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> > index fdaffa5bf4..434c88837e 100644
> > --- a/libavformat/avformat.h
> > +++ b/libavformat/avformat.h
> > @@ -2167,6 +2167,14 @@ AVStream *avformat_new_stream(AVFormatContext *s, 
> > const AVCodec *c);
> >  int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type,
> >  uint8_t *data, size_t size);
> >
> > +/**
> > + * Removes any existing side data of the given type.
> > + *
> > + * @param st stream
> > + * @param type side information type
> > + */
> > +void av_stream_remove_side_data(AVStream *st, enum AVPacketSideDataType 
> > type);
>
> What would use this and why ?
> The commit message does not explain this
>
> If side data is changing it probably should be put in AVPackets or AVFrames
> not the stream.
>

I am using this to removing the side data that contains the
AVEncryptionInitInfo objects once I handle them.  Since an MP4 file
can contain multiple pssh atoms, there can be multiple
AVEncryptionInitInfo structs.  To make it easier for me, I want to
remove the side data that contain them once I have handled them.  This
means that if the AVStream contains the side data, it is because of
new init info I haven't seen.  Since the pssh atoms are more "global"
it makes more sense to put them in the AVStream.

>
> [...]
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> You can kill me, but you cannot change the truth.
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/avformat.h: Add av_stream_remove_side_data.

2018-07-02 Thread Jacob Trimble
On Mon, Jun 25, 2018 at 4:04 PM Jacob Trimble  wrote:
>
> Signed-off-by: Jacob Trimble 
> ---
>  libavformat/avformat.h |  8 
>  libavformat/utils.c| 11 +++
>  2 files changed, 19 insertions(+)
>
> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> index fdaffa5bf4..434c88837e 100644
> --- a/libavformat/avformat.h
> +++ b/libavformat/avformat.h
> @@ -2167,6 +2167,14 @@ AVStream *avformat_new_stream(AVFormatContext *s, 
> const AVCodec *c);
>  int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type,
>  uint8_t *data, size_t size);
>
> +/**
> + * Removes any existing side data of the given type.
> + *
> + * @param st stream
> + * @param type side information type
> + */
> +void av_stream_remove_side_data(AVStream *st, enum AVPacketSideDataType 
> type);
> +
>  /**
>   * Allocate new information from stream.
>   *
> diff --git a/libavformat/utils.c b/libavformat/utils.c
> index c9cdd2b470..4f7c408d93 100644
> --- a/libavformat/utils.c
> +++ b/libavformat/utils.c
> @@ -5491,6 +5491,17 @@ int av_stream_add_side_data(AVStream *st, enum 
> AVPacketSideDataType type,
>  return 0;
>  }
>
> +void av_stream_remove_side_data(AVStream *st, enum AVPacketSideDataType type)
> +{
> +  for (int i = 0; i < st->nb_side_data; i++) {
> +  if (st->side_data[i].type == type) {
> +  av_freep(>side_data[i].data);
> +  st->side_data[i] = st->side_data[st->nb_side_data - 1];
> +  st->nb_side_data--;
> +  }
> +  }
> +}
> +
>  uint8_t *av_stream_new_side_data(AVStream *st, enum AVPacketSideDataType 
> type,
>   int size)
>  {
> --
> 2.18.0.rc2.346.g013aa6912e-goog
>

Ping.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


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

2018-07-02 Thread Jacob Trimble
On Mon, Jun 25, 2018 at 10:59 AM Jacob Trimble  wrote:
>
> Rebased and updated to handle multiple PSSH atoms.  PTAL.
>
> On Tue, Jan 9, 2018 at 10:28 AM Jacob Trimble  wrote:
>>
>> On Mon, Jan 8, 2018 at 5:23 PM, Carl Eugen Hoyos  wrote:
>> > 2018-01-09 0:22 GMT+01:00 Jacob Trimble 
>> > :
>> >
>> >> 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, _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.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] libavutil/encryption_info: Add unit tests.

2018-06-26 Thread Jacob Trimble
On Mon, Jun 25, 2018 at 5:30 PM Michael Niedermayer
 wrote:
>
> On Fri, Jun 01, 2018 at 12:51:48PM -0700, Jacob Trimble wrote:
> > Signed-off-by: Jacob Trimble 
> > ---
> >  libavutil/Makefile|   1 +
> >  libavutil/encryption_info.h   |   2 +-
> >  libavutil/tests/.gitignore|   2 +
> >  libavutil/tests/encryption_info.c | 176 ++
> >  tests/fate/libavutil.mak  |   4 +
> >  tests/ref/fate/encryption-info|   0
> >  6 files changed, 184 insertions(+), 1 deletion(-)
> >  create mode 100644 libavutil/tests/encryption_info.c
> >  create mode 100644 tests/ref/fate/encryption-info
> >
> > diff --git a/libavutil/Makefile b/libavutil/Makefile
> > index d0632f16a6..9ed24cfc82 100644
> > --- a/libavutil/Makefile
> > +++ b/libavutil/Makefile
> > @@ -200,6 +200,7 @@ TESTPROGS = adler32 
> > \
> >  des \
> >  dict\
> >  display \
> > +encryption_info \
> >  error   \
> >  eval\
> >  file\
>
> > diff --git a/libavutil/encryption_info.h b/libavutil/encryption_info.h
> > index 9140968fde..8fe7ebfe43 100644
> > --- a/libavutil/encryption_info.h
> > +++ b/libavutil/encryption_info.h
> > @@ -129,7 +129,7 @@ typedef struct AVEncryptionInitInfo {
> >   *
> >   * @param subsample_count The number of subsamples.
> >   * @param key_id_size The number of bytes in the key ID, should be 16.
> > - * @param key_id_size The number of bytes in the IV, should be 16.
> > + * @param iv_size The number of bytes in the IV, should be 16.
> >   *
> >   * @return The new AVEncryptionInfo structure, or NULL on error.
> >   */
>
> How is this related to adding a test ?
>

I guess it's unrelated, created a separate patch for it.

>
>
> > diff --git a/libavutil/tests/.gitignore b/libavutil/tests/.gitignore
> > index 71f75a8ee9..9d90827954 100644
> > --- a/libavutil/tests/.gitignore
> > +++ b/libavutil/tests/.gitignore
> > @@ -17,6 +17,7 @@
> >  /dict
> >  /display
> >  /error
> > +/encryption_info
> >  /eval
> >  /fifo
> >  /file
>
> > @@ -24,6 +25,7 @@
> >  /hmac
> >  /hwdevice
> >  /imgutils
> > +/integer
> >  /lfg
> >  /lls
> >  /log
>
> this also looks unrelated

Same.

>
>
> [...]
> --
> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> Opposition brings concord. Out of discord comes the fairest harmony.
> -- Heraclitus
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
From c97e44904020944e469faec18b9c279cb6d89b46 Mon Sep 17 00:00:00 2001
From: Jacob Trimble 
Date: Fri, 1 Jun 2018 11:38:05 -0700
Subject: [PATCH] libavutil/encryption_info: Add unit tests.

Signed-off-by: Jacob Trimble 
---
 libavutil/Makefile|   1 +
 libavutil/tests/.gitignore|   1 +
 libavutil/tests/encryption_info.c | 176 ++
 tests/fate/libavutil.mak  |   4 +
 tests/ref/fate/encryption-info|   0
 5 files changed, 182 insertions(+)
 create mode 100644 libavutil/tests/encryption_info.c
 create mode 100644 tests/ref/fate/encryption-info

diff --git a/libavutil/Makefile b/libavutil/Makefile
index d0632f16a6..9ed24cfc82 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -200,6 +200,7 @@ TESTPROGS = adler32 \
 des \
 dict\
 display \
+encryption_info \
 error   \
 eval\
 file\
diff --git a/libavutil/tests/.gitignore b/libavutil/tests/.gitignore
index 71f75a8ee9..d7de295617 100644
--- a/libavutil/tests/.gitignore
+++ b/libavutil/tests/.gitignore
@@ -17,6 +17,7 @@
 /dict
 /display
 /error
+/encryption_in

[FFmpeg-devel] [PATCH] avutil/gitignore: Ignore integer test binary.

2018-06-26 Thread Jacob Trimble
Signed-off-by: Jacob Trimble 
---
 libavutil/tests/.gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libavutil/tests/.gitignore b/libavutil/tests/.gitignore
index 71f75a8ee9..bf07c57b75 100644
--- a/libavutil/tests/.gitignore
+++ b/libavutil/tests/.gitignore
@@ -24,6 +24,7 @@
 /hmac
 /hwdevice
 /imgutils
+/integer
 /lfg
 /lls
 /log
-- 
2.18.0.rc2.346.g013aa6912e-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avutil/encryption_info: Fix documentation problem.

2018-06-26 Thread Jacob Trimble
Signed-off-by: Jacob Trimble 
---
 libavutil/encryption_info.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavutil/encryption_info.h b/libavutil/encryption_info.h
index 9140968fde..8fe7ebfe43 100644
--- a/libavutil/encryption_info.h
+++ b/libavutil/encryption_info.h
@@ -129,7 +129,7 @@ typedef struct AVEncryptionInitInfo {
  *
  * @param subsample_count The number of subsamples.
  * @param key_id_size The number of bytes in the key ID, should be 16.
- * @param key_id_size The number of bytes in the IV, should be 16.
+ * @param iv_size The number of bytes in the IV, should be 16.
  *
  * @return The new AVEncryptionInfo structure, or NULL on error.
  */
-- 
2.18.0.rc2.346.g013aa6912e-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/avformat.h: Add av_stream_remove_side_data.

2018-06-25 Thread Jacob Trimble
Signed-off-by: Jacob Trimble 
---
 libavformat/avformat.h |  8 
 libavformat/utils.c| 11 +++
 2 files changed, 19 insertions(+)

diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index fdaffa5bf4..434c88837e 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -2167,6 +2167,14 @@ AVStream *avformat_new_stream(AVFormatContext *s, const 
AVCodec *c);
 int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type,
 uint8_t *data, size_t size);
 
+/**
+ * Removes any existing side data of the given type.
+ *
+ * @param st stream
+ * @param type side information type
+ */
+void av_stream_remove_side_data(AVStream *st, enum AVPacketSideDataType type);
+
 /**
  * Allocate new information from stream.
  *
diff --git a/libavformat/utils.c b/libavformat/utils.c
index c9cdd2b470..4f7c408d93 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -5491,6 +5491,17 @@ int av_stream_add_side_data(AVStream *st, enum 
AVPacketSideDataType type,
 return 0;
 }
 
+void av_stream_remove_side_data(AVStream *st, enum AVPacketSideDataType type)
+{
+  for (int i = 0; i < st->nb_side_data; i++) {
+  if (st->side_data[i].type == type) {
+  av_freep(>side_data[i].data);
+  st->side_data[i] = st->side_data[st->nb_side_data - 1];
+  st->nb_side_data--;
+  }
+  }
+}
+
 uint8_t *av_stream_new_side_data(AVStream *st, enum AVPacketSideDataType type,
  int size)
 {
-- 
2.18.0.rc2.346.g013aa6912e-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] libavutil/encryption_info: Add unit tests.

2018-06-25 Thread Jacob Trimble
Now that the patches have been merged this doesn't depend on anything.

On Fri, Jun 1, 2018 at 12:54 PM Jacob Trimble  wrote:

> On Fri, Jun 1, 2018 at 12:52 PM Jacob Trimble  wrote:
> >
> > Signed-off-by: Jacob Trimble 
> > ---
> >  libavutil/Makefile|   1 +
> >  libavutil/encryption_info.h   |   2 +-
> >  libavutil/tests/.gitignore|   2 +
> >  libavutil/tests/encryption_info.c | 176 ++
> >  tests/fate/libavutil.mak  |   4 +
> >  tests/ref/fate/encryption-info|   0
> >  6 files changed, 184 insertions(+), 1 deletion(-)
> >  create mode 100644 libavutil/tests/encryption_info.c
> >  create mode 100644 tests/ref/fate/encryption-info
> >
> > diff --git a/libavutil/Makefile b/libavutil/Makefile
> > index d0632f16a6..9ed24cfc82 100644
> > --- a/libavutil/Makefile
> > +++ b/libavutil/Makefile
> > @@ -200,6 +200,7 @@ TESTPROGS = adler32
>\
> >  des
>  \
> >  dict
> \
> >  display
>  \
> > +encryption_info
>  \
> >  error
>  \
> >  eval
> \
> >  file
> \
> > diff --git a/libavutil/encryption_info.h b/libavutil/encryption_info.h
> > index 9140968fde..8fe7ebfe43 100644
> > --- a/libavutil/encryption_info.h
> > +++ b/libavutil/encryption_info.h
> > @@ -129,7 +129,7 @@ typedef struct AVEncryptionInitInfo {
> >   *
> >   * @param subsample_count The number of subsamples.
> >   * @param key_id_size The number of bytes in the key ID, should be 16.
> > - * @param key_id_size The number of bytes in the IV, should be 16.
> > + * @param iv_size The number of bytes in the IV, should be 16.
> >   *
> >   * @return The new AVEncryptionInfo structure, or NULL on error.
> >   */
> > diff --git a/libavutil/tests/.gitignore b/libavutil/tests/.gitignore
> > index 71f75a8ee9..9d90827954 100644
> > --- a/libavutil/tests/.gitignore
> > +++ b/libavutil/tests/.gitignore
> > @@ -17,6 +17,7 @@
> >  /dict
> >  /display
> >  /error
> > +/encryption_info
> >  /eval
> >  /fifo
> >  /file
> > @@ -24,6 +25,7 @@
> >  /hmac
> >  /hwdevice
> >  /imgutils
> > +/integer
> >  /lfg
> >  /lls
> >  /log
> > diff --git a/libavutil/tests/encryption_info.c
> b/libavutil/tests/encryption_info.c
> > new file mode 100644
> > index 00..d489612b7d
> > --- /dev/null
> > +++ b/libavutil/tests/encryption_info.c
> > @@ -0,0 +1,176 @@
> > +/*
> > + * 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
> > + */
> > +
> > +#include "libavutil/encryption_info.h"
> > +
> > +#include 
> > +#include 
> > +
> > +#include "libavutil/avassert.h"
> > +
> > +static const AVSubsampleEncryptionInfo test_subsamples[] = {{1, 2}, {3,
> 4}, {5, 6}, {7, 8}};
> > +static const size_t test_subsample_count = sizeof(test_subsamples) /
> sizeof(test_subsamples[0]);
> > +static const uint8_t test_iv[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
> 0x17, 0x18};
> > +static const uint8_t test_key_id[] = {0x21, 0x22, 0x23, 0x24};
> > +static const uint8_t test_key_id_2[] = {0x31, 0x32, 0x33, 0x34};
> > +static const uint8_t test_system_id[] = {0x41, 0x42, 0x43};
> > +static const uint8_t test_data[] = {0x51, 0x52};
> > +
> > +static int compare_encryption_info(const AVEncryptionInfo *a, const
> AVEncryptionInfo *b) {
> > +if (!a || !b || a->scheme != b->scheme || a->crypt_byte_block !=
> b->crypt_byte_block ||
> > +a->skip_byte_block != b->skip_byte_block || a->key_id_size !=
> b->key_id_size ||
> > +a->iv_size != b->iv_size || a->subsample_cou

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

2018-06-25 Thread Jacob Trimble
Rebased and updated to handle multiple PSSH atoms.  PTAL.

On Tue, Jan 9, 2018 at 10:28 AM Jacob Trimble  wrote:

> On Mon, Jan 8, 2018 at 5:23 PM, Carl Eugen Hoyos 
> wrote:
> > 2018-01-09 0:22 GMT+01:00 Jacob Trimble <
> modmaker-at-google@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, _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
>
From 2c2c6386432678ea485a84f90a02991f481324e1 Mon Sep 17 00:00:00 2001
From: Jacob Trimble 
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 
---
 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, _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, _data);
+if (ret < 0)
+goto finish;
+
+av_freep(>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, _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.
+ 

Re: [FFmpeg-devel] libavutil/encryption_info: Allow multiple init info.

2018-06-21 Thread Jacob Trimble
On Thu, Jun 21, 2018 at 9:48 AM Michael Niedermayer
 wrote:
>
> > +if (UINT32_MAX == init_info_count ||
> > +UINT32_MAX - *side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA ||
> > +UINT32_MAX - *side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < 
> > info->system_id_size ||
> > +UINT32_MAX - *side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA - 
> > info->system_id_size < info->data_size) {
> >  return NULL;
> > +}
>
> you can simplify this with (u)int64_t
>

Done
From f440fe2be172672c439fa8b216b08a8d0895f76f Mon Sep 17 00:00:00 2001
From: Jacob Trimble 
Date: Mon, 23 Apr 2018 10:33:58 -0700
Subject: [PATCH] libavutil/encryption_info: Allow multiple init info.

It is possible for there to be multiple encryption init info structure.
For example, to support multiple key systems or in key rotation.  This
changes the AVEncryptionInitInfo struct to be a linked list so there
can be multiple structs without breaking ABI.

Signed-off-by: Jacob Trimble 
---
 libavutil/encryption_info.c | 146 +++-
 libavutil/encryption_info.h |   5 ++
 2 files changed, 100 insertions(+), 51 deletions(-)

diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
index 20a752d6b4..3b7e16cd0c 100644
--- a/libavutil/encryption_info.c
+++ b/libavutil/encryption_info.c
@@ -160,13 +160,16 @@ uint8_t *av_encryption_info_add_side_data(const AVEncryptionInfo *info, size_t *
 }
 
 // The format of the AVEncryptionInitInfo side data:
-// u32be system_id_size
-// u32be num_key_ids
-// u32be key_id_size
-// u32be data_size
-// u8[system_id_size] system_id
-// u8[key_id_size][num_key_id] key_ids
-// u8[data_size] data
+// u32be init_info_count
+// {
+//   u32be system_id_size
+//   u32be num_key_ids
+//   u32be key_id_size
+//   u32be data_size
+//   u8[system_id_size] system_id
+//   u8[key_id_size][num_key_id] key_ids
+//   u8[data_size] data
+// }[init_info_count]
 
 #define FF_ENCRYPTION_INIT_INFO_EXTRA 16
 
@@ -215,6 +218,7 @@ void av_encryption_init_info_free(AVEncryptionInitInfo *info)
 for (i = 0; i < info->num_key_ids; i++) {
 av_free(info->key_ids[i]);
 }
+av_encryption_init_info_free(info->next);
 av_free(info->system_id);
 av_free(info->key_ids);
 av_free(info->data);
@@ -225,71 +229,111 @@ void av_encryption_init_info_free(AVEncryptionInitInfo *info)
 AVEncryptionInitInfo *av_encryption_init_info_get_side_data(
 const uint8_t *side_data, size_t side_data_size)
 {
-AVEncryptionInitInfo *info;
-uint64_t system_id_size, num_key_ids, key_id_size, data_size, i;
+// |ret| tracks the front of the list, |info| tracks the back.
+AVEncryptionInitInfo *ret = NULL, *info, *temp_info;
+uint64_t system_id_size, num_key_ids, key_id_size, data_size, i, j;
+uint64_t init_info_count;
 
-if (!side_data || side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA)
+if (!side_data || side_data_size < 4)
 return NULL;
 
-system_id_size = AV_RB32(side_data);
-num_key_ids = AV_RB32(side_data + 4);
-key_id_size = AV_RB32(side_data + 8);
-data_size = AV_RB32(side_data + 12);
+init_info_count = AV_RB32(side_data);
+side_data += 4;
+side_data_size -= 4;
+for (i = 0; i < init_info_count; i++) {
+if (side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA) {
+av_encryption_init_info_free(ret);
+return NULL;
+}
 
-// UINT32_MAX + UINT32_MAX + UINT32_MAX * UINT32_MAX == UINT64_MAX
-if (side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < system_id_size + data_size + num_key_ids * key_id_size)
-return NULL;
+system_id_size = AV_RB32(side_data);
+num_key_ids = AV_RB32(side_data + 4);
+key_id_size = AV_RB32(side_data + 8);
+data_size = AV_RB32(side_data + 12);
 
-info = av_encryption_init_info_alloc(system_id_size, num_key_ids, key_id_size, data_size);
-if (!info)
-return NULL;
+// UINT32_MAX + UINT32_MAX + UINT32_MAX * UINT32_MAX == UINT64_MAX
+if (side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < system_id_size + data_size + num_key_ids * key_id_size) {
+av_encryption_init_info_free(ret);
+return NULL;
+}
+side_data += FF_ENCRYPTION_INIT_INFO_EXTRA;
+side_data_size -= FF_ENCRYPTION_INIT_INFO_EXTRA;
+
+temp_info = av_encryption_init_info_alloc(system_id_size, num_key_ids, key_id_size, data_size);
+if (!temp_info) {
+av_encryption_init_info_free(ret);
+return NULL;
+}
+if (i == 0) {
+info = ret = temp_info;
+} else {
+info->next = temp_info;
+info = temp_info;
+}
 
-memcpy(info->system_id, side_data + 16, system_id_size);
-side_data += system_id_si

Re: [FFmpeg-devel] libavutil/encryption_info: Allow multiple init info.

2018-06-20 Thread Jacob Trimble
On Thu, Jun 14, 2018 at 9:44 AM Jacob Trimble  wrote:
>
> On Thu, Jun 7, 2018 at 11:51 AM Jacob Trimble  wrote:
> >
> > On Thu, May 31, 2018 at 5:50 PM Jacob Trimble  wrote:
> > >
> > > On Thu, May 31, 2018 at 9:40 AM Jacob Trimble  wrote:
> > > >
> > > > On Fri, May 25, 2018 at 6:13 PM Michael Niedermayer
> > > >  wrote:
> > > > >
> > > > > [...]
> > > > >
> > > > > > Added fix for issue found by Chrome's ClusterFuzz 
> > > > > > (http://crbug.com/846662).
> > > > >
> > > > > this belongs in a seperate patch unless its a bug specific to the 
> > > > > code added
> > > > > with this patch
> > > > >
> > > >
> > > > Ok.  Now this patch depends on
> > > > http://ffmpeg.org/pipermail/ffmpeg-devel/2018-May/230782.html.
> > > >
> > >
> > > Noticed some bugs when integrating it.
> > >
> > > > > [...]
> > > > >
> > > > > --
> > > > > Michael GnuPG fingerprint: 
> > > > > 9FF2128B147EF6730BADF133611EC787040B0FAB
> > > > >
> > > > > I have often repented speaking, but never of holding my tongue.
> > > > > -- Xenocrates
> > > > > ___
> > > > > ffmpeg-devel mailing list
> > > > > ffmpeg-devel@ffmpeg.org
> > > > > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >
> > Removed controversial NULL checks.  This patch no longer depends on 
> > anything.
>
> Ping.

Ping.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] libavutil/encryption_info: Allow multiple init info.

2018-06-14 Thread Jacob Trimble
On Thu, Jun 7, 2018 at 11:51 AM Jacob Trimble  wrote:
>
> On Thu, May 31, 2018 at 5:50 PM Jacob Trimble  wrote:
> >
> > On Thu, May 31, 2018 at 9:40 AM Jacob Trimble  wrote:
> > >
> > > On Fri, May 25, 2018 at 6:13 PM Michael Niedermayer
> > >  wrote:
> > > >
> > > > [...]
> > > >
> > > > > Added fix for issue found by Chrome's ClusterFuzz 
> > > > > (http://crbug.com/846662).
> > > >
> > > > this belongs in a seperate patch unless its a bug specific to the code 
> > > > added
> > > > with this patch
> > > >
> > >
> > > Ok.  Now this patch depends on
> > > http://ffmpeg.org/pipermail/ffmpeg-devel/2018-May/230782.html.
> > >
> >
> > Noticed some bugs when integrating it.
> >
> > > > [...]
> > > >
> > > > --
> > > > Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
> > > >
> > > > I have often repented speaking, but never of holding my tongue.
> > > > -- Xenocrates
> > > > ___
> > > > ffmpeg-devel mailing list
> > > > ffmpeg-devel@ffmpeg.org
> > > > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> Removed controversial NULL checks.  This patch no longer depends on anything.

Ping.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/mov: Add check for per-sample IV size.

2018-06-12 Thread Jacob Trimble
Found by Chrome's ClusterFuzz: http://crbug.com/849062.

Signed-off-by: Jacob Trimble 
---
 libavformat/mov.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index 2fca025889..5d9ffa69a3 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -6273,8 +6273,13 @@ static int mov_read_tenc(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
 return AVERROR(ENOMEM);
 }
 sc->cenc.per_sample_iv_size = avio_r8(pb);
+if (sc->cenc.per_sample_iv_size != 0 && sc->cenc.per_sample_iv_size != 8 &&
+sc->cenc.per_sample_iv_size != 16) {
+av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
+return AVERROR_INVALIDDATA;
+}
 if (avio_read(pb, sc->cenc.default_encrypted_sample->key_id, 16) != 16) {
-av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID");
+av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
 return AVERROR_INVALIDDATA;
 }
 
@@ -6286,7 +6291,7 @@ static int mov_read_tenc(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
 }
 
 if (avio_read(pb, sc->cenc.default_encrypted_sample->iv, iv_size) != 
iv_size) {
-av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV");
+av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
 return AVERROR_INVALIDDATA;
 }
 }
-- 
2.18.0.rc1.242.g61856ae69a-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] avformat/mov: Fix reading saio/saiz for clear content.

2018-06-07 Thread Jacob Trimble
On Thu, Jun 7, 2018 at 10:38 AM Jacob Trimble  wrote:
>
> Found by Chrome's ClusterFuzz: http://crbug.com/850389
>
> Signed-off-by: Jacob Trimble 
> ---
>  libavformat/mov.c | 10 ++
>  1 file changed, 10 insertions(+)
>
> diff --git a/libavformat/mov.c b/libavformat/mov.c
> index 4ad19122b3..d07171b3f4 100644
> --- a/libavformat/mov.c
> +++ b/libavformat/mov.c
> @@ -6041,6 +6041,11 @@ static int mov_read_saiz(MOVContext *c, AVIOContext 
> *pb, MOVAtom atom)
>  if (ret != 1)
>  return ret;
>
> +if (!sc->cenc.default_encrypted_sample) {
> +// Didn't see a 'schm' or 'tenc' atom, so it isn't encrypted.
> +return 0;
> +}
> +
>  if (encryption_index->nb_encrypted_samples) {
>  // This can happen if we have both saio/saiz and senc atoms.
>  av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in 
> saiz\n");
> @@ -6095,6 +6100,11 @@ static int mov_read_saio(MOVContext *c, AVIOContext 
> *pb, MOVAtom atom)
>  if (ret != 1)
>  return ret;
>
> +if (!sc->cenc.default_encrypted_sample) {
> +// Didn't see a 'schm' or 'tenc' atom, so it isn't encrypted.
> +return 0;
> +}
> +
>  if (encryption_index->nb_encrypted_samples) {
>  // This can happen if we have both saio/saiz and senc atoms.
>  av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in 
> saio\n");
> --
> 2.17.1.1185.g55be947832-goog
>

Based on comments downstream, I've added error checks for the
encrypted type of saio/saiz atoms.
From e4185c0fd08a1baedcf81935ff0f5ac9a97eba4e Mon Sep 17 00:00:00 2001
From: Jacob Trimble 
Date: Thu, 7 Jun 2018 10:29:33 -0700
Subject: [PATCH] avformat/mov: Fix reading saio/saiz for clear content.

This validates that the common encryption saio/saiz atoms only appear
when the data is actually encrypted.  This also ignores those atoms
in clear content.

Found by Chrome's ClusterFuzz: http://crbug.com/850389

Signed-off-by: Jacob Trimble 
---
 libavformat/mov.c | 71 ---
 1 file changed, 55 insertions(+), 16 deletions(-)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index 4ad19122b3..2fca025889 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -6035,7 +6035,7 @@ static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 MOVEncryptionIndex *encryption_index;
 MOVStreamContext *sc;
 int ret;
-unsigned int sample_count;
+unsigned int sample_count, aux_info_type, aux_info_param;
 
 ret = get_current_encryption_info(c, _index, );
 if (ret != 1)
@@ -6054,14 +6054,33 @@ static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 
 avio_r8(pb); /* version */
 if (avio_rb24(pb) & 0x01) {  /* flags */
-if (avio_rb32(pb) != sc->cenc.default_encrypted_sample->scheme) {
-av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
-return 0;
-}
-if (avio_rb32(pb) != 0) {
-av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
-return 0;
+aux_info_type = avio_rb32(pb);
+aux_info_param = avio_rb32(pb);
+if (sc->cenc.default_encrypted_sample) {
+if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
+av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
+return 0;
+}
+if (aux_info_param != 0) {
+av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
+return 0;
+}
+} else {
+// Didn't see 'schm' or 'tenc', so this isn't encrypted.
+if ((aux_info_type == MKBETAG('c','e','n','c') ||
+ aux_info_type == MKBETAG('c','e','n','s') ||
+ aux_info_type == MKBETAG('c','b','c','1') ||
+ aux_info_type == MKBETAG('c','b','c','s')) &&
+aux_info_param == 0) {
+av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
+return AVERROR_INVALIDDATA;
+} else {
+return 0;
+}
 }
+} else if (!sc->cenc.default_encrypted_sample) {
+// Didn't see 'schm' or 'tenc', so this isn't encrypted.
+return 0;
 }
 
 encryption_index->auxiliary_info_default_size = avio_r8(pb);
@@ -6089,7 +6108,8 @@ static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 MOVEncryptionIndex *encryption_index;
 MOVStreamContext *sc;
 int i, ret;
-unsigned int version, entry_count, alloc_size = 0;
+unsigned int versi

Re: [FFmpeg-devel] libavutil/encryption_info: Allow multiple init info.

2018-06-07 Thread Jacob Trimble
On Thu, May 31, 2018 at 5:50 PM Jacob Trimble  wrote:
>
> On Thu, May 31, 2018 at 9:40 AM Jacob Trimble  wrote:
> >
> > On Fri, May 25, 2018 at 6:13 PM Michael Niedermayer
> >  wrote:
> > >
> > > [...]
> > >
> > > > Added fix for issue found by Chrome's ClusterFuzz 
> > > > (http://crbug.com/846662).
> > >
> > > this belongs in a seperate patch unless its a bug specific to the code 
> > > added
> > > with this patch
> > >
> >
> > Ok.  Now this patch depends on
> > http://ffmpeg.org/pipermail/ffmpeg-devel/2018-May/230782.html.
> >
>
> Noticed some bugs when integrating it.
>
> > > [...]
> > >
> > > --
> > > Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
> > >
> > > I have often repented speaking, but never of holding my tongue.
> > > -- Xenocrates
> > > ___
> > > ffmpeg-devel mailing list
> > > ffmpeg-devel@ffmpeg.org
> > > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Removed controversial NULL checks.  This patch no longer depends on anything.
From 0c4c33f26ba4204a775709cdd6367dd1ea4bd024 Mon Sep 17 00:00:00 2001
From: Jacob Trimble 
Date: Mon, 23 Apr 2018 10:33:58 -0700
Subject: [PATCH] libavutil/encryption_info: Allow multiple init info.

It is possible for there to be multiple encryption init info structure.
For example, to support multiple key systems or in key rotation.  This
changes the AVEncryptionInitInfo struct to be a linked list so there
can be multiple structs without breaking ABI.

Signed-off-by: Jacob Trimble 
---
 libavutil/encryption_info.c | 140 
 libavutil/encryption_info.h |   5 ++
 2 files changed, 100 insertions(+), 45 deletions(-)

diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
index 20a752d6b4..1072d2795b 100644
--- a/libavutil/encryption_info.c
+++ b/libavutil/encryption_info.c
@@ -160,13 +160,16 @@ uint8_t *av_encryption_info_add_side_data(const AVEncryptionInfo *info, size_t *
 }
 
 // The format of the AVEncryptionInitInfo side data:
-// u32be system_id_size
-// u32be num_key_ids
-// u32be key_id_size
-// u32be data_size
-// u8[system_id_size] system_id
-// u8[key_id_size][num_key_id] key_ids
-// u8[data_size] data
+// u32be init_info_count
+// {
+//   u32be system_id_size
+//   u32be num_key_ids
+//   u32be key_id_size
+//   u32be data_size
+//   u8[system_id_size] system_id
+//   u8[key_id_size][num_key_id] key_ids
+//   u8[data_size] data
+// }[init_info_count]
 
 #define FF_ENCRYPTION_INIT_INFO_EXTRA 16
 
@@ -215,6 +218,7 @@ void av_encryption_init_info_free(AVEncryptionInitInfo *info)
 for (i = 0; i < info->num_key_ids; i++) {
 av_free(info->key_ids[i]);
 }
+av_encryption_init_info_free(info->next);
 av_free(info->system_id);
 av_free(info->key_ids);
 av_free(info->data);
@@ -225,71 +229,117 @@ void av_encryption_init_info_free(AVEncryptionInitInfo *info)
 AVEncryptionInitInfo *av_encryption_init_info_get_side_data(
 const uint8_t *side_data, size_t side_data_size)
 {
-AVEncryptionInitInfo *info;
-uint64_t system_id_size, num_key_ids, key_id_size, data_size, i;
+// |ret| tracks the front of the list, |info| tracks the back.
+AVEncryptionInitInfo *ret = NULL, *info, *temp_info;
+uint64_t system_id_size, num_key_ids, key_id_size, data_size, i, j;
+uint64_t init_info_count;
 
-if (!side_data || side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA)
+if (!side_data || side_data_size < 4)
 return NULL;
 
-system_id_size = AV_RB32(side_data);
-num_key_ids = AV_RB32(side_data + 4);
-key_id_size = AV_RB32(side_data + 8);
-data_size = AV_RB32(side_data + 12);
+init_info_count = AV_RB32(side_data);
+side_data += 4;
+side_data_size -= 4;
+for (i = 0; i < init_info_count; i++) {
+if (side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA) {
+av_encryption_init_info_free(ret);
+return NULL;
+}
 
-// UINT32_MAX + UINT32_MAX + UINT32_MAX * UINT32_MAX == UINT64_MAX
-if (side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < system_id_size + data_size + num_key_ids * key_id_size)
-return NULL;
+system_id_size = AV_RB32(side_data);
+num_key_ids = AV_RB32(side_data + 4);
+key_id_size = AV_RB32(side_data + 8);
+data_size = AV_RB32(side_data + 12);
 
-info = av_encryption_init_info_alloc(system_id_size, num_key_ids, key_id_size, data_size);
-if (!info)
-return NULL;
+// UINT32_MAX + UINT32_MAX + UINT32_MAX * UINT32_MAX == UINT64_MAX
+if (side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < system_id_size + data_size + num_key_ids * key_id_size) {
+

[FFmpeg-devel] [PATCH] avformat/mov: Fix reading saio/saiz for clear content.

2018-06-07 Thread Jacob Trimble
Found by Chrome's ClusterFuzz: http://crbug.com/850389

Signed-off-by: Jacob Trimble 
---
 libavformat/mov.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index 4ad19122b3..d07171b3f4 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -6041,6 +6041,11 @@ static int mov_read_saiz(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
 if (ret != 1)
 return ret;
 
+if (!sc->cenc.default_encrypted_sample) {
+// Didn't see a 'schm' or 'tenc' atom, so it isn't encrypted.
+return 0;
+}
+
 if (encryption_index->nb_encrypted_samples) {
 // This can happen if we have both saio/saiz and senc atoms.
 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in 
saiz\n");
@@ -6095,6 +6100,11 @@ static int mov_read_saio(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
 if (ret != 1)
 return ret;
 
+if (!sc->cenc.default_encrypted_sample) {
+// Didn't see a 'schm' or 'tenc' atom, so it isn't encrypted.
+return 0;
+}
+
 if (encryption_index->nb_encrypted_samples) {
 // This can happen if we have both saio/saiz and senc atoms.
 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in 
saio\n");
-- 
2.17.1.1185.g55be947832-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] libavutil/encryption_info: Add NULL checks.

2018-06-07 Thread Jacob Trimble
On Tue, Jun 5, 2018 at 1:06 PM Mark Thompson  wrote:
>
> On 05/06/18 17:30, Jacob Trimble wrote:
> > Just because I can't check whether my food has salmonella doesn't mean
> > I shouldn't check the temperature when I cook it.  Adding a NULL check
> > is trivial and will catch the most common error case.  We also can't
> > check whether malloc() allocates enough memory, so should we then not
> > check for NULL?  NULL is used as an error signal, so if the caller
> > didn't include a NULL check, they will pass it here.  Rather than
> > crashing the program (hopefully it will crash, it is undefined
> > behavior, so anything could happen), we should be nice and validate
> > the input and error out.  Just because it is impossible to check other
> > error cases doesn't mean we should ignore all error checks.
>
> (My opinion, others may disagree.)
>
> Please consider what is actually useful to an API user here.
>
> The check you are suggesting will cause the function to, when passed entirely 
> invalid arguments, silently return having done nothing.  Is this better than 
> the almost-guaranteed segfault you will get instead?  Well, no.  There is 
> much more scope for the error to go unnoticed and cause other hard-to-debug 
> issues later, where it could have been caught immediately.

It returns an error, which should be checked by the caller.  We can't
do anything to change the caller's code, but we can make our code not
crash their program.

>
> If there is a concern that a function like this could be misused then (since 
> this is certainly undefined behaviour in any case) turning it into an abort() 
> is the best case so that the program will definitely fail and any errors can 
> be diagnosed immediately.  As such, I think argument checks for nonsensical 
> invalid input like this should be done either with av_assert or not at all.

What about invalid MP4 files?  Should we convert those to abort() too?
 When parsing MP4 files, we check that it is valid and return an error
code if it is not.  There is no difference between a method to parse
an MP4 file and these, so these should validate the inputs as best it
can and return errors if we find them.

>
> - Mark
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

When I design an API, I try to make it hard to misuse, being as
helpful to the caller as possible.  Having the function intentionally
crash on certain input when a simple if could solve it is not a good
idea.  I think the memcpy API is an example of a bad api, it assumes
valid input.  Are we going to stop checking that MP4 files are valid
too?  If we only accept valid MP4 files it seems pointless to check it
and return errors.  These functions return NULL on errors, it is an
error to pass NULL, therefore we should check and return NULL.  It is
impossible to check some things, but if it were possible, I would
suggest checking that too.

One other problem is that NULL is sometimes a valid value to pass to a
function and sometimes not.  NULL is used as a signal value whereas an
invalid pointer is never valid.  From the compiler's point of view,
there is no difference between a function that accepts NULL as valid
and one that does not.  So the only thing we can do is write a comment
saying "Does not accept NULL", but this is fragile as the compiler
can't check this (without static analysis).  By having us return an
error for invalid input, it makes the API more stable and easier to
use.  We can't stop the caller from ignoring the return value, but we
can at least do our best to validate the input and avoid crashing the
program.

But if you aren't going to accept a patch to increase code heath,
there is nothing I can do.  I'll remove the NULL checks from my other
patch so it can be submitted.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] libavutil/encryption_info: Add NULL checks.

2018-06-05 Thread Jacob Trimble
On Mon, Jun 4, 2018 at 2:24 PM Carl Eugen Hoyos  wrote:
>
> 2018-06-04 23:07 GMT+02:00, Jacob Trimble :
> > On Mon, Jun 4, 2018 at 10:46 AM Carl Eugen Hoyos  wrote:
> >>
> >> 2018-06-04 18:59 GMT+02:00, Jacob Trimble
> >> :
> >> > On Fri, Jun 1, 2018 at 5:03 PM Michael Niedermayer
> >> >  wrote:
> >> >>
> >> >> On Thu, May 31, 2018 at 09:33:36AM -0700, Jacob Trimble wrote:
> >> >> > Found by Chrome's ClusterFuzz: http://crbug.com/846662.
> >> >> >
> >> >> > Signed-off-by: Jacob Trimble 
> >> >> > ---
> >> >> >  libavutil/encryption_info.c | 7 +--
> >> >> >  1 file changed, 5 insertions(+), 2 deletions(-)
> >> >> >
> >> >> > diff --git a/libavutil/encryption_info.c
> >> >> > b/libavutil/encryption_info.c
> >> >> > index 20a752d6b4..a48ded922c 100644
> >> >> > --- a/libavutil/encryption_info.c
> >> >> > +++ b/libavutil/encryption_info.c
> >> >> > @@ -64,6 +64,8 @@ AVEncryptionInfo *av_encryption_info_clone(const
> >> >> > AVEncryptionInfo *info)
> >> >> >  {
> >> >> >  AVEncryptionInfo *ret;
> >> >> >
> >> >> > +if (!info)
> >> >> > +return NULL;
> >> >> >  ret = av_encryption_info_alloc(info->subsample_count,
> >> >> > info->key_id_size, info->iv_size);
> >> >> >  if (!ret)
> >> >> >  return NULL;
> >> >>
> >> >> > @@ -127,7 +129,7 @@ uint8_t *av_encryption_info_add_side_data(const
> >> >> > AVEncryptionInfo *info, size_t *
> >> >> >  uint8_t *buffer, *cur_buffer;
> >> >> >  uint32_t i;
> >> >> >
> >> >> > -if (UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA < info->key_id_size ||
> >> >> > +if (!info || !size || UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA <
> >> >> > info->key_id_size ||
> >> >> >  UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA - info->key_id_size <
> >> >> > info->iv_size ||
> >> >> >  (UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA - info->key_id_size -
> >> >> > info->iv_size) / 8 < info->subsample_count) {
> >> >> >  return NULL;
> >> >> > @@ -260,7 +262,8 @@ uint8_t
> >> >> > *av_encryption_init_info_add_side_data(const
> >> >> > AVEncryptionInitInfo *info,
> >> >> >  uint8_t *buffer, *cur_buffer;
> >> >> >  uint32_t i, max_size;
> >> >> >
> >> >> > -if (UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA <
> >> >> > info->system_id_size ||
> >> >> > +if (!info || !side_data_size ||
> >> >> > +UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA <
> >> >> > info->system_id_size ||
> >> >> >  UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA -
> >> >> > info->system_id_size < info->data_size) {
> >> >> >  return NULL;
> >> >> >  }
> >> >>
> >> >> in which valid case would these be called with NULL input ?
> >> >> iam asking as this feels as if it might be a bug in teh caller
> >> >>
> >> >
> >> > This was found by Chrome's ClusterFuzz, which I am not that familiar
> >> > with.  I think it was just running fuzz tests directly on FFmpeg code,
> >> > so it wasn't in production code.  But since this is a public method,
> >> > we should validate the input in any case.
> >>
> >> How do you validate the size of C buffers in general?
> >
> > I'm not sure I understand your comment.  You can't verify the
> > length of buffers unless the size is given to the method.
>
> If we can't verify the size of the buffer (where both overread
> and overwrite at least can have catastrophic impact) why
> is it a good idea to check if the user passed an actual pointer
> (as is required) or NULL as argument (where NULL typically
> has limited impact)?
>
> > These functions do accept the size and verify that the data
> > is valid for the given size.
>
> I may misunderstand the code but it looks to me as if the
> given size is only checked because the needed space is
> not necessarily kno

Re: [FFmpeg-devel] [PATCH] libavutil/encryption_info: Add NULL checks.

2018-06-04 Thread Jacob Trimble
On Mon, Jun 4, 2018 at 10:46 AM Carl Eugen Hoyos  wrote:
>
> 2018-06-04 18:59 GMT+02:00, Jacob Trimble :
> > On Fri, Jun 1, 2018 at 5:03 PM Michael Niedermayer
> >  wrote:
> >>
> >> On Thu, May 31, 2018 at 09:33:36AM -0700, Jacob Trimble wrote:
> >> > Found by Chrome's ClusterFuzz: http://crbug.com/846662.
> >> >
> >> > Signed-off-by: Jacob Trimble 
> >> > ---
> >> >  libavutil/encryption_info.c | 7 +--
> >> >  1 file changed, 5 insertions(+), 2 deletions(-)
> >> >
> >> > diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
> >> > index 20a752d6b4..a48ded922c 100644
> >> > --- a/libavutil/encryption_info.c
> >> > +++ b/libavutil/encryption_info.c
> >> > @@ -64,6 +64,8 @@ AVEncryptionInfo *av_encryption_info_clone(const
> >> > AVEncryptionInfo *info)
> >> >  {
> >> >  AVEncryptionInfo *ret;
> >> >
> >> > +if (!info)
> >> > +return NULL;
> >> >  ret = av_encryption_info_alloc(info->subsample_count,
> >> > info->key_id_size, info->iv_size);
> >> >  if (!ret)
> >> >  return NULL;
> >>
> >> > @@ -127,7 +129,7 @@ uint8_t *av_encryption_info_add_side_data(const
> >> > AVEncryptionInfo *info, size_t *
> >> >  uint8_t *buffer, *cur_buffer;
> >> >  uint32_t i;
> >> >
> >> > -if (UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA < info->key_id_size ||
> >> > +if (!info || !size || UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA <
> >> > info->key_id_size ||
> >> >  UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA - info->key_id_size <
> >> > info->iv_size ||
> >> >  (UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA - info->key_id_size -
> >> > info->iv_size) / 8 < info->subsample_count) {
> >> >  return NULL;
> >> > @@ -260,7 +262,8 @@ uint8_t *av_encryption_init_info_add_side_data(const
> >> > AVEncryptionInitInfo *info,
> >> >  uint8_t *buffer, *cur_buffer;
> >> >  uint32_t i, max_size;
> >> >
> >> > -if (UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA <
> >> > info->system_id_size ||
> >> > +if (!info || !side_data_size ||
> >> > +UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA <
> >> > info->system_id_size ||
> >> >  UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA -
> >> > info->system_id_size < info->data_size) {
> >> >  return NULL;
> >> >  }
> >>
> >> in which valid case would these be called with NULL input ?
> >> iam asking as this feels as if it might be a bug in teh caller
> >>
> >
> > This was found by Chrome's ClusterFuzz, which I am not that familiar
> > with.  I think it was just running fuzz tests directly on FFmpeg code,
> > so it wasn't in production code.  But since this is a public method,
> > we should validate the input in any case.
>
> How do you validate the size of C buffers in general?
>

I'm not sure I understand your comment.  You can't verify the length
of buffers unless the size is given to the method.  These functions do
accept the size and verify that the data is valid for the given size.
Since we are verifying the data and the size we are given, we should
be checking for NULL as well.

> Carl Eugen
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] libavutil/encryption_info: Add NULL checks.

2018-06-04 Thread Jacob Trimble
On Fri, Jun 1, 2018 at 5:03 PM Michael Niedermayer
 wrote:
>
> On Thu, May 31, 2018 at 09:33:36AM -0700, Jacob Trimble wrote:
> > Found by Chrome's ClusterFuzz: http://crbug.com/846662.
> >
> > Signed-off-by: Jacob Trimble 
> > ---
> >  libavutil/encryption_info.c | 7 +--
> >  1 file changed, 5 insertions(+), 2 deletions(-)
> >
> > diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
> > index 20a752d6b4..a48ded922c 100644
> > --- a/libavutil/encryption_info.c
> > +++ b/libavutil/encryption_info.c
> > @@ -64,6 +64,8 @@ AVEncryptionInfo *av_encryption_info_clone(const 
> > AVEncryptionInfo *info)
> >  {
> >  AVEncryptionInfo *ret;
> >
> > +if (!info)
> > +return NULL;
> >  ret = av_encryption_info_alloc(info->subsample_count, 
> > info->key_id_size, info->iv_size);
> >  if (!ret)
> >  return NULL;
>
> > @@ -127,7 +129,7 @@ uint8_t *av_encryption_info_add_side_data(const 
> > AVEncryptionInfo *info, size_t *
> >  uint8_t *buffer, *cur_buffer;
> >  uint32_t i;
> >
> > -if (UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA < info->key_id_size ||
> > +if (!info || !size || UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA < 
> > info->key_id_size ||
> >  UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA - info->key_id_size < 
> > info->iv_size ||
> >  (UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA - info->key_id_size - 
> > info->iv_size) / 8 < info->subsample_count) {
> >  return NULL;
> > @@ -260,7 +262,8 @@ uint8_t *av_encryption_init_info_add_side_data(const 
> > AVEncryptionInitInfo *info,
> >  uint8_t *buffer, *cur_buffer;
> >  uint32_t i, max_size;
> >
> > -if (UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA < info->system_id_size 
> > ||
> > +if (!info || !side_data_size ||
> > +UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA < info->system_id_size 
> > ||
> >  UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA - info->system_id_size 
> > < info->data_size) {
> >  return NULL;
> >  }
>
> in which valid case would these be called with NULL input ?
> iam asking as this feels as if it might be a bug in teh caller
>

This was found by Chrome's ClusterFuzz, which I am not that familiar
with.  I think it was just running fuzz tests directly on FFmpeg code,
so it wasn't in production code.  But since this is a public method,
we should validate the input in any case.

> thx
>
> [...]
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> In a rich man's house there is no place to spit but his face.
> -- Diogenes of Sinope
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] libavutil/encryption_info: Add unit tests.

2018-06-01 Thread Jacob Trimble
On Fri, Jun 1, 2018 at 12:52 PM Jacob Trimble  wrote:
>
> Signed-off-by: Jacob Trimble 
> ---
>  libavutil/Makefile|   1 +
>  libavutil/encryption_info.h   |   2 +-
>  libavutil/tests/.gitignore|   2 +
>  libavutil/tests/encryption_info.c | 176 ++
>  tests/fate/libavutil.mak  |   4 +
>  tests/ref/fate/encryption-info|   0
>  6 files changed, 184 insertions(+), 1 deletion(-)
>  create mode 100644 libavutil/tests/encryption_info.c
>  create mode 100644 tests/ref/fate/encryption-info
>
> diff --git a/libavutil/Makefile b/libavutil/Makefile
> index d0632f16a6..9ed24cfc82 100644
> --- a/libavutil/Makefile
> +++ b/libavutil/Makefile
> @@ -200,6 +200,7 @@ TESTPROGS = adler32   
>   \
>  des \
>  dict\
>  display \
> +encryption_info \
>  error   \
>  eval\
>  file\
> diff --git a/libavutil/encryption_info.h b/libavutil/encryption_info.h
> index 9140968fde..8fe7ebfe43 100644
> --- a/libavutil/encryption_info.h
> +++ b/libavutil/encryption_info.h
> @@ -129,7 +129,7 @@ typedef struct AVEncryptionInitInfo {
>   *
>   * @param subsample_count The number of subsamples.
>   * @param key_id_size The number of bytes in the key ID, should be 16.
> - * @param key_id_size The number of bytes in the IV, should be 16.
> + * @param iv_size The number of bytes in the IV, should be 16.
>   *
>   * @return The new AVEncryptionInfo structure, or NULL on error.
>   */
> diff --git a/libavutil/tests/.gitignore b/libavutil/tests/.gitignore
> index 71f75a8ee9..9d90827954 100644
> --- a/libavutil/tests/.gitignore
> +++ b/libavutil/tests/.gitignore
> @@ -17,6 +17,7 @@
>  /dict
>  /display
>  /error
> +/encryption_info
>  /eval
>  /fifo
>  /file
> @@ -24,6 +25,7 @@
>  /hmac
>  /hwdevice
>  /imgutils
> +/integer
>  /lfg
>  /lls
>  /log
> diff --git a/libavutil/tests/encryption_info.c 
> b/libavutil/tests/encryption_info.c
> new file mode 100644
> index 00..d489612b7d
> --- /dev/null
> +++ b/libavutil/tests/encryption_info.c
> @@ -0,0 +1,176 @@
> +/*
> + * 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
> + */
> +
> +#include "libavutil/encryption_info.h"
> +
> +#include 
> +#include 
> +
> +#include "libavutil/avassert.h"
> +
> +static const AVSubsampleEncryptionInfo test_subsamples[] = {{1, 2}, {3, 4}, 
> {5, 6}, {7, 8}};
> +static const size_t test_subsample_count = sizeof(test_subsamples) / 
> sizeof(test_subsamples[0]);
> +static const uint8_t test_iv[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
> 0x18};
> +static const uint8_t test_key_id[] = {0x21, 0x22, 0x23, 0x24};
> +static const uint8_t test_key_id_2[] = {0x31, 0x32, 0x33, 0x34};
> +static const uint8_t test_system_id[] = {0x41, 0x42, 0x43};
> +static const uint8_t test_data[] = {0x51, 0x52};
> +
> +static int compare_encryption_info(const AVEncryptionInfo *a, const 
> AVEncryptionInfo *b) {
> +if (!a || !b || a->scheme != b->scheme || a->crypt_byte_block != 
> b->crypt_byte_block ||
> +a->skip_byte_block != b->skip_byte_block || a->key_id_size != 
> b->key_id_size ||
> +a->iv_size != b->iv_size || a->subsample_count != b->subsample_count)
> +return 1;
> +
> +if (memcmp(a->key_id, b->key_id, a->key_id_size) != 0 ||
> +memcmp(a->iv, b->iv, a->iv_size) != 0 ||
> +memcmp(a->subsamples, b->subsamples

[FFmpeg-devel] [PATCH] libavutil/encryption_info: Add unit tests.

2018-06-01 Thread Jacob Trimble
Signed-off-by: Jacob Trimble 
---
 libavutil/Makefile|   1 +
 libavutil/encryption_info.h   |   2 +-
 libavutil/tests/.gitignore|   2 +
 libavutil/tests/encryption_info.c | 176 ++
 tests/fate/libavutil.mak  |   4 +
 tests/ref/fate/encryption-info|   0
 6 files changed, 184 insertions(+), 1 deletion(-)
 create mode 100644 libavutil/tests/encryption_info.c
 create mode 100644 tests/ref/fate/encryption-info

diff --git a/libavutil/Makefile b/libavutil/Makefile
index d0632f16a6..9ed24cfc82 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -200,6 +200,7 @@ TESTPROGS = adler32 
\
 des \
 dict\
 display \
+encryption_info \
 error   \
 eval\
 file\
diff --git a/libavutil/encryption_info.h b/libavutil/encryption_info.h
index 9140968fde..8fe7ebfe43 100644
--- a/libavutil/encryption_info.h
+++ b/libavutil/encryption_info.h
@@ -129,7 +129,7 @@ typedef struct AVEncryptionInitInfo {
  *
  * @param subsample_count The number of subsamples.
  * @param key_id_size The number of bytes in the key ID, should be 16.
- * @param key_id_size The number of bytes in the IV, should be 16.
+ * @param iv_size The number of bytes in the IV, should be 16.
  *
  * @return The new AVEncryptionInfo structure, or NULL on error.
  */
diff --git a/libavutil/tests/.gitignore b/libavutil/tests/.gitignore
index 71f75a8ee9..9d90827954 100644
--- a/libavutil/tests/.gitignore
+++ b/libavutil/tests/.gitignore
@@ -17,6 +17,7 @@
 /dict
 /display
 /error
+/encryption_info
 /eval
 /fifo
 /file
@@ -24,6 +25,7 @@
 /hmac
 /hwdevice
 /imgutils
+/integer
 /lfg
 /lls
 /log
diff --git a/libavutil/tests/encryption_info.c 
b/libavutil/tests/encryption_info.c
new file mode 100644
index 00..d489612b7d
--- /dev/null
+++ b/libavutil/tests/encryption_info.c
@@ -0,0 +1,176 @@
+/*
+ * 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
+ */
+
+#include "libavutil/encryption_info.h"
+
+#include 
+#include 
+
+#include "libavutil/avassert.h"
+
+static const AVSubsampleEncryptionInfo test_subsamples[] = {{1, 2}, {3, 4}, 
{5, 6}, {7, 8}};
+static const size_t test_subsample_count = sizeof(test_subsamples) / 
sizeof(test_subsamples[0]);
+static const uint8_t test_iv[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
0x18};
+static const uint8_t test_key_id[] = {0x21, 0x22, 0x23, 0x24};
+static const uint8_t test_key_id_2[] = {0x31, 0x32, 0x33, 0x34};
+static const uint8_t test_system_id[] = {0x41, 0x42, 0x43};
+static const uint8_t test_data[] = {0x51, 0x52};
+
+static int compare_encryption_info(const AVEncryptionInfo *a, const 
AVEncryptionInfo *b) {
+if (!a || !b || a->scheme != b->scheme || a->crypt_byte_block != 
b->crypt_byte_block ||
+a->skip_byte_block != b->skip_byte_block || a->key_id_size != 
b->key_id_size ||
+a->iv_size != b->iv_size || a->subsample_count != b->subsample_count)
+return 1;
+
+if (memcmp(a->key_id, b->key_id, a->key_id_size) != 0 ||
+memcmp(a->iv, b->iv, a->iv_size) != 0 ||
+memcmp(a->subsamples, b->subsamples, a->subsample_count * 
sizeof(a->subsamples[0])))
+return 1;
+
+return 0;
+}
+
+static int compare_encryption_init_info(const AVEncryptionInitInfo *a, const 
AVEncryptionInitInfo *b) {
+if (!a || !b || a->system_id_size != b->system_id_size ||
+a->num_key_ids != b->num_key_ids || a->key_id_size != b->key_id_size ||
+a->data_size != b->data_size)
+return 1;
+
+if (memcmp(a->system_id, b->system_id, a->system_id_size) != 0 ||
+memcmp(a->data, b->data, a->data_size) != 0)
+return 1;
+
+for (uint32_t i = 0; i < a->num_ke

Re: [FFmpeg-devel] libavutil/encryption_info: Allow multiple init info.

2018-05-31 Thread Jacob Trimble
On Thu, May 31, 2018 at 9:40 AM Jacob Trimble  wrote:
>
> On Fri, May 25, 2018 at 6:13 PM Michael Niedermayer
>  wrote:
> >
> > [...]
> >
> > > Added fix for issue found by Chrome's ClusterFuzz 
> > > (http://crbug.com/846662).
> >
> > this belongs in a seperate patch unless its a bug specific to the code added
> > with this patch
> >
>
> Ok.  Now this patch depends on
> http://ffmpeg.org/pipermail/ffmpeg-devel/2018-May/230782.html.
>

Noticed some bugs when integrating it.

> > [...]
> >
> > --
> > Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
> >
> > I have often repented speaking, but never of holding my tongue.
> > -- Xenocrates
> > ___
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
From ea52a1264787256a2c92bc162d217b98e1b39e23 Mon Sep 17 00:00:00 2001
From: Jacob Trimble 
Date: Mon, 23 Apr 2018 10:33:58 -0700
Subject: [PATCH] libavutil/encryption_info: Allow multiple init info.

It is possible for there to be multiple encryption init info structure.
For example, to support multiple key systems or in key rotation.  This
changes the AVEncryptionInitInfo struct to be a linked list so there
can be multiple structs without breaking ABI.

Signed-off-by: Jacob Trimble 
---
 libavutil/encryption_info.c | 153 
 libavutil/encryption_info.h |   5 ++
 2 files changed, 109 insertions(+), 49 deletions(-)

diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
index a48ded922c..00f7d0fde0 100644
--- a/libavutil/encryption_info.c
+++ b/libavutil/encryption_info.c
@@ -162,13 +162,16 @@ uint8_t *av_encryption_info_add_side_data(const AVEncryptionInfo *info, size_t *
 }
 
 // The format of the AVEncryptionInitInfo side data:
-// u32be system_id_size
-// u32be num_key_ids
-// u32be key_id_size
-// u32be data_size
-// u8[system_id_size] system_id
-// u8[key_id_size][num_key_id] key_ids
-// u8[data_size] data
+// u32be init_info_count
+// {
+//   u32be system_id_size
+//   u32be num_key_ids
+//   u32be key_id_size
+//   u32be data_size
+//   u8[system_id_size] system_id
+//   u8[key_id_size][num_key_id] key_ids
+//   u8[data_size] data
+// }[init_info_count]
 
 #define FF_ENCRYPTION_INIT_INFO_EXTRA 16
 
@@ -217,6 +220,7 @@ void av_encryption_init_info_free(AVEncryptionInitInfo *info)
 for (i = 0; i < info->num_key_ids; i++) {
 av_free(info->key_ids[i]);
 }
+av_encryption_init_info_free(info->next);
 av_free(info->system_id);
 av_free(info->key_ids);
 av_free(info->data);
@@ -227,72 +231,123 @@ void av_encryption_init_info_free(AVEncryptionInitInfo *info)
 AVEncryptionInitInfo *av_encryption_init_info_get_side_data(
 const uint8_t *side_data, size_t side_data_size)
 {
-AVEncryptionInitInfo *info;
-uint64_t system_id_size, num_key_ids, key_id_size, data_size, i;
+// |ret| tracks the front of the list, |info| tracks the back.
+AVEncryptionInitInfo *ret = NULL, *info, *temp_info;
+uint64_t system_id_size, num_key_ids, key_id_size, data_size, i, j;
+uint64_t init_info_count;
 
-if (!side_data || side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA)
+if (!side_data || side_data_size < 4)
 return NULL;
 
-system_id_size = AV_RB32(side_data);
-num_key_ids = AV_RB32(side_data + 4);
-key_id_size = AV_RB32(side_data + 8);
-data_size = AV_RB32(side_data + 12);
+init_info_count = AV_RB32(side_data);
+side_data += 4;
+side_data_size -= 4;
+for (i = 0; i < init_info_count; i++) {
+if (side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA) {
+av_encryption_init_info_free(ret);
+return NULL;
+}
 
-// UINT32_MAX + UINT32_MAX + UINT32_MAX * UINT32_MAX == UINT64_MAX
-if (side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < system_id_size + data_size + num_key_ids * key_id_size)
-return NULL;
+system_id_size = AV_RB32(side_data);
+num_key_ids = AV_RB32(side_data + 4);
+key_id_size = AV_RB32(side_data + 8);
+data_size = AV_RB32(side_data + 12);
 
-info = av_encryption_init_info_alloc(system_id_size, num_key_ids, key_id_size, data_size);
-if (!info)
-return NULL;
+// UINT32_MAX + UINT32_MAX + UINT32_MAX * UINT32_MAX == UINT64_MAX
+if (side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < system_id_size + data_size + num_key_ids * key_id_size) {
+av_encryption_init_info_free(ret);
+return NULL;
+}
+side_data += FF_ENCRYPTION_INIT_INFO_EXTRA;
+side_data_size -= FF_ENCRYPTION_INIT_INFO_EXTRA;
+
+temp_info = av_encryption_init_info_alloc(system_id_size, num_key_ids, key_id_size, data_size);
+

[FFmpeg-devel] [PATCH] libavformat/mov: Fix heap buffer overflow.

2018-05-31 Thread Jacob Trimble
Found by Chrome's ClusterFuzz: https://crbug.com/847060

Signed-off-by: Jacob Trimble 
---
 libavformat/mov.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index f2a540ad50..08cc382a68 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -5895,7 +5895,7 @@ static int mov_read_senc(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
 return AVERROR(ENOMEM);
 
 for (i = 0; i < sample_count; i++) {
-unsigned int min_samples = FFMIN(FFMAX(i, 1024 * 1024), sample_count);
+unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), 
sample_count);
 encrypted_samples = 
av_fast_realloc(encryption_index->encrypted_samples, _size,
 min_samples * 
sizeof(*encrypted_samples));
 if (encrypted_samples) {
@@ -5949,7 +5949,7 @@ static int mov_parse_auxiliary_info(MOVContext *c, 
MOVStreamContext *sc, AVIOCon
 }
 
 for (i = 0; i < sample_count && !pb->eof_reached; i++) {
-unsigned int min_samples = FFMIN(FFMAX(i, 1024 * 1024), sample_count);
+unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), 
sample_count);
 encrypted_samples = 
av_fast_realloc(encryption_index->encrypted_samples, _size,
 min_samples * 
sizeof(*encrypted_samples));
 if (!encrypted_samples) {
@@ -6110,7 +6110,7 @@ static int mov_read_saio(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
 return AVERROR(ENOMEM);
 
 for (i = 0; i < entry_count && !pb->eof_reached; i++) {
-unsigned int min_offsets = FFMIN(FFMAX(i, 1024), entry_count);
+unsigned int min_offsets = FFMIN(FFMAX(i + 1, 1024), entry_count);
 auxiliary_offsets = av_fast_realloc(
 encryption_index->auxiliary_offsets, _size,
 min_offsets * sizeof(*auxiliary_offsets));
-- 
2.17.0.921.gf22659ad46-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] libavutil/encryption_info: Allow multiple init info.

2018-05-31 Thread Jacob Trimble
On Fri, May 25, 2018 at 6:13 PM Michael Niedermayer
 wrote:
>
> [...]
>
> > Added fix for issue found by Chrome's ClusterFuzz (http://crbug.com/846662).
>
> this belongs in a seperate patch unless its a bug specific to the code added
> with this patch
>

Ok.  Now this patch depends on
http://ffmpeg.org/pipermail/ffmpeg-devel/2018-May/230782.html.

> [...]
>
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> I have often repented speaking, but never of holding my tongue.
> -- Xenocrates
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
From 468958a26c1df8f599925038518ca4dae90de0f7 Mon Sep 17 00:00:00 2001
From: Jacob Trimble 
Date: Mon, 23 Apr 2018 10:33:58 -0700
Subject: [PATCH] libavutil/encryption_info: Allow multiple init info.

It is possible for there to be multiple encryption init info structure.
For example, to support multiple key systems or in key rotation.  This
changes the AVEncryptionInitInfo struct to be a linked list so there
can be multiple structs without breaking ABI.

Signed-off-by: Jacob Trimble 
---
 libavutil/encryption_info.c | 148 
 libavutil/encryption_info.h |   5 ++
 2 files changed, 104 insertions(+), 49 deletions(-)

diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
index a48ded922c..4675ceccf6 100644
--- a/libavutil/encryption_info.c
+++ b/libavutil/encryption_info.c
@@ -162,13 +162,16 @@ uint8_t *av_encryption_info_add_side_data(const AVEncryptionInfo *info, size_t *
 }
 
 // The format of the AVEncryptionInitInfo side data:
-// u32be system_id_size
-// u32be num_key_ids
-// u32be key_id_size
-// u32be data_size
-// u8[system_id_size] system_id
-// u8[key_id_size][num_key_id] key_ids
-// u8[data_size] data
+// u32be init_info_count
+// {
+//   u32be system_id_size
+//   u32be num_key_ids
+//   u32be key_id_size
+//   u32be data_size
+//   u8[system_id_size] system_id
+//   u8[key_id_size][num_key_id] key_ids
+//   u8[data_size] data
+// }[init_info_count]
 
 #define FF_ENCRYPTION_INIT_INFO_EXTRA 16
 
@@ -217,6 +220,7 @@ void av_encryption_init_info_free(AVEncryptionInitInfo *info)
 for (i = 0; i < info->num_key_ids; i++) {
 av_free(info->key_ids[i]);
 }
+av_encryption_init_info_free(info->next);
 av_free(info->system_id);
 av_free(info->key_ids);
 av_free(info->data);
@@ -227,72 +231,118 @@ void av_encryption_init_info_free(AVEncryptionInitInfo *info)
 AVEncryptionInitInfo *av_encryption_init_info_get_side_data(
 const uint8_t *side_data, size_t side_data_size)
 {
-AVEncryptionInitInfo *info;
-uint64_t system_id_size, num_key_ids, key_id_size, data_size, i;
+AVEncryptionInitInfo *ret = NULL, *info;
+uint64_t system_id_size, num_key_ids, key_id_size, data_size, i, j;
+uint64_t init_info_count;
 
-if (!side_data || side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA)
+if (!side_data || side_data_size < 4)
 return NULL;
 
-system_id_size = AV_RB32(side_data);
-num_key_ids = AV_RB32(side_data + 4);
-key_id_size = AV_RB32(side_data + 8);
-data_size = AV_RB32(side_data + 12);
+init_info_count = AV_RB32(side_data);
+side_data += 4;
+side_data_size -= 4;
+for (i = 0; i < init_info_count; i++) {
+if (side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA) {
+av_encryption_init_info_free(ret);
+return NULL;
+}
 
-// UINT32_MAX + UINT32_MAX + UINT32_MAX * UINT32_MAX == UINT64_MAX
-if (side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < system_id_size + data_size + num_key_ids * key_id_size)
-return NULL;
+system_id_size = AV_RB32(side_data);
+num_key_ids = AV_RB32(side_data + 4);
+key_id_size = AV_RB32(side_data + 8);
+data_size = AV_RB32(side_data + 12);
 
-info = av_encryption_init_info_alloc(system_id_size, num_key_ids, key_id_size, data_size);
-if (!info)
-return NULL;
+// UINT32_MAX + UINT32_MAX + UINT32_MAX * UINT32_MAX == UINT64_MAX
+if (side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < system_id_size + data_size + num_key_ids * key_id_size) {
+av_encryption_init_info_free(ret);
+return NULL;
+}
+side_data += FF_ENCRYPTION_INIT_INFO_EXTRA;
+side_data_size -= FF_ENCRYPTION_INIT_INFO_EXTRA;
 
-memcpy(info->system_id, side_data + 16, system_id_size);
-side_data += system_id_size + 16;
-for (i = 0; i < num_key_ids; i++) {
-  memcpy(info->key_ids[i], side_data, key_id_size);
-  side_data += key_id_size;
+info = av_encryption_init_info_alloc(system_id_size, num_key_ids, key_id_size, data_size);
+if (!info) {
+av_encryption_init_info_free(ret);
+return N

[FFmpeg-devel] [PATCH] libavutil/encryption_info: Add NULL checks.

2018-05-31 Thread Jacob Trimble
Found by Chrome's ClusterFuzz: http://crbug.com/846662.

Signed-off-by: Jacob Trimble 
---
 libavutil/encryption_info.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
index 20a752d6b4..a48ded922c 100644
--- a/libavutil/encryption_info.c
+++ b/libavutil/encryption_info.c
@@ -64,6 +64,8 @@ AVEncryptionInfo *av_encryption_info_clone(const 
AVEncryptionInfo *info)
 {
 AVEncryptionInfo *ret;
 
+if (!info)
+return NULL;
 ret = av_encryption_info_alloc(info->subsample_count, info->key_id_size, 
info->iv_size);
 if (!ret)
 return NULL;
@@ -127,7 +129,7 @@ uint8_t *av_encryption_info_add_side_data(const 
AVEncryptionInfo *info, size_t *
 uint8_t *buffer, *cur_buffer;
 uint32_t i;
 
-if (UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA < info->key_id_size ||
+if (!info || !size || UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA < 
info->key_id_size ||
 UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA - info->key_id_size < 
info->iv_size ||
 (UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA - info->key_id_size - 
info->iv_size) / 8 < info->subsample_count) {
 return NULL;
@@ -260,7 +262,8 @@ uint8_t *av_encryption_init_info_add_side_data(const 
AVEncryptionInitInfo *info,
 uint8_t *buffer, *cur_buffer;
 uint32_t i, max_size;
 
-if (UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA < info->system_id_size ||
+if (!info || !side_data_size ||
+UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA < info->system_id_size ||
 UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA - info->system_id_size < 
info->data_size) {
 return NULL;
 }
-- 
2.17.0.921.gf22659ad46-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] libavutil/encryption_info: Allow multiple init info.

2018-05-25 Thread Jacob Trimble
On Mon, May 21, 2018 at 9:25 AM, Jacob Trimble <modma...@google.com> wrote:
> On Mon, May 14, 2018 at 4:49 PM, Jacob Trimble <modma...@google.com> wrote:
>> On Tue, May 8, 2018 at 3:47 PM, Michael Niedermayer
>> <mich...@niedermayer.cc> wrote:
>>> On Mon, May 07, 2018 at 04:59:33PM -0700, Jacob Trimble wrote:
>>>> On Mon, May 7, 2018 at 3:18 PM, Michael Niedermayer
>>>> <mich...@niedermayer.cc> wrote:
>>>> > On Mon, Apr 23, 2018 at 11:03:57AM -0700, Jacob Trimble wrote:
>>>> >> While integrating my encryption info changes, I noticed a problem with
>>>> >> the init info structs.  I implemented them as side-data on the Stream.
>>>> >> But this means there can only be one per stream.  However, there can
>>>> >> be multiple 'pssh' atoms in a single stream (e.g. for key rotation or
>>>> >> multiple key systems). (sorry for not noticing sooner)
>>>> >>
>>>> >> Attached is a patch to fix this by making the init info a
>>>> >> singly-linked-list.  It is ABI compatible and is still easy to use and
>>>> >> understand.  The alternative would be to break ABI and have the
>>>> >> side-data methods return an array of pointers.  I could do that
>>>> >> instead if that is preferable.
>>>> >
>>>> >>  encryption_info.c |  154 
>>>> >> +++-------
>>>> >>  encryption_info.h |5 +
>>>> >>  2 files changed, 106 insertions(+), 53 deletions(-)
>>>> >> e5eecc73a6997bbd11541771372d38ea9c3972a7  
>>>> >> 0001-libavutil-encryption_info-Allow-multiple-init-info.patch
>>>> >> From bb941a77e882e93629d63d63059d0063b9519e29 Mon Sep 17 00:00:00 2001
>>>> >> From: Jacob Trimble <modma...@google.com>
>>>> >> Date: Mon, 23 Apr 2018 10:33:58 -0700
>>>> >> Subject: [PATCH] libavutil/encryption_info: Allow multiple init info.
>>>> >>
>>>> >> It is possible for there to be multiple encryption init info structure.
>>>> >> For example, to support multiple key systems or in key rotation.  This
>>>> >> changes the AVEncryptionInitInfo struct to be a linked list so there
>>>> >> can be multiple structs without breaking ABI.
>>>> >>
>>>> >> Signed-off-by: Jacob Trimble <modma...@google.com>
>>>> >> ---
>>>> >>  libavutil/encryption_info.c | 154 +++-
>>>> >>  libavutil/encryption_info.h |   5 ++
>>>> >>  2 files changed, 106 insertions(+), 53 deletions(-)
>>>> >>
>>>> >> diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
>>>> >> index 20a752d6b4..9935c10d74 100644
>>>> >> --- a/libavutil/encryption_info.c
>>>> >> +++ b/libavutil/encryption_info.c
>>>> >> @@ -160,13 +160,16 @@ uint8_t *av_encryption_info_add_side_data(const 
>>>> >> AVEncryptionInfo *info, size_t *
>>>> >>  }
>>>> >>
>>>> >>  // The format of the AVEncryptionInitInfo side data:
>>>> >> -// u32be system_id_size
>>>> >> -// u32be num_key_ids
>>>> >> -// u32be key_id_size
>>>> >> -// u32be data_size
>>>> >> -// u8[system_id_size] system_id
>>>> >> -// u8[key_id_size][num_key_id] key_ids
>>>> >> -// u8[data_size] data
>>>> >> +// u32be init_info_count
>>>> >> +// {
>>>> >> +//   u32be system_id_size
>>>> >> +//   u32be num_key_ids
>>>> >> +//   u32be key_id_size
>>>> >> +//   u32be data_size
>>>> >> +//   u8[system_id_size] system_id
>>>> >> +//   u8[key_id_size][num_key_id] key_ids
>>>> >> +//   u8[data_size] data
>>>> >> +// }[init_info_count]
>>>> >>
>>>> >>  #define FF_ENCRYPTION_INIT_INFO_EXTRA 16
>>>> >>
>>>> >> @@ -215,6 +218,7 @@ void 
>>>> >> av_encryption_init_info_free(AVEncryptionInitInfo *info)
>>>> >>  for (i = 0; i < info->num_key_ids; i++) {
>>>> >>  av_free(info->key_ids[i]);
>>>> >>  }
>>>> >> +av_encryption_init_inf

Re: [FFmpeg-devel] libavutil/encryption_info: Allow multiple init info.

2018-05-21 Thread Jacob Trimble
On Mon, May 14, 2018 at 4:49 PM, Jacob Trimble <modma...@google.com> wrote:
> On Tue, May 8, 2018 at 3:47 PM, Michael Niedermayer
> <mich...@niedermayer.cc> wrote:
>> On Mon, May 07, 2018 at 04:59:33PM -0700, Jacob Trimble wrote:
>>> On Mon, May 7, 2018 at 3:18 PM, Michael Niedermayer
>>> <mich...@niedermayer.cc> wrote:
>>> > On Mon, Apr 23, 2018 at 11:03:57AM -0700, Jacob Trimble wrote:
>>> >> While integrating my encryption info changes, I noticed a problem with
>>> >> the init info structs.  I implemented them as side-data on the Stream.
>>> >> But this means there can only be one per stream.  However, there can
>>> >> be multiple 'pssh' atoms in a single stream (e.g. for key rotation or
>>> >> multiple key systems). (sorry for not noticing sooner)
>>> >>
>>> >> Attached is a patch to fix this by making the init info a
>>> >> singly-linked-list.  It is ABI compatible and is still easy to use and
>>> >> understand.  The alternative would be to break ABI and have the
>>> >> side-data methods return an array of pointers.  I could do that
>>> >> instead if that is preferable.
>>> >
>>> >>  encryption_info.c |  154 
>>> >> +++---
>>> >>  encryption_info.h |    5 +
>>> >>  2 files changed, 106 insertions(+), 53 deletions(-)
>>> >> e5eecc73a6997bbd11541771372d38ea9c3972a7  
>>> >> 0001-libavutil-encryption_info-Allow-multiple-init-info.patch
>>> >> From bb941a77e882e93629d63d63059d0063b9519e29 Mon Sep 17 00:00:00 2001
>>> >> From: Jacob Trimble <modma...@google.com>
>>> >> Date: Mon, 23 Apr 2018 10:33:58 -0700
>>> >> Subject: [PATCH] libavutil/encryption_info: Allow multiple init info.
>>> >>
>>> >> It is possible for there to be multiple encryption init info structure.
>>> >> For example, to support multiple key systems or in key rotation.  This
>>> >> changes the AVEncryptionInitInfo struct to be a linked list so there
>>> >> can be multiple structs without breaking ABI.
>>> >>
>>> >> Signed-off-by: Jacob Trimble <modma...@google.com>
>>> >> ---
>>> >>  libavutil/encryption_info.c | 154 +++-
>>> >>  libavutil/encryption_info.h |   5 ++
>>> >>  2 files changed, 106 insertions(+), 53 deletions(-)
>>> >>
>>> >> diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
>>> >> index 20a752d6b4..9935c10d74 100644
>>> >> --- a/libavutil/encryption_info.c
>>> >> +++ b/libavutil/encryption_info.c
>>> >> @@ -160,13 +160,16 @@ uint8_t *av_encryption_info_add_side_data(const 
>>> >> AVEncryptionInfo *info, size_t *
>>> >>  }
>>> >>
>>> >>  // The format of the AVEncryptionInitInfo side data:
>>> >> -// u32be system_id_size
>>> >> -// u32be num_key_ids
>>> >> -// u32be key_id_size
>>> >> -// u32be data_size
>>> >> -// u8[system_id_size] system_id
>>> >> -// u8[key_id_size][num_key_id] key_ids
>>> >> -// u8[data_size] data
>>> >> +// u32be init_info_count
>>> >> +// {
>>> >> +//   u32be system_id_size
>>> >> +//   u32be num_key_ids
>>> >> +//   u32be key_id_size
>>> >> +//   u32be data_size
>>> >> +//   u8[system_id_size] system_id
>>> >> +//   u8[key_id_size][num_key_id] key_ids
>>> >> +//   u8[data_size] data
>>> >> +// }[init_info_count]
>>> >>
>>> >>  #define FF_ENCRYPTION_INIT_INFO_EXTRA 16
>>> >>
>>> >> @@ -215,6 +218,7 @@ void 
>>> >> av_encryption_init_info_free(AVEncryptionInitInfo *info)
>>> >>  for (i = 0; i < info->num_key_ids; i++) {
>>> >>  av_free(info->key_ids[i]);
>>> >>  }
>>> >> +av_encryption_init_info_free(info->next);
>>> >>  av_free(info->system_id);
>>> >>  av_free(info->key_ids);
>>> >>  av_free(info->data);
>>> >> @@ -225,71 +229,115 @@ void 
>>> >> av_encryption_init_info_free(AVEncryptionInitInfo *info)
>>> >>  AVEncryptionInitInfo *av_encryption_init_

Re: [FFmpeg-devel] [PATCH] add support for parsing pssh box

2018-05-17 Thread Jacob Trimble
On Wed, May 16, 2018 at 11:32 PM, Zewu Chen  wrote:
> Use structure AVEncryptionInitInfo to provide CENC initialization information
> for the application.
>
> Signed-off-by: Chen Zewu 
> ---
>  libavformat/isom.h |  1 +
>  libavformat/mov.c  | 64 
> ++
>  2 files changed, 65 insertions(+)
>
> diff --git a/libavformat/isom.h b/libavformat/isom.h
> index fb36112..f0f5b2c 100644
> --- a/libavformat/isom.h
> +++ b/libavformat/isom.h
> @@ -274,6 +274,7 @@ typedef struct MOVContext {
>  MOVFragmentIndex frag_index;
>  int atom_depth;
>  unsigned int aax_mode;  ///< 'aax' file has been detected
> +AVEncryptionInitInfo *cenc_init_info;
>  uint8_t file_key[20];
>  uint8_t file_iv[20];
>  void *activation_bytes;
> diff --git a/libavformat/mov.c b/libavformat/mov.c
> index 1975011..f87f10b 100644
> --- a/libavformat/mov.c
> +++ b/libavformat/mov.c
> @@ -6165,6 +6165,52 @@ static int mov_read_schm(MOVContext *c, AVIOContext 
> *pb, MOVAtom atom)
>  return 0;
>  }
>
> +static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
> +{
> +int i, err;
> +int64_t start_pos;
> +uint8_t version = 0;
> +uint32_t num_key_ids = 0;
> +uint32_t data_size = 0;
> +
> +if (c->fc->nb_streams < 1)
> +return AVERROR_INVALIDDATA;
> +
> +version = avio_r8(pb);
> +avio_skip(pb, 3); /* flags */
> +
> +start_pos = avio_tell(pb);
> +
> +avio_skip(pb, 16); /* system id */
> +
> +if (version > 0) {
> +num_key_ids = avio_rb32(pb);
> +avio_skip(pb, 16*num_key_ids); /* KIDs */
> +}
> +
> +data_size = avio_rb32(pb);
> +
> +if (c->cenc_init_info)
> +av_log(c->fc, AV_LOG_WARNING, "Duplicated PSSH atom\n");
> +av_free(c->cenc_init_info);
> +c->cenc_init_info = av_encryption_init_info_alloc(16, num_key_ids, 16, 
> data_size);
> +if (!c->cenc_init_info)
> +return AVERROR(ENOMEM);
> +
> +avio_seek(pb, start_pos, SEEK_SET);
> +avio_read(pb, c->cenc_init_info->system_id, 16);
> +
> +if (version > 0)
> +avio_skip(pb, 4); /*  kid_count */
> +for (i = 0; i < num_key_ids; i++)
> +avio_read(pb, c->cenc_init_info->key_ids[i], 16);
> +
> +avio_skip(pb, 4); /* data_size */
> +avio_read(pb, c->cenc_init_info->data, data_size);
> +
> +return err;
> +}
> +
>  static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
>  {
>  AVStream *st;
> @@ -6507,6 +6553,7 @@ static const MOVParseTableEntry 
> mov_default_parse_table[] = {
>  { MKTAG('s','a','i','z'), mov_read_saiz },
>  { MKTAG('s','a','i','o'), mov_read_saio },
>  { MKTAG('s','c','h','m'), mov_read_schm },
> +{ MKTAG('p','s','s','h'), mov_read_pssh },
>  { MKTAG('s','c','h','i'), mov_read_default },
>  { MKTAG('t','e','n','c'), mov_read_tenc },
>  { MKTAG('d','f','L','a'), mov_read_dfla },
> @@ -6982,6 +7029,7 @@ static int mov_read_close(AVFormatContext *s)
>  }
>  av_freep(>frag_index.item);
>
> +av_freep(>cenc_init_info);
>  av_freep(>aes_decrypt);
>  av_freep(>chapter_tracks);
>
> @@ -7263,6 +7311,22 @@ static int mov_read_header(AVFormatContext *s)
>
>  ff_rfps_calculate(s);
>
> +if (mov->cenc_init_info) {
> +for (i = 0; i < s->nb_streams; i++) {
> +AVStream *st = s->streams[i];
> +uint8_t *info;
> +size_t info_size;
> +
> +info = 
> av_encryption_init_info_add_side_data(mov->cenc_init_info, _size);
> +if (!info)
> +return AVERROR(ENOMEM);
> +
> +err = av_stream_add_side_data(st, 
> AV_PKT_DATA_ENCRYPTION_INIT_INFO, info, info_size);
> +if (err < 0)
> +break;
> +}
> +}
> +
>  for (i = 0; i < s->nb_streams; i++) {
>  AVStream *st = s->streams[i];
>  MOVStreamContext *sc = st->priv_data;
> --
> 1.9.1
>
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

MP4 can have multiple PSSH boxes in it, so this would depend on
http://ffmpeg.org/pipermail/ffmpeg-devel/2018-May/229665.html

I also have implemented this with multiple PSSH support as well as
exposing the AVEncryptionInfo, but I am waiting on that patch to be
merged.  I sent a first version that only supported one PSSH box in it
in January, with no movement on it.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] libavutil/encryption_info: Allow multiple init info.

2018-05-14 Thread Jacob Trimble
On Tue, May 8, 2018 at 3:47 PM, Michael Niedermayer
<mich...@niedermayer.cc> wrote:
> On Mon, May 07, 2018 at 04:59:33PM -0700, Jacob Trimble wrote:
>> On Mon, May 7, 2018 at 3:18 PM, Michael Niedermayer
>> <mich...@niedermayer.cc> wrote:
>> > On Mon, Apr 23, 2018 at 11:03:57AM -0700, Jacob Trimble wrote:
>> >> While integrating my encryption info changes, I noticed a problem with
>> >> the init info structs.  I implemented them as side-data on the Stream.
>> >> But this means there can only be one per stream.  However, there can
>> >> be multiple 'pssh' atoms in a single stream (e.g. for key rotation or
>> >> multiple key systems). (sorry for not noticing sooner)
>> >>
>> >> Attached is a patch to fix this by making the init info a
>> >> singly-linked-list.  It is ABI compatible and is still easy to use and
>> >> understand.  The alternative would be to break ABI and have the
>> >> side-data methods return an array of pointers.  I could do that
>> >> instead if that is preferable.
>> >
>> >>  encryption_info.c |  154 
>> >> +++---
>> >>  encryption_info.h |5 +
>> >>  2 files changed, 106 insertions(+), 53 deletions(-)
>> >> e5eecc73a6997bbd11541771372d38ea9c3972a7  
>> >> 0001-libavutil-encryption_info-Allow-multiple-init-info.patch
>> >> From bb941a77e882e93629d63d63059d0063b9519e29 Mon Sep 17 00:00:00 2001
>> >> From: Jacob Trimble <modma...@google.com>
>> >> Date: Mon, 23 Apr 2018 10:33:58 -0700
>> >> Subject: [PATCH] libavutil/encryption_info: Allow multiple init info.
>> >>
>> >> It is possible for there to be multiple encryption init info structure.
>> >> For example, to support multiple key systems or in key rotation.  This
>> >> changes the AVEncryptionInitInfo struct to be a linked list so there
>> >> can be multiple structs without breaking ABI.
>> >>
>> >> Signed-off-by: Jacob Trimble <modma...@google.com>
>> >> ---
>> >>  libavutil/encryption_info.c | 154 +++-
>> >>  libavutil/encryption_info.h |   5 ++
>> >>  2 files changed, 106 insertions(+), 53 deletions(-)
>> >>
>> >> diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
>> >> index 20a752d6b4..9935c10d74 100644
>> >> --- a/libavutil/encryption_info.c
>> >> +++ b/libavutil/encryption_info.c
>> >> @@ -160,13 +160,16 @@ uint8_t *av_encryption_info_add_side_data(const 
>> >> AVEncryptionInfo *info, size_t *
>> >>  }
>> >>
>> >>  // The format of the AVEncryptionInitInfo side data:
>> >> -// u32be system_id_size
>> >> -// u32be num_key_ids
>> >> -// u32be key_id_size
>> >> -// u32be data_size
>> >> -// u8[system_id_size] system_id
>> >> -// u8[key_id_size][num_key_id] key_ids
>> >> -// u8[data_size] data
>> >> +// u32be init_info_count
>> >> +// {
>> >> +//   u32be system_id_size
>> >> +//   u32be num_key_ids
>> >> +//   u32be key_id_size
>> >> +//   u32be data_size
>> >> +//   u8[system_id_size] system_id
>> >> +//   u8[key_id_size][num_key_id] key_ids
>> >> +//   u8[data_size] data
>> >> +// }[init_info_count]
>> >>
>> >>  #define FF_ENCRYPTION_INIT_INFO_EXTRA 16
>> >>
>> >> @@ -215,6 +218,7 @@ void 
>> >> av_encryption_init_info_free(AVEncryptionInitInfo *info)
>> >>  for (i = 0; i < info->num_key_ids; i++) {
>> >>  av_free(info->key_ids[i]);
>> >>  }
>> >> +av_encryption_init_info_free(info->next);
>> >>  av_free(info->system_id);
>> >>  av_free(info->key_ids);
>> >>  av_free(info->data);
>> >> @@ -225,71 +229,115 @@ void 
>> >> av_encryption_init_info_free(AVEncryptionInitInfo *info)
>> >>  AVEncryptionInitInfo *av_encryption_init_info_get_side_data(
>> >>  const uint8_t *side_data, size_t side_data_size)
>> >>  {
>> >> -AVEncryptionInitInfo *info;
>> >> +AVEncryptionInitInfo *ret = NULL, *info;
>> >>  uint64_t system_id_size, num_key_ids, key_id_size, data_size, i;
>> >> +uint64_t init_info_count;
>> >>
>> >>

Re: [FFmpeg-devel] libavutil/encryption_info: Allow multiple init info.

2018-05-07 Thread Jacob Trimble
On Mon, May 7, 2018 at 3:18 PM, Michael Niedermayer
<mich...@niedermayer.cc> wrote:
> On Mon, Apr 23, 2018 at 11:03:57AM -0700, Jacob Trimble wrote:
>> While integrating my encryption info changes, I noticed a problem with
>> the init info structs.  I implemented them as side-data on the Stream.
>> But this means there can only be one per stream.  However, there can
>> be multiple 'pssh' atoms in a single stream (e.g. for key rotation or
>> multiple key systems). (sorry for not noticing sooner)
>>
>> Attached is a patch to fix this by making the init info a
>> singly-linked-list.  It is ABI compatible and is still easy to use and
>> understand.  The alternative would be to break ABI and have the
>> side-data methods return an array of pointers.  I could do that
>> instead if that is preferable.
>
>>  encryption_info.c |  154 
>> +++---
>>  encryption_info.h |5 +
>>  2 files changed, 106 insertions(+), 53 deletions(-)
>> e5eecc73a6997bbd11541771372d38ea9c3972a7  
>> 0001-libavutil-encryption_info-Allow-multiple-init-info.patch
>> From bb941a77e882e93629d63d63059d0063b9519e29 Mon Sep 17 00:00:00 2001
>> From: Jacob Trimble <modma...@google.com>
>> Date: Mon, 23 Apr 2018 10:33:58 -0700
>> Subject: [PATCH] libavutil/encryption_info: Allow multiple init info.
>>
>> It is possible for there to be multiple encryption init info structure.
>> For example, to support multiple key systems or in key rotation.  This
>> changes the AVEncryptionInitInfo struct to be a linked list so there
>> can be multiple structs without breaking ABI.
>>
>> Signed-off-by: Jacob Trimble <modma...@google.com>
>> ---
>>  libavutil/encryption_info.c | 154 +++-
>>  libavutil/encryption_info.h |   5 ++
>>  2 files changed, 106 insertions(+), 53 deletions(-)
>>
>> diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
>> index 20a752d6b4..9935c10d74 100644
>> --- a/libavutil/encryption_info.c
>> +++ b/libavutil/encryption_info.c
>> @@ -160,13 +160,16 @@ uint8_t *av_encryption_info_add_side_data(const 
>> AVEncryptionInfo *info, size_t *
>>  }
>>
>>  // The format of the AVEncryptionInitInfo side data:
>> -// u32be system_id_size
>> -// u32be num_key_ids
>> -// u32be key_id_size
>> -// u32be data_size
>> -// u8[system_id_size] system_id
>> -// u8[key_id_size][num_key_id] key_ids
>> -// u8[data_size] data
>> +// u32be init_info_count
>> +// {
>> +//   u32be system_id_size
>> +//   u32be num_key_ids
>> +//   u32be key_id_size
>> +//   u32be data_size
>> +//   u8[system_id_size] system_id
>> +//   u8[key_id_size][num_key_id] key_ids
>> +//   u8[data_size] data
>> +// }[init_info_count]
>>
>>  #define FF_ENCRYPTION_INIT_INFO_EXTRA 16
>>
>> @@ -215,6 +218,7 @@ void av_encryption_init_info_free(AVEncryptionInitInfo 
>> *info)
>>  for (i = 0; i < info->num_key_ids; i++) {
>>  av_free(info->key_ids[i]);
>>  }
>> +av_encryption_init_info_free(info->next);
>>  av_free(info->system_id);
>>  av_free(info->key_ids);
>>  av_free(info->data);
>> @@ -225,71 +229,115 @@ void 
>> av_encryption_init_info_free(AVEncryptionInitInfo *info)
>>  AVEncryptionInitInfo *av_encryption_init_info_get_side_data(
>>  const uint8_t *side_data, size_t side_data_size)
>>  {
>> -AVEncryptionInitInfo *info;
>> +AVEncryptionInitInfo *ret = NULL, *info;
>>  uint64_t system_id_size, num_key_ids, key_id_size, data_size, i;
>> +uint64_t init_info_count;
>>
>> -if (!side_data || side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA)
>> -return NULL;
>> -
>> -system_id_size = AV_RB32(side_data);
> [...]
>> +init_info_count = AV_RB32(side_data);
>
> i may be missing something but this looks like the meaning of the first
> field changes, this thus doesnt look compatible to me

It changes the binary format of the side-data, but that was explicitly
not part of ABI.  The fields in the structs are unchanged.  This would
only cause a problem if the side data bytes were stored out-of-band
from a different version of FFmpeg.

>
> also indention is quite inconsistent in the new code

One of these days, I'll remember that this uses 4 spaces not 2.  Fixed.

>
> [...]
>
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> Many that live deserve death. And some that die deserve life. C

Re: [FFmpeg-devel] libavutil/encryption_info: Allow multiple init info.

2018-05-07 Thread Jacob Trimble
On Fri, Apr 27, 2018 at 5:30 PM, Jacob Trimble <modma...@google.com> wrote:
> On Fri, Apr 27, 2018 at 10:33 AM, Jacob Trimble <modma...@google.com> wrote:
>> On Mon, Apr 23, 2018 at 11:03 AM, Jacob Trimble <modma...@google.com> wrote:
>>> While integrating my encryption info changes, I noticed a problem with
>>> the init info structs.  I implemented them as side-data on the Stream.
>>> But this means there can only be one per stream.  However, there can
>>> be multiple 'pssh' atoms in a single stream (e.g. for key rotation or
>>> multiple key systems). (sorry for not noticing sooner)
>>>
>>> Attached is a patch to fix this by making the init info a
>>> singly-linked-list.  It is ABI compatible and is still easy to use and
>>> understand.  The alternative would be to break ABI and have the
>>> side-data methods return an array of pointers.  I could do that
>>> instead if that is preferable.
>>
>> Ping
>
> Noticed a bug, fixed.

Ping.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] libavutil/encryption_info: Allow multiple init info.

2018-04-27 Thread Jacob Trimble
On Fri, Apr 27, 2018 at 10:33 AM, Jacob Trimble <modma...@google.com> wrote:
> On Mon, Apr 23, 2018 at 11:03 AM, Jacob Trimble <modma...@google.com> wrote:
>> While integrating my encryption info changes, I noticed a problem with
>> the init info structs.  I implemented them as side-data on the Stream.
>> But this means there can only be one per stream.  However, there can
>> be multiple 'pssh' atoms in a single stream (e.g. for key rotation or
>> multiple key systems). (sorry for not noticing sooner)
>>
>> Attached is a patch to fix this by making the init info a
>> singly-linked-list.  It is ABI compatible and is still easy to use and
>> understand.  The alternative would be to break ABI and have the
>> side-data methods return an array of pointers.  I could do that
>> instead if that is preferable.
>
> Ping

Noticed a bug, fixed.
From 50ec8ed80687134ecb9e74c45336e920d9e28666 Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modma...@google.com>
Date: Mon, 23 Apr 2018 10:33:58 -0700
Subject: [PATCH] libavutil/encryption_info: Allow multiple init info.

It is possible for there to be multiple encryption init info structure.
For example, to support multiple key systems or in key rotation.  This
changes the AVEncryptionInitInfo struct to be a linked list so there
can be multiple structs without breaking ABI.

Signed-off-by: Jacob Trimble <modma...@google.com>
---
 libavutil/encryption_info.c | 156 +++-
 libavutil/encryption_info.h |   5 ++
 2 files changed, 107 insertions(+), 54 deletions(-)

diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
index 20a752d6b4..2329d94f12 100644
--- a/libavutil/encryption_info.c
+++ b/libavutil/encryption_info.c
@@ -160,13 +160,16 @@ uint8_t *av_encryption_info_add_side_data(const AVEncryptionInfo *info, size_t *
 }
 
 // The format of the AVEncryptionInitInfo side data:
-// u32be system_id_size
-// u32be num_key_ids
-// u32be key_id_size
-// u32be data_size
-// u8[system_id_size] system_id
-// u8[key_id_size][num_key_id] key_ids
-// u8[data_size] data
+// u32be init_info_count
+// {
+//   u32be system_id_size
+//   u32be num_key_ids
+//   u32be key_id_size
+//   u32be data_size
+//   u8[system_id_size] system_id
+//   u8[key_id_size][num_key_id] key_ids
+//   u8[data_size] data
+// }[init_info_count]
 
 #define FF_ENCRYPTION_INIT_INFO_EXTRA 16
 
@@ -215,6 +218,7 @@ void av_encryption_init_info_free(AVEncryptionInitInfo *info)
 for (i = 0; i < info->num_key_ids; i++) {
 av_free(info->key_ids[i]);
 }
+av_encryption_init_info_free(info->next);
 av_free(info->system_id);
 av_free(info->key_ids);
 av_free(info->data);
@@ -225,71 +229,115 @@ void av_encryption_init_info_free(AVEncryptionInitInfo *info)
 AVEncryptionInitInfo *av_encryption_init_info_get_side_data(
 const uint8_t *side_data, size_t side_data_size)
 {
-AVEncryptionInitInfo *info;
-uint64_t system_id_size, num_key_ids, key_id_size, data_size, i;
-
-if (!side_data || side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA)
-return NULL;
-
-system_id_size = AV_RB32(side_data);
-num_key_ids = AV_RB32(side_data + 4);
-key_id_size = AV_RB32(side_data + 8);
-data_size = AV_RB32(side_data + 12);
-
-// UINT32_MAX + UINT32_MAX + UINT32_MAX * UINT32_MAX == UINT64_MAX
-if (side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < system_id_size + data_size + num_key_ids * key_id_size)
-return NULL;
+AVEncryptionInitInfo *ret = NULL, *info;
+uint64_t system_id_size, num_key_ids, key_id_size, data_size, i, j;
+uint64_t init_info_count;
 
-info = av_encryption_init_info_alloc(system_id_size, num_key_ids, key_id_size, data_size);
-if (!info)
+if (!side_data || side_data_size < 4)
 return NULL;
 
-memcpy(info->system_id, side_data + 16, system_id_size);
-side_data += system_id_size + 16;
-for (i = 0; i < num_key_ids; i++) {
-  memcpy(info->key_ids[i], side_data, key_id_size);
-  side_data += key_id_size;
+init_info_count = AV_RB32(side_data);
+side_data += 4;
+side_data_size -= 4;
+for (i = 0; i < init_info_count; i++) {
+  if (side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA) {
+  av_encryption_init_info_free(ret);
+  return NULL;
+  }
+
+  system_id_size = AV_RB32(side_data);
+  num_key_ids = AV_RB32(side_data + 4);
+  key_id_size = AV_RB32(side_data + 8);
+  data_size = AV_RB32(side_data + 12);
+
+  // UINT32_MAX + UINT32_MAX + UINT32_MAX * UINT32_MAX == UINT64_MAX
+  if (side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < system_id_size + data_size + num_key_ids * key_id_size) {
+  av_encryption_init_info_free(ret);
+  return NULL;
+  }
+  side_data += FF_ENCRYPTION_INIT_INFO_EXTRA;
+  side_data_size -= 

Re: [FFmpeg-devel] libavutil/encryption_info: Allow multiple init info.

2018-04-27 Thread Jacob Trimble
On Mon, Apr 23, 2018 at 11:03 AM, Jacob Trimble <modma...@google.com> wrote:
> While integrating my encryption info changes, I noticed a problem with
> the init info structs.  I implemented them as side-data on the Stream.
> But this means there can only be one per stream.  However, there can
> be multiple 'pssh' atoms in a single stream (e.g. for key rotation or
> multiple key systems). (sorry for not noticing sooner)
>
> Attached is a patch to fix this by making the init info a
> singly-linked-list.  It is ABI compatible and is still easy to use and
> understand.  The alternative would be to break ABI and have the
> side-data methods return an array of pointers.  I could do that
> instead if that is preferable.

Ping
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] libavutil/encryption_info: Allow multiple init info.

2018-04-23 Thread Jacob Trimble
While integrating my encryption info changes, I noticed a problem with
the init info structs.  I implemented them as side-data on the Stream.
But this means there can only be one per stream.  However, there can
be multiple 'pssh' atoms in a single stream (e.g. for key rotation or
multiple key systems). (sorry for not noticing sooner)

Attached is a patch to fix this by making the init info a
singly-linked-list.  It is ABI compatible and is still easy to use and
understand.  The alternative would be to break ABI and have the
side-data methods return an array of pointers.  I could do that
instead if that is preferable.
From bb941a77e882e93629d63d63059d0063b9519e29 Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modma...@google.com>
Date: Mon, 23 Apr 2018 10:33:58 -0700
Subject: [PATCH] libavutil/encryption_info: Allow multiple init info.

It is possible for there to be multiple encryption init info structure.
For example, to support multiple key systems or in key rotation.  This
changes the AVEncryptionInitInfo struct to be a linked list so there
can be multiple structs without breaking ABI.

Signed-off-by: Jacob Trimble <modma...@google.com>
---
 libavutil/encryption_info.c | 154 +++-
 libavutil/encryption_info.h |   5 ++
 2 files changed, 106 insertions(+), 53 deletions(-)

diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
index 20a752d6b4..9935c10d74 100644
--- a/libavutil/encryption_info.c
+++ b/libavutil/encryption_info.c
@@ -160,13 +160,16 @@ uint8_t *av_encryption_info_add_side_data(const AVEncryptionInfo *info, size_t *
 }
 
 // The format of the AVEncryptionInitInfo side data:
-// u32be system_id_size
-// u32be num_key_ids
-// u32be key_id_size
-// u32be data_size
-// u8[system_id_size] system_id
-// u8[key_id_size][num_key_id] key_ids
-// u8[data_size] data
+// u32be init_info_count
+// {
+//   u32be system_id_size
+//   u32be num_key_ids
+//   u32be key_id_size
+//   u32be data_size
+//   u8[system_id_size] system_id
+//   u8[key_id_size][num_key_id] key_ids
+//   u8[data_size] data
+// }[init_info_count]
 
 #define FF_ENCRYPTION_INIT_INFO_EXTRA 16
 
@@ -215,6 +218,7 @@ void av_encryption_init_info_free(AVEncryptionInitInfo *info)
 for (i = 0; i < info->num_key_ids; i++) {
 av_free(info->key_ids[i]);
 }
+av_encryption_init_info_free(info->next);
 av_free(info->system_id);
 av_free(info->key_ids);
 av_free(info->data);
@@ -225,71 +229,115 @@ void av_encryption_init_info_free(AVEncryptionInitInfo *info)
 AVEncryptionInitInfo *av_encryption_init_info_get_side_data(
 const uint8_t *side_data, size_t side_data_size)
 {
-AVEncryptionInitInfo *info;
+AVEncryptionInitInfo *ret = NULL, *info;
 uint64_t system_id_size, num_key_ids, key_id_size, data_size, i;
+uint64_t init_info_count;
 
-if (!side_data || side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA)
-return NULL;
-
-system_id_size = AV_RB32(side_data);
-num_key_ids = AV_RB32(side_data + 4);
-key_id_size = AV_RB32(side_data + 8);
-data_size = AV_RB32(side_data + 12);
-
-// UINT32_MAX + UINT32_MAX + UINT32_MAX * UINT32_MAX == UINT64_MAX
-if (side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < system_id_size + data_size + num_key_ids * key_id_size)
-return NULL;
-
-info = av_encryption_init_info_alloc(system_id_size, num_key_ids, key_id_size, data_size);
-if (!info)
+if (!side_data || side_data_size < 4)
 return NULL;
 
-memcpy(info->system_id, side_data + 16, system_id_size);
-side_data += system_id_size + 16;
-for (i = 0; i < num_key_ids; i++) {
-  memcpy(info->key_ids[i], side_data, key_id_size);
-  side_data += key_id_size;
+init_info_count = AV_RB32(side_data);
+side_data += 4;
+side_data_size -= 4;
+for (i = 0; i < init_info_count; i++) {
+  if (side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA) {
+  av_encryption_init_info_free(ret);
+  return NULL;
+  }
+
+  system_id_size = AV_RB32(side_data);
+  num_key_ids = AV_RB32(side_data + 4);
+  key_id_size = AV_RB32(side_data + 8);
+  data_size = AV_RB32(side_data + 12);
+
+  // UINT32_MAX + UINT32_MAX + UINT32_MAX * UINT32_MAX == UINT64_MAX
+  if (side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < system_id_size + data_size + num_key_ids * key_id_size) {
+  av_encryption_init_info_free(ret);
+  return NULL;
+  }
+  side_data += FF_ENCRYPTION_INIT_INFO_EXTRA;
+  side_data_size -= FF_ENCRYPTION_INIT_INFO_EXTRA;
+
+  info = av_encryption_init_info_alloc(system_id_size, num_key_ids, key_id_size, data_size);
+  if (!info) {
+  av_encryption_init_info_free(ret);
+  return NULL;
+  }
+  info->next = ret;
+  ret = info;
+
+  memcpy(info->system_id, side_data, system_id_size);
+  side_data += system_id_s

Re: [FFmpeg-devel] [PATCH 2/3] avformat/mov: Fix parsing of saio/siaz atoms in encrypted content.

2018-04-19 Thread Jacob Trimble
On Thu, Apr 19, 2018 at 2:07 AM, Michael Niedermayer
<mich...@niedermayer.cc> wrote:
> On Tue, Jan 09, 2018 at 10:27:28AM -0800, Jacob Trimble wrote:
>> On Mon, Jan 8, 2018 at 5:39 PM, Carl Eugen Hoyos <ceffm...@gmail.com> wrote:
>> > 2018-01-08 23:34 GMT+01:00 Jacob Trimble 
>> > <modmaker-at-google@ffmpeg.org>:
>> >> On Fri, Jan 5, 2018 at 3:41 PM, Carl Eugen Hoyos <ceffm...@gmail.com> 
>> >> wrote:
>> >>> 2018-01-05 23:58 GMT+01:00 Jacob Trimble 
>> >>> <modmaker-at-google@ffmpeg.org>:
>> >>>> On Fri, Jan 5, 2018 at 2:01 PM, Carl Eugen Hoyos <ceffm...@gmail.com> 
>> >>>> wrote:
>> >>>>> 2018-01-05 22:29 GMT+01:00 Jacob Trimble 
>> >>>>> <modmaker-at-google@ffmpeg.org>:
>> >>>>>> On Fri, Jan 5, 2018 at 12:41 PM, Carl Eugen Hoyos 
>> >>>>>> <ceffm...@gmail.com> wrote:
>> >>>>>>> 2018-01-05 20:49 GMT+01:00 Jacob Trimble 
>> >>>>>>> <modmaker-at-google@ffmpeg.org>:
>> >>>>>>>
>> >>>>>>>> +entry_count = avio_rb32(pb);
>> >>>>>>>> +encryption_index->auxiliary_offsets = 
>> >>>>>>>> av_malloc_array(sizeof(size_t), entry_count);
>> >>>>>>>
>> >>>>>>> (sizeof(variable) instead of sizeof(type), please.)
>> >>>>>>>
>> >>>>>>> But since this could be used for a dos attack, please change this
>> >>>>>>> to something similar to 1112ba01.
>> >>>>>>> If it is easy to avoid it, very short files should not allocate
>> >>>>>>> gigabytes.
>> >>>>>>
>> >>>>>> Switched to calculating the size based on the number of remaining
>> >>>>>> bytes and returning an error if it doesn't match what is read.
>> >>>>>
>> >>>>> Sorry if I miss something:
>> >>>>>
>> >>>>>> +entry_count = (atom.size - 8 - (has_saio_type ? 8 : 0)) / 
>> >>>>>> (version == 0 ? 4 : 8);
>> >>>>>> +if (avio_rb32(pb) != entry_count) {
>> >>>>>> +av_log(c->fc, AV_LOG_ERROR, "incorrect entry_count in 
>> >>>>>> saio\n");
>> >>>>>> +return AVERROR_INVALIDDATA;
>> >>>>>> +}
>> >>>>>> +encryption_index->auxiliary_offsets =
>> >>>>>> +
>> >>>>>> av_malloc_array(sizeof(*encryption_index->auxiliary_offsets), 
>> >>>>>> entry_count);
>> >>>>>
>> >>>>> Does this avoid a 1G allocation for a file of a few bytes?
>> >>>>>
>> >>>>> Didn't you simply increase the number of needed bytes to change in a 
>> >>>>> valid
>> >>>>> mov file to behave maliciously from one to two?
>> >>>>
>> >>>> From what I can tell, the mov_read_default method (which is what reads
>> >>>> child atoms) will verify "atom.size" to fit inside the parent atom.
>> >>>> This means that for "atom.size" to be excessively large for the file
>> >>>> size, the input would need to be non-seekable (since I think the
>> >>>> top-level atom uses the file size) and all the atoms would need to
>> >>>> have invalid sizes.
>> >>>
>> >>> (I did not check this but I am not convinced the sample I fixed last
>> >>> week is so sophisticated.)
>> >>>
>> >>>> But technically I guess it is possible.
>> >>>
>> >>> Thank you.
>> >>>
>> >>>> But this is basically malloc some number of bytes then read that many
>> >>>> bytes.  The only alternative I can think of (in the face of
>> >>>> non-seekable inputs) is to try-read in chunks until we hit EOF or the
>> >>>> end of the expected size.  This seems like a lot of extra work that is
>> >>>
>> >>>> not mirrored elsewhere.
>> >>>
>> >>> On the contrary.
>> >>>
>> >>> But you are right, I forgot to write that you have to add an "if (!eof)"

Re: [FFmpeg-devel] [PATCH 1/3] avformat/mov: Increase support for common encryption.

2018-04-19 Thread Jacob Trimble
On Thu, Apr 19, 2018 at 7:01 AM, James Almer <jamr...@gmail.com> wrote:
> On 4/18/2018 9:42 PM, Michael Niedermayer wrote:
>> On Wed, Apr 18, 2018 at 09:47:17AM -0700, Jacob Trimble wrote:
>>> On Tue, Apr 17, 2018 at 7:11 PM, Michael Niedermayer
>>> <mich...@niedermayer.cc> wrote:
>>>> On Tue, Apr 03, 2018 at 04:08:51PM -0700, Jacob Trimble wrote:
>>>>>>>
>>>>>>> Ping again.  I know this is low priority, but I would like to get
>>>>>>> these merged soon.
>>>>>>
>>>>>> Ping.  Despite being almost 2 months old, these patches still apply
>>>>>> cleanly.  Please take a look.  These have been in review for almost 3
>>>>>> months.
>>>>>
>>>>> Ping (going to keep pinging this until someone merges this or tells me
>>>>> why not).  Day after tomorrow this will be in review for 4 months!!!
>>>>>
>>>>> Also noticed a bug when integrating this, so here is an updated patch.
>>>>
>>>>>  libavformat/isom.h |   14 +
>>>>>  libavformat/mov.c  |  396 
>>>>> ++---
>>>>>  tests/fate/mov.mak |8
>>>>>  tests/ref/fate/mov-frag-encrypted  |   57 
>>>>>  tests/ref/fate/mov-tenc-only-encrypted |   57 
>>>>>  5 files changed, 450 insertions(+), 82 deletions(-)
>>>>> 9f1b7e04bc8001ad9faa59485090189f529cbf24  
>>>>> 0001-avformat-mov-Increase-support-for-v7.patch
>>>>> From 282effab6026341c49a52950cf8ba11afc9dc6aa Mon Sep 17 00:00:00 2001
>>>>> From: Jacob Trimble <modma...@google.com>
>>>>> Date: Wed, 6 Dec 2017 16:17:54 -0800
>>>>> Subject: [PATCH] avformat/mov: Increase support for common encryption.
>>>>
>>>> maybe iam missing something but applying this to master seems to cause
>>>> fate to fail
>>>>
>>>>
>>>> --- ./tests/ref/fate/mov-3elist-encrypted   2018-04-17 
>>>> 14:20:30.560366780 +0200
>>>> +++ tests/data/fate/mov-3elist-encrypted2018-04-18 
>>>> 03:53:32.872157901 +0200
>>>> @@ -1,57 +0,0 @@
>>>> -#format: frame checksums
>>>> -#version: 2
>>>> -#hash: MD5
>>>> -#tb 0: 1/24
>>>> -#media_type 0: video
>>>> -#codec_id 0: rawvideo
>>>> -#dimensions 0: 640x480
>>>> -#sar 0: 0/1
>>>> -#stream#, dts,pts, duration, size, hash
>>>> -0,  0,  0,1,   460800, 
>>>> 80fbbdec589e15e6c493b44d243f92a9
>>>> -0,  1,  1,1,   460800, 
>>>> f4b23293bb2ecf69cc3570853d8c56a1
>>>> -0,  2,  2,1,   460800, 
>>>> 0c03ce2c1c6ec405d7455465ecd559a3
>>>> -0,  3,  3,1,   460800, 
>>>> 7921791695537fba2c3c123da4834cb9
>>>> -0,  4,  4,1,   460800, 
>>>> 30c8e2903a561b84d4cbaf95c668d236
>>>> -0,  5,  5,1,   460800, 
>>>> 7ff42e998217c17592ddf6b584f26cef
>>>> -0,  6,  6,1,   460800, 
>>>> 5e402c48bf097db2d31b82bb4194a382
>>>> -0,  7,  7,1,   460800, 
>>>> 824c49e92c8ae6d99a0207b514dd756c
>>>> -0,  8,  8,1,   460800, 
>>>> 24f189216a1d9cf2313b2d6dbe3dbdd3
>>>> -0,  9,  9,1,   460800, 
>>>> 519179a8e74275d26b183374637e003f
>>>> -0, 10, 10,1,   460800, 
>>>> f18331ddcef0adf5b069bfa98baf8db4
>>>> -0, 11, 11,1,   460800, 
>>>> 081f61688690d47db5384e5d5a70
>>>> -0, 12, 12,1,   460800, 
>>>> 90dbf019b9035433371a8df41a9268b7
>>>> -0, 13, 13,1,   460800, 
>>>> bb5adfb9c66732898b34186eca1667ba
>>>> -0, 14, 14,1,   460800, 
>>>> cc08cfd64f37783ecddaf143f6ad78bc
>>>> -0, 15, 15,1,   460800, 
>>>> b8ae21d024fe4df903d56f4521993c72
>>>> -0, 16, 16,1,   460800, 
>>>> b45a99907f045dcadf0a2befc11555e3
>>>> -0, 17, 17,1,   460800, 
>>>> 603ba935845e65ab6cccbbec88bbf60d
>>>> -0, 

[FFmpeg-devel] [PATCH] avformat/mov: Fix memory leak in encryption info.

2018-04-19 Thread Jacob Trimble
Signed-off-by: Jacob Trimble <modma...@google.com>
---
 libavformat/mov.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index fc512b8d72..4eda48d617 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -5833,6 +5833,7 @@ static int mov_read_sample_encryption_info(MOVContext *c, 
AVIOContext *pb, MOVSt
 
 if (use_subsamples) {
 subsample_count = avio_rb16(pb);
+av_free((*sample)->subsamples);
 (*sample)->subsamples = av_mallocz_array(subsample_count, 
sizeof(*subsamples));
 if (!(*sample)->subsamples) {
 av_encryption_info_free(*sample);
-- 
2.17.0.484.g0c8726318c-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH 1/3] avformat/mov: Increase support for common encryption.

2018-04-18 Thread Jacob Trimble
On Tue, Apr 17, 2018 at 7:11 PM, Michael Niedermayer
<mich...@niedermayer.cc> wrote:
> On Tue, Apr 03, 2018 at 04:08:51PM -0700, Jacob Trimble wrote:
>> >>
>> >> Ping again.  I know this is low priority, but I would like to get
>> >> these merged soon.
>> >
>> > Ping.  Despite being almost 2 months old, these patches still apply
>> > cleanly.  Please take a look.  These have been in review for almost 3
>> > months.
>>
>> Ping (going to keep pinging this until someone merges this or tells me
>> why not).  Day after tomorrow this will be in review for 4 months!!!
>>
>> Also noticed a bug when integrating this, so here is an updated patch.
>
>>  libavformat/isom.h |   14 +
>>  libavformat/mov.c  |  396 
>> ++---
>>  tests/fate/mov.mak |8
>>  tests/ref/fate/mov-frag-encrypted  |   57 
>>  tests/ref/fate/mov-tenc-only-encrypted |   57 
>>  5 files changed, 450 insertions(+), 82 deletions(-)
>> 9f1b7e04bc8001ad9faa59485090189f529cbf24  
>> 0001-avformat-mov-Increase-support-for-v7.patch
>> From 282effab6026341c49a52950cf8ba11afc9dc6aa Mon Sep 17 00:00:00 2001
>> From: Jacob Trimble <modma...@google.com>
>> Date: Wed, 6 Dec 2017 16:17:54 -0800
>> Subject: [PATCH] avformat/mov: Increase support for common encryption.
>
> maybe iam missing something but applying this to master seems to cause
> fate to fail
>
>
> --- ./tests/ref/fate/mov-3elist-encrypted   2018-04-17 14:20:30.560366780 
> +0200
> +++ tests/data/fate/mov-3elist-encrypted2018-04-18 03:53:32.872157901 
> +0200
> @@ -1,57 +0,0 @@
> -#format: frame checksums
> -#version: 2
> -#hash: MD5
> -#tb 0: 1/24
> -#media_type 0: video
> -#codec_id 0: rawvideo
> -#dimensions 0: 640x480
> -#sar 0: 0/1
> -#stream#, dts,pts, duration, size, hash
> -0,  0,  0,1,   460800, 
> 80fbbdec589e15e6c493b44d243f92a9
> -0,  1,  1,1,   460800, 
> f4b23293bb2ecf69cc3570853d8c56a1
> -0,  2,  2,1,   460800, 
> 0c03ce2c1c6ec405d7455465ecd559a3
> -0,  3,  3,1,   460800, 
> 7921791695537fba2c3c123da4834cb9
> -0,  4,  4,1,   460800, 
> 30c8e2903a561b84d4cbaf95c668d236
> -0,  5,  5,1,   460800, 
> 7ff42e998217c17592ddf6b584f26cef
> -0,  6,  6,1,   460800, 
> 5e402c48bf097db2d31b82bb4194a382
> -0,  7,  7,1,   460800, 
> 824c49e92c8ae6d99a0207b514dd756c
> -0,  8,  8,1,   460800, 
> 24f189216a1d9cf2313b2d6dbe3dbdd3
> -0,  9,  9,1,   460800, 
> 519179a8e74275d26b183374637e003f
> -0, 10, 10,1,   460800, 
> f18331ddcef0adf5b069bfa98baf8db4
> -0, 11, 11,1,   460800, 
> 081f61688690d47db5384e5d5a70
> -0, 12, 12,1,   460800, 
> 90dbf019b9035433371a8df41a9268b7
> -0, 13, 13,1,   460800, 
> bb5adfb9c66732898b34186eca1667ba
> -0, 14, 14,1,   460800, 
> cc08cfd64f37783ecddaf143f6ad78bc
> -0, 15, 15,1,   460800, 
> b8ae21d024fe4df903d56f4521993c72
> -0, 16, 16,1,   460800, 
> b45a99907f045dcadf0a2befc11555e3
> -0, 17, 17,1,   460800, 
> 603ba935845e65ab6cccbbec88bbf60d
> -0, 18, 18,1,   460800, 
> df80c8d3e6a77258a306903f17995a18
> -0, 19, 19,1,   460800, 
> 4b7e90c0a5fd0e0cd958d47f0afac636
> -0, 20, 20,1,   460800, 
> 9feb6e36182f1745be6387edea240eb6
> -0, 21, 21,1,   460800, 
> 86e6de4bd0a5ff7558f4cf6c1ec3930d
> -0, 22, 22,1,   460800, 
> 726b69df77edbe7b503d4698656d1320
> -0, 23, 23,1,   460800, 
> d282fb7a953ac205b0a43d00c2d60a33
> -0, 24, 24,1,   460800, 
> eece3daa70cc20208dd75d91ac84c8fd
> -0, 25, 25,1,   460800, 
> c86d23e73bcce351fc315fb1f13348da
> -0, 26, 26,1,   460800, 
> 93497b4f7c5ad9d61212239b7c9d2770
> -0, 27, 27,1,   460800, 
> eb217d2c12de67903835a8c58f620488
> -0, 28, 28,1,   460800, 
> d966480867bb54c8cd044f18388ed486
> -0, 29, 29,1,   460800, 
> 3ea6207942b3181fdd8e8aa6cae1062a
> -0, 30, 30,1,   460800, 
> 2620df54aca086ec0fb9527c6e6f5135
> -0, 31, 31, 

[FFmpeg-devel] [PATCH] avformat/mov: Fix parsing of tfdt when using sample descriptors.

2018-04-04 Thread Jacob Trimble
Signed-off-by: Jacob Trimble <modma...@google.com>
---
 libavformat/mov.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index e7c32e6148..97b1462aab 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -4601,7 +4601,7 @@ static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
 return AVERROR_INVALIDDATA;
 }
 sc = st->priv_data;
-if (sc->pseudo_stream_id + 1 != frag->stsd_id)
+if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != 
-1)
 return 0;
 version = avio_r8(pb);
 avio_rb24(pb); /* flags */
-- 
2.17.0.484.g0c8726318c-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH 1/3] avformat/mov: Increase support for common encryption.

2018-04-03 Thread Jacob Trimble
>>
>> Ping again.  I know this is low priority, but I would like to get
>> these merged soon.
>
> Ping.  Despite being almost 2 months old, these patches still apply
> cleanly.  Please take a look.  These have been in review for almost 3
> months.

Ping (going to keep pinging this until someone merges this or tells me
why not).  Day after tomorrow this will be in review for 4 months!!!

Also noticed a bug when integrating this, so here is an updated patch.
From 282effab6026341c49a52950cf8ba11afc9dc6aa Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modma...@google.com>
Date: Wed, 6 Dec 2017 16:17:54 -0800
Subject: [PATCH] avformat/mov: Increase support for common encryption.

- Parse schm atom to get different encryption schemes.
- Allow senc atom to appear in track fragments.
- Allow 16-byte IVs.
- Allow constant IVs (specified in tenc).
- Allow only tenc to specify encryption (i.e. no senc/saiz/saio).
- Use sample descriptor to detect clear fragments.

This doesn't support:
- Different sample descriptor holding different encryption info.
  - Only first sample descriptor can be encrypted.
- Encrypted sample groups (i.e. seig).
- Non-'cenc' encryption scheme when using -decryption_key.

Signed-off-by: Jacob Trimble <modma...@google.com>
---
 libavformat/isom.h |  14 +
 libavformat/mov.c  | 396 -
 tests/fate/mov.mak |   8 +
 tests/ref/fate/mov-frag-encrypted  |  57 
 tests/ref/fate/mov-tenc-only-encrypted |  57 
 5 files changed, 450 insertions(+), 82 deletions(-)
 create mode 100644 tests/ref/fate/mov-frag-encrypted
 create mode 100644 tests/ref/fate/mov-tenc-only-encrypted

diff --git a/libavformat/isom.h b/libavformat/isom.h
index 4da34142f0..eb942cf882 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -27,6 +27,7 @@
 #include 
 #include 
 
+#include "libavutil/encryption_info.h"
 #include "libavutil/mastering_display_metadata.h"
 #include "libavutil/spherical.h"
 #include "libavutil/stereo3d.h"
@@ -108,12 +109,20 @@ typedef struct MOVSbgp {
 unsigned int index;
 } MOVSbgp;
 
+typedef struct MOVEncryptionIndex {
+// Individual encrypted samples.  If there are no elements, then the default
+// settings will be used.
+unsigned int nb_encrypted_samples;
+AVEncryptionInfo **encrypted_samples;
+} MOVEncryptionIndex;
+
 typedef struct MOVFragmentStreamInfo {
 int id;
 int64_t sidx_pts;
 int64_t first_tfra_pts;
 int64_t tfdt_dts;
 int index_entry;
+MOVEncryptionIndex *encryption_index;
 } MOVFragmentStreamInfo;
 
 typedef struct MOVFragmentIndexItem {
@@ -215,6 +224,7 @@ typedef struct MOVStreamContext {
 
 int has_sidx;  // If there is an sidx entry for this stream.
 struct {
+// TODO: Remove once old methods are removed from mov.c
 int use_subsamples;
 uint8_t* auxiliary_info;
 uint8_t* auxiliary_info_end;
@@ -223,7 +233,11 @@ typedef struct MOVStreamContext {
 uint8_t* auxiliary_info_sizes;
 size_t auxiliary_info_sizes_count;
 int64_t auxiliary_info_index;
+
 struct AVAESCTR* aes_ctr;
+unsigned int per_sample_iv_size;  // Either 0, 8, or 16.
+AVEncryptionInfo *default_encrypted_sample;
+MOVEncryptionIndex *encryption_index;
 } cenc;
 } MOVStreamContext;
 
diff --git a/libavformat/mov.c b/libavformat/mov.c
index e7c32e6148..8a83b0f805 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -1330,6 +1330,7 @@ static int update_frag_index(MOVContext *c, int64_t offset)
 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
 frag_stream_info[i].index_entry = -1;
+frag_stream_info[i].encryption_index = NULL;
 }
 
 if (index < c->frag_index.nb_items)
@@ -5755,57 +5756,250 @@ static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 return 0;
 }
 
+/**
+ * Gets the current encryption info and associated current stream context.  If
+ * we are parsing a track fragment, this will return the specific encryption
+ * info for this fragment; otherwise this will return the global encryption
+ * info for the current stream.
+ */
+static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
+{
+MOVFragmentStreamInfo *frag_stream_info;
+AVStream *st;
+int i;
+
+frag_stream_info = get_current_frag_stream_info(>frag_index);
+if (frag_stream_info) {
+for (i = 0; i < c->fc->nb_streams; i++) {
+if (c->fc->streams[i]->id == frag_stream_info->id) {
+  st = c->fc->streams[i];
+  break;
+}
+}
+if (i == c->fc->nb_streams)
+return 0;
+*sc = st->priv_data;
+
+if (!frag_stream_in

Re: [FFmpeg-devel] [PATCH 1/3] avformat/mov: Increase support for common encryption.

2018-03-22 Thread Jacob Trimble
On Mon, Mar 5, 2018 at 12:22 PM, Jacob Trimble <modma...@google.com> wrote:
> On Mon, Feb 12, 2018 at 9:35 AM, Jacob Trimble <modma...@google.com> wrote:
>> On Tue, Jan 30, 2018 at 11:27 AM, Jacob Trimble <modma...@google.com> wrote:
>>> On Wed, Jan 24, 2018 at 5:46 PM, Michael Niedermayer
>>> <mich...@niedermayer.cc> wrote:
>>>> On Wed, Jan 24, 2018 at 11:43:26AM -0800, Jacob Trimble wrote:
>>>>> On Mon, Jan 22, 2018 at 7:38 PM, Michael Niedermayer
>>>>> <mich...@niedermayer.cc> wrote
>>>>> > [...]
>>>>> >> This removes support for saio/saiz atoms, but it was incorrect before.
>>>>> >> A follow-up change will add correct support for those.
>>>>> >
>>>>> > This removal should be done by a seperate patch if it is done.
>>>>> > diff has matched up the removed function with a added one making this
>>>>> > hard to read as is
>>>>> >
>>>>>
>>>>> The problem is that the old code used the saiz atoms to parse the senc
>>>>> atom.  I split the patch up for readability, but the two patches need
>>>>> to be applied at the same time (or squashed) since the first breaks
>>>>> encrypted content.  But I can squash them again if it is preferable to
>>>>> not have a commit that intentionally breaks things.
>>>>
>>>> I didnt investigate this deeply so there is likely a better option that
>>>> i miss but you could just remove the functions which become unused in a
>>>> subsequent patch to prevent diff from messing the line matching up totally
>>>>
>>>
>>> Done.
>>>
>>>>
>>>>>
>>>>> >
>>>>> >>
>>>>> >> Signed-off-by: Jacob Trimble <modma...@google.com>
>>>>> >> ---
>>>>> >>  libavformat/isom.h |  20 +-
>>>>> >>  libavformat/mov.c  | 432 
>>>>> >> ++---
>>>>> >>  tests/fate/mov.mak |   8 +
>>>>> >>  tests/ref/fate/mov-frag-encrypted  |  57 +
>>>>> >>  tests/ref/fate/mov-tenc-only-encrypted |  57 +
>>>>> >>  5 files changed, 422 insertions(+), 152 deletions(-)
>>>>> >>  create mode 100644 tests/ref/fate/mov-frag-encrypted
>>>>> >>  create mode 100644 tests/ref/fate/mov-tenc-only-encrypted
>>>>> >
>>>>> > This depends on other patches you posted, this should be mentioned or
>>>>> > all patches should be in the same patchset in order
>>>>> >
>>>>>
>>>>> This depends on
>>>>> http://ffmpeg.org/pipermail/ffmpeg-devel/2018-January/223754.html and
>>>>> the recently pushed change to libavutil/aes_ctr.  Should I add
>>>>> something to the commit message or is that enough?
>>>>
>>>> If you post a new version, then there should be a mail or comment 
>>>> explaining
>>>> any dependancies on yet to be applied patches.
>>>> It should not be in the commit messages or commited changes ideally
>>>> This way people trying to test code dont need to guess what they need
>>>> to apply first before a patchset
>>>>
>>>>
>>>> [...]
>>>>> >> +static int get_current_encryption_info(MOVContext *c, 
>>>>> >> MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
>>>>> >>  {
>>>>> >> +MOVFragmentStreamInfo *frag_stream_info;
>>>>> >>  AVStream *st;
>>>>> >> -MOVStreamContext *sc;
>>>>> >> -size_t auxiliary_info_size;
>>>>> >> +int i;
>>>>> >>
>>>>> >> -if (c->decryption_key_len == 0 || c->fc->nb_streams < 1)
>>>>> >> -return 0;
>>>>> >> +frag_stream_info = get_current_frag_stream_info(>frag_index);
>>>>> >> +if (frag_stream_info) {
>>>>> >> +for (i = 0; i < c->fc->nb_streams; i++) {
>>>>> >> +if (c->fc->streams[i]->id == frag_stream_info->id) {
>>>>> >> +  st = c->fc->streams[i];
>>>>> >> +  break;

Re: [FFmpeg-devel] [PATCH 1/3] avformat/mov: Increase support for common encryption.

2018-03-05 Thread Jacob Trimble
On Mon, Feb 12, 2018 at 9:35 AM, Jacob Trimble <modma...@google.com> wrote:
> On Tue, Jan 30, 2018 at 11:27 AM, Jacob Trimble <modma...@google.com> wrote:
>> On Wed, Jan 24, 2018 at 5:46 PM, Michael Niedermayer
>> <mich...@niedermayer.cc> wrote:
>>> On Wed, Jan 24, 2018 at 11:43:26AM -0800, Jacob Trimble wrote:
>>>> On Mon, Jan 22, 2018 at 7:38 PM, Michael Niedermayer
>>>> <mich...@niedermayer.cc> wrote
>>>> > [...]
>>>> >> This removes support for saio/saiz atoms, but it was incorrect before.
>>>> >> A follow-up change will add correct support for those.
>>>> >
>>>> > This removal should be done by a seperate patch if it is done.
>>>> > diff has matched up the removed function with a added one making this
>>>> > hard to read as is
>>>> >
>>>>
>>>> The problem is that the old code used the saiz atoms to parse the senc
>>>> atom.  I split the patch up for readability, but the two patches need
>>>> to be applied at the same time (or squashed) since the first breaks
>>>> encrypted content.  But I can squash them again if it is preferable to
>>>> not have a commit that intentionally breaks things.
>>>
>>> I didnt investigate this deeply so there is likely a better option that
>>> i miss but you could just remove the functions which become unused in a
>>> subsequent patch to prevent diff from messing the line matching up totally
>>>
>>
>> Done.
>>
>>>
>>>>
>>>> >
>>>> >>
>>>> >> Signed-off-by: Jacob Trimble <modma...@google.com>
>>>> >> ---
>>>> >>  libavformat/isom.h |  20 +-
>>>> >>  libavformat/mov.c  | 432 
>>>> >> ++---
>>>> >>  tests/fate/mov.mak |   8 +
>>>> >>  tests/ref/fate/mov-frag-encrypted  |  57 +
>>>> >>  tests/ref/fate/mov-tenc-only-encrypted |  57 +
>>>> >>  5 files changed, 422 insertions(+), 152 deletions(-)
>>>> >>  create mode 100644 tests/ref/fate/mov-frag-encrypted
>>>> >>  create mode 100644 tests/ref/fate/mov-tenc-only-encrypted
>>>> >
>>>> > This depends on other patches you posted, this should be mentioned or
>>>> > all patches should be in the same patchset in order
>>>> >
>>>>
>>>> This depends on
>>>> http://ffmpeg.org/pipermail/ffmpeg-devel/2018-January/223754.html and
>>>> the recently pushed change to libavutil/aes_ctr.  Should I add
>>>> something to the commit message or is that enough?
>>>
>>> If you post a new version, then there should be a mail or comment explaining
>>> any dependancies on yet to be applied patches.
>>> It should not be in the commit messages or commited changes ideally
>>> This way people trying to test code dont need to guess what they need
>>> to apply first before a patchset
>>>
>>>
>>> [...]
>>>> >> +static int get_current_encryption_info(MOVContext *c, 
>>>> >> MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
>>>> >>  {
>>>> >> +MOVFragmentStreamInfo *frag_stream_info;
>>>> >>  AVStream *st;
>>>> >> -MOVStreamContext *sc;
>>>> >> -size_t auxiliary_info_size;
>>>> >> +int i;
>>>> >>
>>>> >> -if (c->decryption_key_len == 0 || c->fc->nb_streams < 1)
>>>> >> -return 0;
>>>> >> +frag_stream_info = get_current_frag_stream_info(>frag_index);
>>>> >> +if (frag_stream_info) {
>>>> >> +for (i = 0; i < c->fc->nb_streams; i++) {
>>>> >> +if (c->fc->streams[i]->id == frag_stream_info->id) {
>>>> >> +  st = c->fc->streams[i];
>>>> >> +  break;
>>>> >> +}
>>>> >> +}
>>>> >
>>>> > the indention is inconsistent here
>>>> >
>>>>
>>>> No it's not, it looks like it because the diff looks odd.  If you
>>>> apply the patch, the indentation in this method is consistent.
>>>
>>> Indention depth is 4 in mov*.c
>>> the hunk seems to add lines with a depth of 2
>>> I would be surprised if this is not in the file after applying the patch
>>>
>>> personally i dont care about the depth that much but i know many other 
>>> people
>>> care so this needs to be fixed before this can be applied
>>
>> Didn't see that.  Fixed and did a grep for incorrect indentations.
>>
>>>
>>> [...]
>>>
>>> --
>>> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>>>
>>> Let us carefully observe those good qualities wherein our enemies excel us
>>> and endeavor to excel them, by avoiding what is faulty, and imitating what
>>> is excellent in them. -- Plutarch
>>>
>>> ___
>>> ffmpeg-devel mailing list
>>> ffmpeg-devel@ffmpeg.org
>>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>>
>
> Ping.  This depends on
> http://ffmpeg.org/pipermail/ffmpeg-devel/2018-January/223754.html.

Ping again.  I know this is low priority, but I would like to get
these merged soon.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH 1/3] avformat/mov: Increase support for common encryption.

2018-02-12 Thread Jacob Trimble
On Tue, Jan 30, 2018 at 11:27 AM, Jacob Trimble <modma...@google.com> wrote:
> On Wed, Jan 24, 2018 at 5:46 PM, Michael Niedermayer
> <mich...@niedermayer.cc> wrote:
>> On Wed, Jan 24, 2018 at 11:43:26AM -0800, Jacob Trimble wrote:
>>> On Mon, Jan 22, 2018 at 7:38 PM, Michael Niedermayer
>>> <mich...@niedermayer.cc> wrote
>>> > [...]
>>> >> This removes support for saio/saiz atoms, but it was incorrect before.
>>> >> A follow-up change will add correct support for those.
>>> >
>>> > This removal should be done by a seperate patch if it is done.
>>> > diff has matched up the removed function with a added one making this
>>> > hard to read as is
>>> >
>>>
>>> The problem is that the old code used the saiz atoms to parse the senc
>>> atom.  I split the patch up for readability, but the two patches need
>>> to be applied at the same time (or squashed) since the first breaks
>>> encrypted content.  But I can squash them again if it is preferable to
>>> not have a commit that intentionally breaks things.
>>
>> I didnt investigate this deeply so there is likely a better option that
>> i miss but you could just remove the functions which become unused in a
>> subsequent patch to prevent diff from messing the line matching up totally
>>
>
> Done.
>
>>
>>>
>>> >
>>> >>
>>> >> Signed-off-by: Jacob Trimble <modma...@google.com>
>>> >> ---
>>> >>  libavformat/isom.h |  20 +-
>>> >>  libavformat/mov.c  | 432 
>>> >> ++---
>>> >>  tests/fate/mov.mak |   8 +
>>> >>  tests/ref/fate/mov-frag-encrypted  |  57 +
>>> >>  tests/ref/fate/mov-tenc-only-encrypted |  57 +
>>> >>  5 files changed, 422 insertions(+), 152 deletions(-)
>>> >>  create mode 100644 tests/ref/fate/mov-frag-encrypted
>>> >>  create mode 100644 tests/ref/fate/mov-tenc-only-encrypted
>>> >
>>> > This depends on other patches you posted, this should be mentioned or
>>> > all patches should be in the same patchset in order
>>> >
>>>
>>> This depends on
>>> http://ffmpeg.org/pipermail/ffmpeg-devel/2018-January/223754.html and
>>> the recently pushed change to libavutil/aes_ctr.  Should I add
>>> something to the commit message or is that enough?
>>
>> If you post a new version, then there should be a mail or comment explaining
>> any dependancies on yet to be applied patches.
>> It should not be in the commit messages or commited changes ideally
>> This way people trying to test code dont need to guess what they need
>> to apply first before a patchset
>>
>>
>> [...]
>>> >> +static int get_current_encryption_info(MOVContext *c, 
>>> >> MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
>>> >>  {
>>> >> +MOVFragmentStreamInfo *frag_stream_info;
>>> >>  AVStream *st;
>>> >> -MOVStreamContext *sc;
>>> >> -size_t auxiliary_info_size;
>>> >> +int i;
>>> >>
>>> >> -if (c->decryption_key_len == 0 || c->fc->nb_streams < 1)
>>> >> -return 0;
>>> >> +frag_stream_info = get_current_frag_stream_info(>frag_index);
>>> >> +if (frag_stream_info) {
>>> >> +for (i = 0; i < c->fc->nb_streams; i++) {
>>> >> +if (c->fc->streams[i]->id == frag_stream_info->id) {
>>> >> +  st = c->fc->streams[i];
>>> >> +  break;
>>> >> +}
>>> >> +}
>>> >
>>> > the indention is inconsistent here
>>> >
>>>
>>> No it's not, it looks like it because the diff looks odd.  If you
>>> apply the patch, the indentation in this method is consistent.
>>
>> Indention depth is 4 in mov*.c
>> the hunk seems to add lines with a depth of 2
>> I would be surprised if this is not in the file after applying the patch
>>
>> personally i dont care about the depth that much but i know many other people
>> care so this needs to be fixed before this can be applied
>
> Didn't see that.  Fixed and did a grep for incorrect indentations.
>
>>
>> [...]
>>
>> --
>> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>>
>> Let us carefully observe those good qualities wherein our enemies excel us
>> and endeavor to excel them, by avoiding what is faulty, and imitating what
>> is excellent in them. -- Plutarch
>>
>> ___
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>

Ping.  This depends on
http://ffmpeg.org/pipermail/ffmpeg-devel/2018-January/223754.html.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH 1/3] avformat/mov: Increase support for common encryption.

2018-01-30 Thread Jacob Trimble
On Wed, Jan 24, 2018 at 5:46 PM, Michael Niedermayer
<mich...@niedermayer.cc> wrote:
> On Wed, Jan 24, 2018 at 11:43:26AM -0800, Jacob Trimble wrote:
>> On Mon, Jan 22, 2018 at 7:38 PM, Michael Niedermayer
>> <mich...@niedermayer.cc> wrote
>> > [...]
>> >> This removes support for saio/saiz atoms, but it was incorrect before.
>> >> A follow-up change will add correct support for those.
>> >
>> > This removal should be done by a seperate patch if it is done.
>> > diff has matched up the removed function with a added one making this
>> > hard to read as is
>> >
>>
>> The problem is that the old code used the saiz atoms to parse the senc
>> atom.  I split the patch up for readability, but the two patches need
>> to be applied at the same time (or squashed) since the first breaks
>> encrypted content.  But I can squash them again if it is preferable to
>> not have a commit that intentionally breaks things.
>
> I didnt investigate this deeply so there is likely a better option that
> i miss but you could just remove the functions which become unused in a
> subsequent patch to prevent diff from messing the line matching up totally
>

Done.

>
>>
>> >
>> >>
>> >> Signed-off-by: Jacob Trimble <modma...@google.com>
>> >> ---
>> >>  libavformat/isom.h |  20 +-
>> >>  libavformat/mov.c  | 432 
>> >> ++---
>> >>  tests/fate/mov.mak |   8 +
>> >>  tests/ref/fate/mov-frag-encrypted  |  57 +
>> >>  tests/ref/fate/mov-tenc-only-encrypted |  57 +
>> >>  5 files changed, 422 insertions(+), 152 deletions(-)
>> >>  create mode 100644 tests/ref/fate/mov-frag-encrypted
>> >>  create mode 100644 tests/ref/fate/mov-tenc-only-encrypted
>> >
>> > This depends on other patches you posted, this should be mentioned or
>> > all patches should be in the same patchset in order
>> >
>>
>> This depends on
>> http://ffmpeg.org/pipermail/ffmpeg-devel/2018-January/223754.html and
>> the recently pushed change to libavutil/aes_ctr.  Should I add
>> something to the commit message or is that enough?
>
> If you post a new version, then there should be a mail or comment explaining
> any dependancies on yet to be applied patches.
> It should not be in the commit messages or commited changes ideally
> This way people trying to test code dont need to guess what they need
> to apply first before a patchset
>
>
> [...]
>> >> +static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex 
>> >> **encryption_index, MOVStreamContext **sc)
>> >>  {
>> >> +MOVFragmentStreamInfo *frag_stream_info;
>> >>  AVStream *st;
>> >> -MOVStreamContext *sc;
>> >> -size_t auxiliary_info_size;
>> >> +int i;
>> >>
>> >> -if (c->decryption_key_len == 0 || c->fc->nb_streams < 1)
>> >> -return 0;
>> >> +frag_stream_info = get_current_frag_stream_info(>frag_index);
>> >> +if (frag_stream_info) {
>> >> +for (i = 0; i < c->fc->nb_streams; i++) {
>> >> +if (c->fc->streams[i]->id == frag_stream_info->id) {
>> >> +  st = c->fc->streams[i];
>> >> +  break;
>> >> +}
>> >> +}
>> >
>> > the indention is inconsistent here
>> >
>>
>> No it's not, it looks like it because the diff looks odd.  If you
>> apply the patch, the indentation in this method is consistent.
>
> Indention depth is 4 in mov*.c
> the hunk seems to add lines with a depth of 2
> I would be surprised if this is not in the file after applying the patch
>
> personally i dont care about the depth that much but i know many other people
> care so this needs to be fixed before this can be applied

Didn't see that.  Fixed and did a grep for incorrect indentations.

>
> [...]
>
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> Let us carefully observe those good qualities wherein our enemies excel us
> and endeavor to excel them, by avoiding what is faulty, and imitating what
> is excellent in them. -- Plutarch
>
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
From 18807b5c77e65d

Re: [FFmpeg-devel] [PATCH 1/3] avformat/mov: Increase support for common encryption.

2018-01-24 Thread Jacob Trimble
On Mon, Jan 22, 2018 at 7:38 PM, Michael Niedermayer
<mich...@niedermayer.cc> wrote
> [...]
>> This removes support for saio/saiz atoms, but it was incorrect before.
>> A follow-up change will add correct support for those.
>
> This removal should be done by a seperate patch if it is done.
> diff has matched up the removed function with a added one making this
> hard to read as is
>

The problem is that the old code used the saiz atoms to parse the senc
atom.  I split the patch up for readability, but the two patches need
to be applied at the same time (or squashed) since the first breaks
encrypted content.  But I can squash them again if it is preferable to
not have a commit that intentionally breaks things.

>
>>
>> Signed-off-by: Jacob Trimble <modma...@google.com>
>> ---
>>  libavformat/isom.h |  20 +-
>>  libavformat/mov.c  | 432 
>> ++---
>>  tests/fate/mov.mak |   8 +
>>  tests/ref/fate/mov-frag-encrypted  |  57 +
>>  tests/ref/fate/mov-tenc-only-encrypted |  57 +
>>  5 files changed, 422 insertions(+), 152 deletions(-)
>>  create mode 100644 tests/ref/fate/mov-frag-encrypted
>>  create mode 100644 tests/ref/fate/mov-tenc-only-encrypted
>
> This depends on other patches you posted, this should be mentioned or
> all patches should be in the same patchset in order
>

This depends on
http://ffmpeg.org/pipermail/ffmpeg-devel/2018-January/223754.html and
the recently pushed change to libavutil/aes_ctr.  Should I add
something to the commit message or is that enough?

>
>>
>> diff --git a/libavformat/isom.h b/libavformat/isom.h
>> index 65676fb0f5..3794b1f0fd 100644
>> --- a/libavformat/isom.h
>> +++ b/libavformat/isom.h
>> @@ -27,6 +27,7 @@
>>  #include 
>>  #include 
>>
>> +#include "libavutil/encryption_info.h"
>>  #include "libavutil/mastering_display_metadata.h"
>>  #include "libavutil/spherical.h"
>>  #include "libavutil/stereo3d.h"
>> @@ -108,12 +109,20 @@ typedef struct MOVSbgp {
>>  unsigned int index;
>>  } MOVSbgp;
>>
>> +typedef struct MOVEncryptionIndex {
>> +// Individual encrypted samples.  If there are no elements, then the 
>> default
>> +// settings will be used.
>> +unsigned int nb_encrypted_samples;
>> +AVEncryptionInfo **encrypted_samples;
>> +} MOVEncryptionIndex;
>> +
>>  typedef struct MOVFragmentStreamInfo {
>>  int id;
>>  int64_t sidx_pts;
>>  int64_t first_tfra_pts;
>>  int64_t tfdt_dts;
>>  int index_entry;
>> +MOVEncryptionIndex *encryption_index;
>>  } MOVFragmentStreamInfo;
>>
>>  typedef struct MOVFragmentIndexItem {
>> @@ -214,15 +223,10 @@ typedef struct MOVStreamContext {
>>
>>  int has_sidx;  // If there is an sidx entry for this stream.
>>  struct {
>> -int use_subsamples;
>> -uint8_t* auxiliary_info;
>> -uint8_t* auxiliary_info_end;
>> -uint8_t* auxiliary_info_pos;
>> -uint8_t auxiliary_info_default_size;
>> -uint8_t* auxiliary_info_sizes;
>> -size_t auxiliary_info_sizes_count;
>> -int64_t auxiliary_info_index;
>>  struct AVAESCTR* aes_ctr;
>> +unsigned int per_sample_iv_size;  // Either 0, 8, or 16.
>> +AVEncryptionInfo *default_encrypted_sample;
>> +MOVEncryptionIndex *encryption_index;
>>  } cenc;
>>  } MOVStreamContext;
>>
>> diff --git a/libavformat/mov.c b/libavformat/mov.c
>> index 22faecfc17..37320af2f6 100644
>> --- a/libavformat/mov.c
>> +++ b/libavformat/mov.c
>> @@ -1324,6 +1324,7 @@ static int update_frag_index(MOVContext *c, int64_t 
>> offset)
>>  frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
>>  frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
>>  frag_stream_info[i].index_entry = -1;
>> +frag_stream_info[i].encryption_index = NULL;
>>  }
>>
>>  if (index < c->frag_index.nb_items)
>> @@ -5710,117 +5711,252 @@ static int mov_read_frma(MOVContext *c, 
>> AVIOContext *pb, MOVAtom atom)
>>  return 0;
>>  }
>>
>> -static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
>> +/**
>> + * Gets the current encryption info and associated current stream context.  
>> If
>> + * we are parsing a track fragment, this will return the specific encryption
>> + * info for this fragment; otherwise this will return the global 

Re: [FFmpeg-devel] [PATCH 1/3] avformat/mov: Increase support for common encryption.

2018-01-22 Thread Jacob Trimble
On Wed, Jan 10, 2018 at 5:08 PM, Jacob Trimble <modma...@google.com> wrote:
>
> On Wed, Jan 10, 2018 at 1:51 PM, Michael Niedermayer
> <mich...@niedermayer.cc> wrote:
> > [...]
> >
> > This causes a crash:
> >
> > =
> > ==4012==ERROR: AddressSanitizer: heap-buffer-overflow on address 
> > 0x6020eb78 at pc 0x00a944aa bp 0x7ffcd481ce70 sp 0x7ffcd481ce68
> > READ of size 8 at 0x6020eb78 thread T0
> > #0 0xa944a9 in mov_free_encryption_index 
> > ffmpeg/libavformat/mov.c:6615:20
> > #1 0xa6fb2b in mov_read_close ffmpeg/libavformat/mov.c:6693:13
> > #2 0xa6d96f in mov_read_header ffmpeg/libavformat/mov.c:6867:13
> > #3 0xc4a6ed in avformat_open_input ffmpeg/libavformat/utils.c:613:20
> > #4 0x4db356 in open_input_file ffmpeg/fftools/ffmpeg_opt.c:1069:11
> > #5 0x4da0e7 in open_files ffmpeg/fftools/ffmpeg_opt.c:3202:15
> > #6 0x4d9d98 in ffmpeg_parse_options ffmpeg/fftools/ffmpeg_opt.c:3242:11
> > #7 0x50e98c in main ffmpeg/fftools/ffmpeg.c:4813:11
> > #8 0x7f9cf833cf44 in __libc_start_main 
> > /build/eglibc-SvCtMH/eglibc-2.19/csu/libc-start.c:287
> > #9 0x420da5 in _start (ffmpeg/ffmpeg_g+0x420da5)
> >
> > 0x6020eb78 is located 4 bytes to the right of 4-byte region 
> > [0x6020eb70,0x6020eb74)
> > allocated by thread T0 here:
> > #0 0x4b126e in realloc (ffmpeg/ffmpeg_g+0x4b126e)
> > #1 0x218bbfe in av_strdup ffmpeg/libavutil/mem.c:256:15
> > #2 0x215eec1 in av_dict_set ffmpeg/libavutil/dict.c:87:22
> > #3 0x215f6e2 in av_dict_set_int ffmpeg/libavutil/dict.c:153:12
> > #4 0xa7644c in mov_read_ftyp ffmpeg/libavformat/mov.c:1109:5
> > #5 0xa6b153 in mov_read_default ffmpeg/libavformat/mov.c:6327:23
> > #6 0xa6c543 in mov_read_header ffmpeg/libavformat/mov.c:6865:20
> > #7 0xc4a6ed in avformat_open_input ffmpeg/libavformat/utils.c:613:20
> > #8 0x4db356 in open_input_file ffmpeg/fftools/ffmpeg_opt.c:1069:11
> > #9 0x4da0e7 in open_files ffmpeg/fftools/ffmpeg_opt.c:3202:15
> > #10 0x4d9d98 in ffmpeg_parse_options ffmpeg/fftools/ffmpeg_opt.c:3242:11
> > #11 0x50e98c in main ffmpeg/fftools/ffmpeg.c:4813:11
> > #12 0x7f9cf833cf44 in __libc_start_main 
> > /build/eglibc-SvCtMH/eglibc-2.19/csu/libc-start.c:287
> >
> > The input file should be here:
> > https://bugs.chromium.org/p/chromium/issues/attachment?aid=177545
>
> Fixed.
>
> >
> > [...]
> >
> > --
> > Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
> >
> > Many things microsoft did are stupid, but not doing something just because
> > microsoft did it is even more stupid. If everything ms did were stupid they
> > would be bankrupt already.
> >
> > ___
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >

Ping
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH 1/3] avformat/mov: Increase support for common encryption.

2018-01-10 Thread Jacob Trimble
On Wed, Jan 10, 2018 at 1:51 PM, Michael Niedermayer
<mich...@niedermayer.cc> wrote:
> [...]
>
> This causes a crash:
>
> =
> ==4012==ERROR: AddressSanitizer: heap-buffer-overflow on address 
> 0x6020eb78 at pc 0x00a944aa bp 0x7ffcd481ce70 sp 0x7ffcd481ce68
> READ of size 8 at 0x6020eb78 thread T0
> #0 0xa944a9 in mov_free_encryption_index ffmpeg/libavformat/mov.c:6615:20
> #1 0xa6fb2b in mov_read_close ffmpeg/libavformat/mov.c:6693:13
> #2 0xa6d96f in mov_read_header ffmpeg/libavformat/mov.c:6867:13
> #3 0xc4a6ed in avformat_open_input ffmpeg/libavformat/utils.c:613:20
> #4 0x4db356 in open_input_file ffmpeg/fftools/ffmpeg_opt.c:1069:11
> #5 0x4da0e7 in open_files ffmpeg/fftools/ffmpeg_opt.c:3202:15
> #6 0x4d9d98 in ffmpeg_parse_options ffmpeg/fftools/ffmpeg_opt.c:3242:11
> #7 0x50e98c in main ffmpeg/fftools/ffmpeg.c:4813:11
> #8 0x7f9cf833cf44 in __libc_start_main 
> /build/eglibc-SvCtMH/eglibc-2.19/csu/libc-start.c:287
> #9 0x420da5 in _start (ffmpeg/ffmpeg_g+0x420da5)
>
> 0x6020eb78 is located 4 bytes to the right of 4-byte region 
> [0x6020eb70,0x6020eb74)
> allocated by thread T0 here:
> #0 0x4b126e in realloc (ffmpeg/ffmpeg_g+0x4b126e)
> #1 0x218bbfe in av_strdup ffmpeg/libavutil/mem.c:256:15
> #2 0x215eec1 in av_dict_set ffmpeg/libavutil/dict.c:87:22
> #3 0x215f6e2 in av_dict_set_int ffmpeg/libavutil/dict.c:153:12
> #4 0xa7644c in mov_read_ftyp ffmpeg/libavformat/mov.c:1109:5
> #5 0xa6b153 in mov_read_default ffmpeg/libavformat/mov.c:6327:23
> #6 0xa6c543 in mov_read_header ffmpeg/libavformat/mov.c:6865:20
> #7 0xc4a6ed in avformat_open_input ffmpeg/libavformat/utils.c:613:20
> #8 0x4db356 in open_input_file ffmpeg/fftools/ffmpeg_opt.c:1069:11
> #9 0x4da0e7 in open_files ffmpeg/fftools/ffmpeg_opt.c:3202:15
> #10 0x4d9d98 in ffmpeg_parse_options ffmpeg/fftools/ffmpeg_opt.c:3242:11
> #11 0x50e98c in main ffmpeg/fftools/ffmpeg.c:4813:11
> #12 0x7f9cf833cf44 in __libc_start_main 
> /build/eglibc-SvCtMH/eglibc-2.19/csu/libc-start.c:287
>
> The input file should be here:
> https://bugs.chromium.org/p/chromium/issues/attachment?aid=177545

Fixed.

>
> [...]
>
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> Many things microsoft did are stupid, but not doing something just because
> microsoft did it is even more stupid. If everything ms did were stupid they
> would be bankrupt already.
>
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
From 5f6411a92569d13524485627fa68e62e8fd63e50 Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modma...@google.com>
Date: Wed, 6 Dec 2017 16:17:54 -0800
Subject: [PATCH] avformat/mov: Increase support for common encryption.

- Parse schm atom to get different encryption schemes.
- Allow senc atom to appear in track fragments.
- Allow 16-byte IVs.
- Allow constant IVs (specified in tenc).
- Allow only tenc to specify encryption (i.e. no senc/saiz/saio).
- Use sample descriptor to detect clear fragments.

This doesn't support:
- Different sample descriptor holding different encryption info.
  - Only first sample descriptor can be encrypted.
- Encrypted sample groups (i.e. seig).
- Non-'cenc' encryption scheme when using -decryption_key.

This removes support for saio/saiz atoms, but it was incorrect before.
A follow-up change will add correct support for those.

Signed-off-by: Jacob Trimble <modma...@google.com>
---
 libavformat/isom.h |  20 +-
 libavformat/mov.c  | 432 ++---
 tests/fate/mov.mak |   8 +
 tests/ref/fate/mov-frag-encrypted  |  57 +
 tests/ref/fate/mov-tenc-only-encrypted |  57 +
 5 files changed, 422 insertions(+), 152 deletions(-)
 create mode 100644 tests/ref/fate/mov-frag-encrypted
 create mode 100644 tests/ref/fate/mov-tenc-only-encrypted

diff --git a/libavformat/isom.h b/libavformat/isom.h
index 65676fb0f5..3794b1f0fd 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -27,6 +27,7 @@
 #include 
 #include 
 
+#include "libavutil/encryption_info.h"
 #include "libavutil/mastering_display_metadata.h"
 #include "libavutil/spherical.h"
 #include "libavutil/stereo3d.h"
@@ -108,12 +109,20 @@ typedef struct MOVSbgp {
 unsigned int index;
 } MOVSbgp;
 
+typedef struct MOVEncryptionIndex {
+// Individual encrypted samples.  If there are no elements, then the default
+// settings will be used.
+unsigned int nb_encrypted_samples;
+AVEncryptionInfo **encrypted_samples;
+} MOVEncryptionIndex;
+
 typedef stru

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

2018-01-09 Thread Jacob Trimble
On Mon, Jan 8, 2018 at 5:23 PM, Carl Eugen Hoyos <ceffm...@gmail.com> wrote:
> 2018-01-09 0:22 GMT+01:00 Jacob Trimble <modmaker-at-google@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, _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
From 92949de475a7fd1ede0959d452e3bf01b0a39b1f Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modma...@google.com>
Date: Wed, 6 Dec 2017 16:17:54 -0800
Subject: [PATCH 3/3] 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 <modma...@google.com>
---
 libavformat/mov.c | 95 +++
 1 file changed, 95 insertions(+)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index 750b8a0860..89cd550c12 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -6085,6 +6085,94 @@ 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);
+if (kid_count >= INT_MAX / sizeof(*key_ids))
+return AVERROR(ENOMEM);
+
+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, _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, _data);
+if (ret < 0)
+goto finish;
+
+av_freep(>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, _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;
@@ -6324,6 +6412,12 @@ static int cenc_filter(MOVContext *mov, MOVStreamContext *sc, AVPacket *pkt, int
 

Re: [FFmpeg-devel] [PATCH 2/3] avformat/mov: Fix parsing of saio/siaz atoms in encrypted content.

2018-01-09 Thread Jacob Trimble
On Mon, Jan 8, 2018 at 5:39 PM, Carl Eugen Hoyos <ceffm...@gmail.com> wrote:
> 2018-01-08 23:34 GMT+01:00 Jacob Trimble <modmaker-at-google@ffmpeg.org>:
>> On Fri, Jan 5, 2018 at 3:41 PM, Carl Eugen Hoyos <ceffm...@gmail.com> wrote:
>>> 2018-01-05 23:58 GMT+01:00 Jacob Trimble 
>>> <modmaker-at-google@ffmpeg.org>:
>>>> On Fri, Jan 5, 2018 at 2:01 PM, Carl Eugen Hoyos <ceffm...@gmail.com> 
>>>> wrote:
>>>>> 2018-01-05 22:29 GMT+01:00 Jacob Trimble 
>>>>> <modmaker-at-google@ffmpeg.org>:
>>>>>> On Fri, Jan 5, 2018 at 12:41 PM, Carl Eugen Hoyos <ceffm...@gmail.com> 
>>>>>> wrote:
>>>>>>> 2018-01-05 20:49 GMT+01:00 Jacob Trimble 
>>>>>>> <modmaker-at-google@ffmpeg.org>:
>>>>>>>
>>>>>>>> +entry_count = avio_rb32(pb);
>>>>>>>> +encryption_index->auxiliary_offsets = 
>>>>>>>> av_malloc_array(sizeof(size_t), entry_count);
>>>>>>>
>>>>>>> (sizeof(variable) instead of sizeof(type), please.)
>>>>>>>
>>>>>>> But since this could be used for a dos attack, please change this
>>>>>>> to something similar to 1112ba01.
>>>>>>> If it is easy to avoid it, very short files should not allocate
>>>>>>> gigabytes.
>>>>>>
>>>>>> Switched to calculating the size based on the number of remaining
>>>>>> bytes and returning an error if it doesn't match what is read.
>>>>>
>>>>> Sorry if I miss something:
>>>>>
>>>>>> +entry_count = (atom.size - 8 - (has_saio_type ? 8 : 0)) / (version 
>>>>>> == 0 ? 4 : 8);
>>>>>> +if (avio_rb32(pb) != entry_count) {
>>>>>> +av_log(c->fc, AV_LOG_ERROR, "incorrect entry_count in saio\n");
>>>>>> +return AVERROR_INVALIDDATA;
>>>>>> +}
>>>>>> +encryption_index->auxiliary_offsets =
>>>>>> +av_malloc_array(sizeof(*encryption_index->auxiliary_offsets), 
>>>>>> entry_count);
>>>>>
>>>>> Does this avoid a 1G allocation for a file of a few bytes?
>>>>>
>>>>> Didn't you simply increase the number of needed bytes to change in a valid
>>>>> mov file to behave maliciously from one to two?
>>>>
>>>> From what I can tell, the mov_read_default method (which is what reads
>>>> child atoms) will verify "atom.size" to fit inside the parent atom.
>>>> This means that for "atom.size" to be excessively large for the file
>>>> size, the input would need to be non-seekable (since I think the
>>>> top-level atom uses the file size) and all the atoms would need to
>>>> have invalid sizes.
>>>
>>> (I did not check this but I am not convinced the sample I fixed last
>>> week is so sophisticated.)
>>>
>>>> But technically I guess it is possible.
>>>
>>> Thank you.
>>>
>>>> But this is basically malloc some number of bytes then read that many
>>>> bytes.  The only alternative I can think of (in the face of
>>>> non-seekable inputs) is to try-read in chunks until we hit EOF or the
>>>> end of the expected size.  This seems like a lot of extra work that is
>>>
>>>> not mirrored elsewhere.
>>>
>>> On the contrary.
>>>
>>> But you are right, I forgot to write that you have to add an "if (!eof)"
>>> to the reading loops, see the function that above commit changed.
>>>
>>>> There are several cases where this isn't explicitly checked.
>>>
>>> Yes, and they will be fixed, please don't add another one.
>>>
>>>> Also, how does this attack work?  If the number is way too big, well
>>>> get EOM and error out.
>>>
>>> Which not only causes dos but also makes checking for other (if you
>>> like: more dangerous) issues more difficult which is bad. We already
>>> know that there are cases where the issue is hard to avoid, I believe
>>> this is not such a case.
>>>
>>> It is possible to create (valid) samples that allocate a huge amount
>>> of memory but very small files should not immediately allocate an
>>> amount of several G.
>>
>

Re: [FFmpeg-devel] [PATCH 1/3] avformat/mov: Increase support for common encryption.

2018-01-09 Thread Jacob Trimble
On Mon, Jan 8, 2018 at 5:19 PM, Carl Eugen Hoyos <ceffm...@gmail.com> wrote:
> 2018-01-08 23:16 GMT+01:00 Jacob Trimble <modmaker-at-google@ffmpeg.org>:
>>> You can't remove API just like that without a deprecation period.
>>> Add a new av_aes_ctr_set_full_iv() function, and either leave
>>> av_aes_ctr_set_iv() alone or deprecate it if it effectively becomes
>>> superfluous after adding the new function.
>>>
>>> Also, this patch needs to be split in three. One for the aes_crt
>>> changes, one for the encryption_info changes, and one for mov changes,
>>> with a minor libavutil version bump for the former two, and the
>>> corresponding APIChanges entry.
>>> Alternatively, you could also squash the new encryption_info API from
>>> this patch into the one that actually introduces the entire feature.
>>
>> Whoops, I thought that was internal-only.  Done and split into its own 
>> change.
>>
>> On Sat, Jan 6, 2018 at 7:30 AM, Carl Eugen Hoyos <ceffm...@gmail.com> wrote:
>>> 2018-01-05 20:49 GMT+01:00 Jacob Trimble 
>>> <modmaker-at-google@ffmpeg.org>:
>>>
>>>> +if (!frag_stream_info->encryption_index) {
>>>> +frag_stream_info->encryption_index = 
>>>> av_mallocz(sizeof(MOVEncryptionIndex));
>>>
>>> sizeof(variable), please.
>
> Do you disagree?
> I have no strong opinion, but I thought it makes the code more robust...

I did it most other places, but forgot it here.  Done.

>
>>> [...]
>>>
>>>> +sample_count = avio_rb32(pb);
>>>> +
>>>> +encryption_index->encrypted_samples =
>>>> av_mallocz_array(sizeof(AVEncryptionInfo*), sample_count);
>>>
>>> This should be avoided if possible, see below.
>>>
>>>> +if (!encryption_index->encrypted_samples) {
>>>>  return AVERROR(ENOMEM);
>>>>  }
>>>> +encryption_index->nb_encrypted_samples = sample_count;
>>>>
>>>> -return av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
>>>> +for (i = 0; i < sample_count; i++) {
>>>
>>> Please check here for eof...
>>>
>>>> +ret = mov_read_sample_encryption_info(c, pb, sc,
>>>> _index->encrypted_samples[i], use_subsamples);
>>>
>>> ... and insert a realloc here to avoid the large allocation above, see 
>>> 1112ba01.
>>
>> Done.
>
>> +if (use_subsamples) {
>> +subsample_count = avio_rb16(pb);
>> +for (i = 0; i < subsample_count && !pb->eof_reached; i++) {
>> +unsigned int min_subsamples = FFMIN(FFMAX(i, 1024 * 1024), 
>> subsample_count);
>> +subsamples = av_fast_realloc((*sample)->subsamples, _size,
>> + min_subsamples * 
>> sizeof(*subsamples));
>
> The reason I did not comment on this block in the last mail is that
> iiuc, the maximum allocation here is INT16_MAX * 8 which seems
> acceptable (and there cannot be a realloc with the chosen initial
> limit).

Ok, changed back.

>
>> +sample_count = avio_rb32(pb);
>
> You have to check here...
>
> +for (i = 0; i < sample_count && !pb->eof_reached; i++) {
> +unsigned int min_samples = FFMIN(FFMAX(i, 1024 * 1024), 
> sample_count);
> +encrypted_samples =
> av_fast_realloc(encryption_index->encrypted_samples, _size,
>
> +min_samples *
> sizeof(*encrypted_samples));
>
> ... if this product could overflow for the final reallocation, see 1112ba01.

Done

>
> Thank you, Carl Eugen
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
From e8261628e11347a8aa1b61de04c53cc1174cdae3 Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modma...@google.com>
Date: Wed, 6 Dec 2017 16:17:54 -0800
Subject: [PATCH 1/3] avformat/mov: Increase support for common encryption.

- Parse schm atom to get different encryption schemes.
- Allow senc atom to appear in track fragments.
- Allow 16-byte IVs.
- Allow constant IVs (specified in tenc).
- Allow only tenc to specify encryption (i.e. no senc/saiz/saio).
- Use sample descriptor to detect clear fragments.

This doesn't support:
- Different sample descriptor holding different encryption info.
  - Only first sample descriptor can be encrypted.
- Encrypted sample groups (i.e. seig).
- Non-'cenc' encryption scheme when using -decryption_key.

This

Re: [FFmpeg-devel] [RFC] avcodec/avcodec.h: Add encryption info side data

2018-01-08 Thread Jacob Trimble
On Mon, Jan 8, 2018 at 11:40 AM, Jacob Trimble <modma...@google.com> wrote:
>> I'd assume we'd wait with applying this until the mp4 patch that uses
>> it is reviewed. I'm fine with this patch and I think it can be pushed
>> as it is, although I just noticed an APIchanges entry and minor version
>> bump is actually missing. You could add them when sending the final
>> patch set.
>
> Added APIchanges entry and version bump.
>
>> The format of teh side data should be choosen so that demuxers and encoders
>> producing it can interoperate with muxers and decoders consuming it.
>
>> Please correct me if iam wrong but if some containers can store more than
>> others, then the "other" containers would not use that extra information nor
>> set it but it could still be using a compatible representation for 
>> interoperability
>
> Well I guess I can do the same thing for this as for the
> frame-specific encryption info.  There will be a user-friendly struct
> for accessing it and a binary format that will be stored in the side
> data.  This will allow different (de)muxers to use the data in a
> generic way.
>
>> These should be checked against size, making sure the data is consistent
>
> Done.  Also added addition overflow checking.
>
> On Fri, Jan 5, 2018 at 2:42 PM, James Almer <jamr...@gmail.com> wrote:
>> This being in libavutil, the two functions using AVPacket should be
>> changed to take and return a byte array instead, that the caller
>> manually either got from side data, or will afterwards adds as side data.
>
> Done.

Noticed some bugs when integrating with my other changes.
From 54f996fd8b8b8e44506739b58784e6038309 Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modma...@google.com>
Date: Tue, 5 Dec 2017 14:52:22 -0800
Subject: [PATCH] avcodec/avcodec.h: Add encryption info side data.

This new side-data will contain info on how a packet is encrypted.
This allows the app to handle packet decryption.

Signed-off-by: Jacob Trimble <modma...@google.com>
---
 doc/APIchanges  |   4 +
 libavcodec/avcodec.h|  13 ++
 libavutil/Makefile  |   2 +
 libavutil/encryption_info.c | 295 
 libavutil/encryption_info.h | 200 ++
 libavutil/version.h |   2 +-
 6 files changed, 515 insertions(+), 1 deletion(-)
 create mode 100644 libavutil/encryption_info.c
 create mode 100644 libavutil/encryption_info.h

diff --git a/doc/APIchanges b/doc/APIchanges
index d66c842521..b771031740 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -15,6 +15,10 @@ libavutil: 2017-10-21
 
 API changes, most recent first:
 
+2018-xx-xx - xxx - lavu 56.8.100 - encryption_info.h
+  Add AVEncryptionInitInfo and AVEncryptionInfo structures to hold new side-data
+  for encryption info.
+
 2018-01-xx - xxx - lavfi 7.11.101 - avfilter.h
   Deprecate avfilter_link_get_channels(). Use av_buffersink_get_channels().
 
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index c13deb599f..2e5d39eae3 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1341,6 +1341,19 @@ enum AVPacketSideDataType {
  */
 AV_PKT_DATA_A53_CC,
 
+/**
+ * This side data is encryption initialization data.
+ * The format is not part of ABI, use av_encryption_init_info_* methods to
+ * access.
+ */
+AV_PKT_DATA_ENCRYPTION_INIT_INFO,
+
+/**
+ * This side data contains encryption info for how to decrypt the packet.
+ * The format is not part of ABI, use av_encryption_info_* methods to access.
+ */
+AV_PKT_DATA_ENCRYPTION_INFO,
+
 /**
  * The number of side data types.
  * This is not part of the public API/ABI in the sense that it may
diff --git a/libavutil/Makefile b/libavutil/Makefile
index d7474f59e4..760fce3b30 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -24,6 +24,7 @@ HEADERS = adler32.h \
   dict.h\
   display.h \
   downmix_info.h\
+  encryption_info.h \
   error.h   \
   eval.h\
   fifo.h\
@@ -107,6 +108,7 @@ OBJS = adler32.o\
dict.o   \
display.o\
downmix_info.o  

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

2018-01-08 Thread Jacob Trimble
On Fri, Jan 5, 2018 at 12:55 PM, Jacob Trimble <modma...@google.com> wrote:
> On Fri, Jan 5, 2018 at 12:43 PM, Carl Eugen Hoyos <ceffm...@gmail.com> wrote:
>> 2018-01-05 20:49 GMT+01:00 Jacob Trimble <modmaker-at-google@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.
From da01baef5ead8194a991470de6b477ab59424617 Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modma...@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 <modma...@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, _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, _data);
+if (ret < 0)
+goto finish;
+
+av_freep(>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, _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

Re: [FFmpeg-devel] [PATCH 2/3] avformat/mov: Fix parsing of saio/siaz atoms in encrypted content.

2018-01-08 Thread Jacob Trimble
On Fri, Jan 5, 2018 at 3:41 PM, Carl Eugen Hoyos <ceffm...@gmail.com> wrote:
> 2018-01-05 23:58 GMT+01:00 Jacob Trimble <modmaker-at-google@ffmpeg.org>:
>> On Fri, Jan 5, 2018 at 2:01 PM, Carl Eugen Hoyos <ceffm...@gmail.com> wrote:
>>> 2018-01-05 22:29 GMT+01:00 Jacob Trimble 
>>> <modmaker-at-google@ffmpeg.org>:
>>>> On Fri, Jan 5, 2018 at 12:41 PM, Carl Eugen Hoyos <ceffm...@gmail.com> 
>>>> wrote:
>>>>> 2018-01-05 20:49 GMT+01:00 Jacob Trimble 
>>>>> <modmaker-at-google@ffmpeg.org>:
>>>>>
>>>>>> +entry_count = avio_rb32(pb);
>>>>>> +encryption_index->auxiliary_offsets = 
>>>>>> av_malloc_array(sizeof(size_t), entry_count);
>>>>>
>>>>> (sizeof(variable) instead of sizeof(type), please.)
>>>>>
>>>>> But since this could be used for a dos attack, please change this
>>>>> to something similar to 1112ba01.
>>>>> If it is easy to avoid it, very short files should not allocate
>>>>> gigabytes.
>>>>
>>>> Switched to calculating the size based on the number of remaining
>>>> bytes and returning an error if it doesn't match what is read.
>>>
>>> Sorry if I miss something:
>>>
>>>> +entry_count = (atom.size - 8 - (has_saio_type ? 8 : 0)) / (version == 
>>>> 0 ? 4 : 8);
>>>> +if (avio_rb32(pb) != entry_count) {
>>>> +av_log(c->fc, AV_LOG_ERROR, "incorrect entry_count in saio\n");
>>>> +return AVERROR_INVALIDDATA;
>>>> +}
>>>> +encryption_index->auxiliary_offsets =
>>>> +av_malloc_array(sizeof(*encryption_index->auxiliary_offsets), 
>>>> entry_count);
>>>
>>> Does this avoid a 1G allocation for a file of a few bytes?
>>>
>>> Didn't you simply increase the number of needed bytes to change in a valid
>>> mov file to behave maliciously from one to two?
>>
>> From what I can tell, the mov_read_default method (which is what reads
>> child atoms) will verify "atom.size" to fit inside the parent atom.
>> This means that for "atom.size" to be excessively large for the file
>> size, the input would need to be non-seekable (since I think the
>> top-level atom uses the file size) and all the atoms would need to
>> have invalid sizes.
>
> (I did not check this but I am not convinced the sample I fixed last
> week is so sophisticated.)
>
>> But technically I guess it is possible.
>
> Thank you.
>
>> But this is basically malloc some number of bytes then read that many
>> bytes.  The only alternative I can think of (in the face of
>> non-seekable inputs) is to try-read in chunks until we hit EOF or the
>> end of the expected size.  This seems like a lot of extra work that is
>
>> not mirrored elsewhere.
>
> On the contrary.
>
> But you are right, I forgot to write that you have to add an "if (!eof)"
> to the reading loops, see the function that above commit changed.
>
>> There are several cases where this isn't explicitly checked.
>
> Yes, and they will be fixed, please don't add another one.
>
>> Also, how does this attack work?  If the number is way too big, well
>> get EOM and error out.
>
> Which not only causes dos but also makes checking for other (if you
> like: more dangerous) issues more difficult which is bad. We already
> know that there are cases where the issue is hard to avoid, I believe
> this is not such a case.
>
> It is possible to create (valid) samples that allocate a huge amount
> of memory but very small files should not immediately allocate an
> amount of several G.

Done.

>
> Carl Eugen
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
From 524f81fd4b7ab31c576271f2747087bd16ca8734 Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modma...@google.com>
Date: Wed, 6 Dec 2017 16:17:54 -0800
Subject: [PATCH] avformat/mov: Fix parsing of saio/siaz atoms in encrypted
 content.

This doesn't support saio atoms with more than one offset.

Signed-off-by: Jacob Trimble <modma...@google.com>
---
 libavformat/isom.h |   6 ++
 libavformat/mov.c  | 232 +
 2 files changed, 238 insertions(+)

diff --git a/libavformat/isom.h b/libavformat/isom.h
index 3794b1f0fd..3de8053da2 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -114,6 +114,12 @@ typedef st

Re: [FFmpeg-devel] [PATCH 1/3] avformat/mov: Increase support for common encryption.

2018-01-08 Thread Jacob Trimble
> You can't remove API just like that without a deprecation period.
> Add a new av_aes_ctr_set_full_iv() function, and either leave
> av_aes_ctr_set_iv() alone or deprecate it if it effectively becomes
> superfluous after adding the new function.
>
> Also, this patch needs to be split in three. One for the aes_crt
> changes, one for the encryption_info changes, and one for mov changes,
> with a minor libavutil version bump for the former two, and the
> corresponding APIChanges entry.
> Alternatively, you could also squash the new encryption_info API from
> this patch into the one that actually introduces the entire feature.

Whoops, I thought that was internal-only.  Done and split into its own change.

On Sat, Jan 6, 2018 at 7:30 AM, Carl Eugen Hoyos <ceffm...@gmail.com> wrote:
> 2018-01-05 20:49 GMT+01:00 Jacob Trimble <modmaker-at-google@ffmpeg.org>:
>
>> +if (!frag_stream_info->encryption_index) {
>> +frag_stream_info->encryption_index = 
>> av_mallocz(sizeof(MOVEncryptionIndex));
>
> sizeof(variable), please.
>
> [...]
>
>> +sample_count = avio_rb32(pb);
>> +
>> +encryption_index->encrypted_samples = 
>> av_mallocz_array(sizeof(AVEncryptionInfo*), sample_count);
>
> This should be avoided if possible, see below.
>
>> +if (!encryption_index->encrypted_samples) {
>>  return AVERROR(ENOMEM);
>>  }
>> +encryption_index->nb_encrypted_samples = sample_count;
>>
>> -return av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
>> +for (i = 0; i < sample_count; i++) {
>
> Please check here for eof...
>
>> +ret = mov_read_sample_encryption_info(c, pb, sc, 
>> _index->encrypted_samples[i], use_subsamples);
>
> ... and insert a realloc here to avoid the large allocation above, see 
> 1112ba01.

Done.

>
> Thank you, Carl Eugen
> _______
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
From 0aafd18a05e23bdbe72529e2e1cd81fd98a4149a Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modma...@google.com>
Date: Wed, 6 Dec 2017 16:17:54 -0800
Subject: [PATCH] avformat/mov: Increase support for common encryption.

- Parse schm atom to get different encryption schemes.
- Allow senc atom to appear in track fragments.
- Allow 16-byte IVs.
- Allow constant IVs (specified in tenc).
- Allow only tenc to specify encryption (i.e. no senc/saiz/saio).
- Use sample descriptor to detect clear fragments.

This doesn't support:
- Different sample descriptor holding different encryption info.
  - Only first sample descriptor can be encrypted.
- Encrypted sample groups (i.e. seig).
- Non-'cenc' encryption scheme when using -decryption_key.

This removes support for saio/saiz atoms, but it was incorrect before.
A follow-up change will add correct support for those.

Signed-off-by: Jacob Trimble <modma...@google.com>
---
 libavformat/isom.h |  20 +-
 libavformat/mov.c  | 434 ++---
 tests/fate/mov.mak |   8 +
 tests/ref/fate/mov-frag-encrypted  |  57 +
 tests/ref/fate/mov-tenc-only-encrypted |  57 +
 5 files changed, 423 insertions(+), 153 deletions(-)
 create mode 100644 tests/ref/fate/mov-frag-encrypted
 create mode 100644 tests/ref/fate/mov-tenc-only-encrypted

diff --git a/libavformat/isom.h b/libavformat/isom.h
index 65676fb0f5..3794b1f0fd 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -27,6 +27,7 @@
 #include 
 #include 
 
+#include "libavutil/encryption_info.h"
 #include "libavutil/mastering_display_metadata.h"
 #include "libavutil/spherical.h"
 #include "libavutil/stereo3d.h"
@@ -108,12 +109,20 @@ typedef struct MOVSbgp {
 unsigned int index;
 } MOVSbgp;
 
+typedef struct MOVEncryptionIndex {
+// Individual encrypted samples.  If there are no elements, then the default
+// settings will be used.
+unsigned int nb_encrypted_samples;
+AVEncryptionInfo **encrypted_samples;
+} MOVEncryptionIndex;
+
 typedef struct MOVFragmentStreamInfo {
 int id;
 int64_t sidx_pts;
 int64_t first_tfra_pts;
 int64_t tfdt_dts;
 int index_entry;
+MOVEncryptionIndex *encryption_index;
 } MOVFragmentStreamInfo;
 
 typedef struct MOVFragmentIndexItem {
@@ -214,15 +223,10 @@ typedef struct MOVStreamContext {
 
 int has_sidx;  // If there is an sidx entry for this stream.
 struct {
-int use_subsamples;
-uint8_t* auxiliary_info;
-uint8_t* auxiliary_info_end;
-uint8_t* auxiliary_info_pos;
-uint8_t auxiliary_info_default_size;
-uint8_t* auxiliary_info_sizes;
-size_t auxiliary_info_sizes_count;
-int64

[FFmpeg-devel] [PATCH] avutil/aes_ctr: Add method to set 16-byte IV.

2018-01-08 Thread Jacob Trimble
Signed-off-by: Jacob Trimble <modma...@google.com>
---
 doc/APIchanges| 3 +++
 libavutil/aes_ctr.c   | 6 ++
 libavutil/aes_ctr.h   | 7 ++-
 libavutil/tests/aes_ctr.c | 2 +-
 libavutil/version.h   | 2 +-
 5 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index b771031740..4e07a806eb 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -15,6 +15,9 @@ libavutil: 2017-10-21
 
 API changes, most recent first:
 
+2018-xx-xx - xxx - lavu 56.9.100 - aes_ctr.h
+  Add method to set the 16-byte IV.
+
 2018-xx-xx - xxx - lavu 56.8.100 - encryption_info.h
   Add AVEncryptionInitInfo and AVEncryptionInfo structures to hold new 
side-data
   for encryption info.
diff --git a/libavutil/aes_ctr.c b/libavutil/aes_ctr.c
index e9c568fe0d..0c2e86785f 100644
--- a/libavutil/aes_ctr.c
+++ b/libavutil/aes_ctr.c
@@ -45,6 +45,12 @@ void av_aes_ctr_set_iv(struct AVAESCTR *a, const uint8_t* iv)
 a->block_offset = 0;
 }
 
+void av_aes_ctr_set_full_iv(struct AVAESCTR *a, const uint8_t* iv)
+{
+memcpy(a->counter, iv, sizeof(a->counter));
+a->block_offset = 0;
+}
+
 const uint8_t* av_aes_ctr_get_iv(struct AVAESCTR *a)
 {
 return a->counter;
diff --git a/libavutil/aes_ctr.h b/libavutil/aes_ctr.h
index f596fa6a46..e4aae126a7 100644
--- a/libavutil/aes_ctr.h
+++ b/libavutil/aes_ctr.h
@@ -67,10 +67,15 @@ const uint8_t* av_aes_ctr_get_iv(struct AVAESCTR *a);
 void av_aes_ctr_set_random_iv(struct AVAESCTR *a);
 
 /**
- * Forcefully change the iv
+ * Forcefully change the 8-byte iv
  */
 void av_aes_ctr_set_iv(struct AVAESCTR *a, const uint8_t* iv);
 
+/**
+ * Forcefully change the "full" 16-byte iv, including the counter
+ */
+void av_aes_ctr_set_full_iv(struct AVAESCTR *a, const uint8_t* iv);
+
 /**
  * Increment the top 64 bit of the iv (performed after each frame)
  */
diff --git a/libavutil/tests/aes_ctr.c b/libavutil/tests/aes_ctr.c
index c5ebeda7ac..00fdb05d13 100644
--- a/libavutil/tests/aes_ctr.c
+++ b/libavutil/tests/aes_ctr.c
@@ -45,7 +45,7 @@ int main (void)
 
 av_aes_ctr_set_random_iv(ae);
 iv =   av_aes_ctr_get_iv(ae);
-av_aes_ctr_set_iv(ad, iv);
+av_aes_ctr_set_full_iv(ad, iv);
 
 av_aes_ctr_crypt(ae, tmp, plain, sizeof(tmp));
 av_aes_ctr_crypt(ad, tmp, tmp,   sizeof(tmp));
diff --git a/libavutil/version.h b/libavutil/version.h
index d7398c41c5..0c032c8553 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@
  */
 
 #define LIBAVUTIL_VERSION_MAJOR  56
-#define LIBAVUTIL_VERSION_MINOR   8
+#define LIBAVUTIL_VERSION_MINOR   9
 #define LIBAVUTIL_VERSION_MICRO 100
 
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
-- 
2.16.0.rc0.223.g4a4ac83678-goog

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [RFC] avcodec/avcodec.h: Add encryption info side data

2018-01-08 Thread Jacob Trimble
> I'd assume we'd wait with applying this until the mp4 patch that uses
> it is reviewed. I'm fine with this patch and I think it can be pushed
> as it is, although I just noticed an APIchanges entry and minor version
> bump is actually missing. You could add them when sending the final
> patch set.

Added APIchanges entry and version bump.

> The format of teh side data should be choosen so that demuxers and encoders
> producing it can interoperate with muxers and decoders consuming it.

> Please correct me if iam wrong but if some containers can store more than
> others, then the "other" containers would not use that extra information nor
> set it but it could still be using a compatible representation for 
> interoperability

Well I guess I can do the same thing for this as for the
frame-specific encryption info.  There will be a user-friendly struct
for accessing it and a binary format that will be stored in the side
data.  This will allow different (de)muxers to use the data in a
generic way.

> These should be checked against size, making sure the data is consistent

Done.  Also added addition overflow checking.

On Fri, Jan 5, 2018 at 2:42 PM, James Almer <jamr...@gmail.com> wrote:
> This being in libavutil, the two functions using AVPacket should be
> changed to take and return a byte array instead, that the caller
> manually either got from side data, or will afterwards adds as side data.

Done.
From 332f20f951fc4db77a83f9dc60f75e84717b4fd0 Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modma...@google.com>
Date: Tue, 5 Dec 2017 14:52:22 -0800
Subject: [PATCH] avcodec/avcodec.h: Add encryption info side data.

This new side-data will contain info on how a packet is encrypted.
This allows the app to handle packet decryption.

Signed-off-by: Jacob Trimble <modma...@google.com>
---
 doc/APIchanges  |   4 +
 libavcodec/avcodec.h|  13 ++
 libavutil/Makefile  |   2 +
 libavutil/encryption_info.c | 295 
 libavutil/encryption_info.h | 200 ++
 libavutil/version.h |   2 +-
 6 files changed, 515 insertions(+), 1 deletion(-)
 create mode 100644 libavutil/encryption_info.c
 create mode 100644 libavutil/encryption_info.h

diff --git a/doc/APIchanges b/doc/APIchanges
index d66c842521..b771031740 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -15,6 +15,10 @@ libavutil: 2017-10-21
 
 API changes, most recent first:
 
+2018-xx-xx - xxx - lavu 56.8.100 - encryption_info.h
+  Add AVEncryptionInitInfo and AVEncryptionInfo structures to hold new side-data
+  for encryption info.
+
 2018-01-xx - xxx - lavfi 7.11.101 - avfilter.h
   Deprecate avfilter_link_get_channels(). Use av_buffersink_get_channels().
 
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index c13deb599f..cc74a9a740 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1341,6 +1341,19 @@ enum AVPacketSideDataType {
  */
 AV_PKT_DATA_A53_CC,
 
+/**
+ * This side data is encryption initialization data.
+ * The format is not part of ABI, use av_encryption_init_info_* methods to
+ * access.
+ */
+AV_PKT_DATA_ENCRYPTION_INIT_DATA,
+
+/**
+ * This side data contains encryption info for how to decrypt the packet.
+ * The format is not part of ABI, use av_encryption_info_* methods to access.
+ */
+AV_PKT_DATA_ENCRYPTION_INFO,
+
 /**
  * The number of side data types.
  * This is not part of the public API/ABI in the sense that it may
diff --git a/libavutil/Makefile b/libavutil/Makefile
index d7474f59e4..760fce3b30 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -24,6 +24,7 @@ HEADERS = adler32.h \
   dict.h\
   display.h \
   downmix_info.h\
+  encryption_info.h \
   error.h   \
   eval.h\
   fifo.h\
@@ -107,6 +108,7 @@ OBJS = adler32.o\
dict.o   \
display.o\
downmix_info.o   \
+   encryption_info.o\
error.o  \
eval.o   \
fifo.o   \
d

Re: [FFmpeg-devel] [PATCH 2/3] avformat/mov: Fix parsing of saio/siaz atoms in encrypted content.

2018-01-05 Thread Jacob Trimble
On Fri, Jan 5, 2018 at 2:01 PM, Carl Eugen Hoyos <ceffm...@gmail.com> wrote:
> 2018-01-05 22:29 GMT+01:00 Jacob Trimble <modmaker-at-google@ffmpeg.org>:
>> On Fri, Jan 5, 2018 at 12:41 PM, Carl Eugen Hoyos <ceffm...@gmail.com> wrote:
>>> 2018-01-05 20:49 GMT+01:00 Jacob Trimble 
>>> <modmaker-at-google@ffmpeg.org>:
>>>
>>>> +entry_count = avio_rb32(pb);
>>>> +encryption_index->auxiliary_offsets = av_malloc_array(sizeof(size_t), 
>>>> entry_count);
>>>
>>> (sizeof(variable) instead of sizeof(type), please.)
>>>
>>> But since this could be used for a dos attack, please change this
>>> to something similar to 1112ba01.
>>> If it is easy to avoid it, very short files should not allocate
>>> gigabytes.
>>
>> Switched to calculating the size based on the number of remaining
>> bytes and returning an error if it doesn't match what is read.
>
> Sorry if I miss something:
>
>> +entry_count = (atom.size - 8 - (has_saio_type ? 8 : 0)) / (version == 0 
>> ? 4 : 8);
>> +if (avio_rb32(pb) != entry_count) {
>> +av_log(c->fc, AV_LOG_ERROR, "incorrect entry_count in saio\n");
>> +return AVERROR_INVALIDDATA;
>> +}
>> +encryption_index->auxiliary_offsets =
>> +av_malloc_array(sizeof(*encryption_index->auxiliary_offsets), 
>> entry_count);
>
> Does this avoid a 1G allocation for a file of a few bytes?
>
> Didn't you simply increase the number of needed bytes to change in a valid
> mov file to behave maliciously from one to two?
>

From what I can tell, the mov_read_default method (which is what reads
child atoms) will verify "atom.size" to fit inside the parent atom.
This means that for "atom.size" to be excessively large for the file
size, the input would need to be non-seekable (since I think the
top-level atom uses the file size) and all the atoms would need to
have invalid sizes.  But technically I guess it is possible.

But this is basically malloc some number of bytes then read that many
bytes.  The only alternative I can think of (in the face of
non-seekable inputs) is to try-read in chunks until we hit EOF or the
end of the expected size.  This seems like a lot of extra work that is
not mirrored elsewhere.  There are several cases where this isn't
explicitly checked.

Also, how does this attack work?  If the number is way too big, well
get EOM and error out.  If it is large but there is enough memory,
we'll hit EOF and error out.  Would it be better to explicitly check
for EOF to avoid the loop running for longer than needed?  Or how
about freeing the memory on error so we don't keep the useless memory
around on the error case (even though the app will probably just free
the context anyway).

> Thank you, Carl Eugen
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH 2/3] avformat/mov: Fix parsing of saio/siaz atoms in encrypted content.

2018-01-05 Thread Jacob Trimble
On Fri, Jan 5, 2018 at 12:41 PM, Carl Eugen Hoyos <ceffm...@gmail.com> wrote:
> 2018-01-05 20:49 GMT+01:00 Jacob Trimble <modmaker-at-google@ffmpeg.org>:
>
>> +entry_count = avio_rb32(pb);
>> +encryption_index->auxiliary_offsets = av_malloc_array(sizeof(size_t), 
>> entry_count);
>
> (sizeof(variable) instead of sizeof(type), please.)
>
> But since this could be used for a dos attack, please change this
> to something similar to 1112ba01.
> If it is easy to avoid it, very short files should not allocate
> gigabytes.

Switched to calculating the size based on the number of remaining
bytes and returning an error if it doesn't match what is read.

>
> Carl Eugen
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
From 3c60b4bf10f8711a8db70bf74cc5e4b8ce3d50e0 Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modma...@google.com>
Date: Wed, 6 Dec 2017 16:17:54 -0800
Subject: [PATCH] avformat/mov: Fix parsing of saio/siaz atoms in encrypted
 content.

This doesn't support saio atoms with more than one offset.

Signed-off-by: Jacob Trimble <modma...@google.com>
---
 libavformat/isom.h |   6 ++
 libavformat/mov.c  | 186 +
 2 files changed, 192 insertions(+)

diff --git a/libavformat/isom.h b/libavformat/isom.h
index 3794b1f0fd..3de8053da2 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -114,6 +114,12 @@ typedef struct MOVEncryptionIndex {
 // settings will be used.
 unsigned int nb_encrypted_samples;
 AVEncryptionInfo **encrypted_samples;
+
+uint8_t* auxiliary_info_sizes;
+size_t auxiliary_info_sample_count;
+uint8_t auxiliary_info_default_size;
+size_t* auxiliary_offsets;  ///< Absolute seek position
+size_t auxiliary_offsets_count;
 } MOVEncryptionIndex;
 
 typedef struct MOVFragmentStreamInfo {
diff --git a/libavformat/mov.c b/libavformat/mov.c
index eb3fb71e2a..9ff4a809b7 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -5835,6 +5835,177 @@ static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 return 0;
 }
 
+static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
+{
+AVEncryptionInfo **sample;
+int64_t prev_pos;
+size_t sample_count, sample_info_size, i;
+int ret = 0;
+
+if (encryption_index->nb_encrypted_samples)
+return 0;
+sample_count = encryption_index->auxiliary_info_sample_count;
+if (encryption_index->auxiliary_offsets_count != 1) {
+av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
+return AVERROR_PATCHWELCOME;
+}
+
+encryption_index->encrypted_samples = av_mallocz_array(sizeof(AVEncryptionInfo*), sample_count);
+if (!encryption_index->encrypted_samples)
+return AVERROR(ENOMEM);
+encryption_index->nb_encrypted_samples = sample_count;
+
+prev_pos = avio_tell(pb);
+if (avio_seek(pb, encryption_index->auxiliary_offsets[0], SEEK_SET) != encryption_index->auxiliary_offsets[i]) {
+av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
+goto finish;
+}
+
+for (i = 0; i < sample_count; i++) {
+sample = _index->encrypted_samples[i];
+sample_info_size = encryption_index->auxiliary_info_default_size
+   ? encryption_index->auxiliary_info_default_size
+   : encryption_index->auxiliary_info_sizes[i];
+
+ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
+if (ret < 0)
+goto finish;
+}
+
+finish:
+avio_seek(pb, prev_pos, SEEK_SET);
+return ret;
+}
+
+static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+MOVEncryptionIndex *encryption_index;
+MOVStreamContext *sc;
+int ret;
+unsigned int sample_count, has_saiz_type;
+
+ret = get_current_encryption_info(c, _index, );
+if (ret != 1)
+  return ret;
+
+if (encryption_index->nb_encrypted_samples) {
+// This can happen if we have both saio/saiz and senc atoms.
+av_log(c->fc, AV_LOG_DEBUG, "ignoring duplicate encryption info in saiz\n");
+return 0;
+}
+
+if (encryption_index->auxiliary_info_sample_count) {
+av_log(c->fc, AV_LOG_ERROR, "duplicate saiz atom\n");
+return AVERROR_INVALIDDATA;
+}
+
+avio_r8(pb); /* version */
+has_saiz_type = avio_rb24(pb) & 0x01;  /* flags */
+if (has_saiz_type) {
+if (avio_rb32(pb) != sc->cenc.default_encrypted_sample->scheme) {
+av_log(c

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

2018-01-05 Thread Jacob Trimble
On Fri, Jan 5, 2018 at 12:43 PM, Carl Eugen Hoyos <ceffm...@gmail.com> wrote:
> 2018-01-05 20:49 GMT+01:00 Jacob Trimble <modmaker-at-google@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
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH 1/3] avformat/mov: Increase support for common encryption.

2018-01-05 Thread Jacob Trimble
On Fri, Jan 5, 2018 at 11:49 AM, Jacob Trimble <modma...@google.com> wrote:
>> [...]

This adds two new fate tests that need to be uploaded by someone:

https://storage.googleapis.com/shaka-demo-assets/_bugs/ffmpeg-fate-files/mov-frag-encrypted.mp4
https://storage.googleapis.com/shaka-demo-assets/_bugs/ffmpeg-fate-files/mov-tenc-only-encrypted.mp4
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 2/3] avformat/mov: Fix parsing of saio/siaz atoms in encrypted content.

2018-01-05 Thread Jacob Trimble
This doesn't support saio atoms with more than one offset.

Signed-off-by: Jacob Trimble <modma...@google.com>
---
 libavformat/isom.h |   6 ++
 libavformat/mov.c  | 174 +
 2 files changed, 180 insertions(+)

diff --git a/libavformat/isom.h b/libavformat/isom.h
index 3794b1f0fd..3de8053da2 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -114,6 +114,12 @@ typedef struct MOVEncryptionIndex {
 // settings will be used.
 unsigned int nb_encrypted_samples;
 AVEncryptionInfo **encrypted_samples;
+
+uint8_t* auxiliary_info_sizes;
+size_t auxiliary_info_sample_count;
+uint8_t auxiliary_info_default_size;
+size_t* auxiliary_offsets;  ///< Absolute seek position
+size_t auxiliary_offsets_count;
 } MOVEncryptionIndex;
 
 typedef struct MOVFragmentStreamInfo {
diff --git a/libavformat/mov.c b/libavformat/mov.c
index eb3fb71e2a..554b2be8bd 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -5835,6 +5835,165 @@ static int mov_read_senc(MOVContext *c, AVIOContext 
*pb, MOVAtom atom)
 return 0;
 }
 
+static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, 
AVIOContext *pb, MOVEncryptionIndex *encryption_index)
+{
+AVEncryptionInfo **sample;
+int64_t prev_pos;
+size_t sample_count, sample_info_size, i;
+int ret = 0;
+
+if (encryption_index->nb_encrypted_samples)
+return 0;
+sample_count = encryption_index->auxiliary_info_sample_count;
+if (encryption_index->auxiliary_offsets_count != 1) {
+av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not 
supported\n");
+return AVERROR_PATCHWELCOME;
+}
+
+encryption_index->encrypted_samples = 
av_mallocz_array(sizeof(AVEncryptionInfo*), sample_count);
+if (!encryption_index->encrypted_samples)
+return AVERROR(ENOMEM);
+encryption_index->nb_encrypted_samples = sample_count;
+
+prev_pos = avio_tell(pb);
+if (avio_seek(pb, encryption_index->auxiliary_offsets[0], SEEK_SET) != 
encryption_index->auxiliary_offsets[i]) {
+av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will 
only parse senc atoms for encryption info\n");
+goto finish;
+}
+
+for (i = 0; i < sample_count; i++) {
+sample = _index->encrypted_samples[i];
+sample_info_size = encryption_index->auxiliary_info_default_size
+   ? encryption_index->auxiliary_info_default_size
+   : encryption_index->auxiliary_info_sizes[i];
+
+ret = mov_read_sample_encryption_info(c, pb, sc, sample, 
sample_info_size > sc->cenc.per_sample_iv_size);
+if (ret < 0)
+goto finish;
+}
+
+finish:
+avio_seek(pb, prev_pos, SEEK_SET);
+return ret;
+}
+
+static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+MOVEncryptionIndex *encryption_index;
+MOVStreamContext *sc;
+int ret;
+unsigned int sample_count;
+
+ret = get_current_encryption_info(c, _index, );
+if (ret != 1)
+  return ret;
+
+if (encryption_index->nb_encrypted_samples) {
+// This can happen if we have both saio/saiz and senc atoms.
+av_log(c->fc, AV_LOG_DEBUG, "ignoring duplicate encryption info in 
saiz\n");
+return 0;
+}
+
+if (encryption_index->auxiliary_info_sample_count) {
+av_log(c->fc, AV_LOG_ERROR, "duplicate saiz atom\n");
+return AVERROR_INVALIDDATA;
+}
+
+avio_r8(pb); /* version */
+if (avio_rb24(pb) & 0x01) {  /* flags */
+if (avio_rb32(pb) != sc->cenc.default_encrypted_sample->scheme) {
+av_log(c->fc, AV_LOG_DEBUG, "ignoring saiz box with non-zero 
aux_info_type\n");
+return 0;
+}
+if (avio_rb32(pb) != 0) {
+av_log(c->fc, AV_LOG_DEBUG, "ignoring saiz box with non-zero 
aux_info_type_parameter\n");
+return 0;
+}
+}
+
+encryption_index->auxiliary_info_default_size = avio_r8(pb);
+sample_count = avio_rb32(pb);
+encryption_index->auxiliary_info_sample_count = sample_count;
+
+if (encryption_index->auxiliary_info_default_size == 0) {
+encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
+if (!encryption_index->auxiliary_info_sizes)
+return AVERROR(ENOMEM);
+if (avio_read(pb, encryption_index->auxiliary_info_sizes, 
sample_count) != sample_count) {
+av_log(c->fc, AV_LOG_ERROR, "failed to read the auxiliary info\n");
+return AVERROR_INVALIDDATA;
+}
+}
+
+if (encryption_index->auxiliary_offsets_count) {
+return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
+}
+
+return 0;
+}
+
+static int mov_read_saio(M

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

2018-01-05 Thread Jacob Trimble
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_INIT_DATA.

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

diff --git a/libavformat/mov.c b/libavformat/mov.c
index 554b2be8bd..abd59d8c7b 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -5994,6 +5994,32 @@ static int mov_read_saio(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
 return 0;
 }
 
+static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+AVStream *st;
+uint8_t* side_data;
+size_t size;
+
+if (c->fc->nb_streams < 1)
+return 0;
+st = c->fc->streams[c->fc->nb_streams-1];
+
+size = atom.size + 8;
+side_data = av_stream_new_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_DATA, 
size);
+if (!side_data) {
+return AVERROR(ENOMEM);
+}
+
+AV_WB32(side_data, size);
+AV_WL32(side_data + 4, MKTAG('p','s','s','h'));
+if (avio_read(pb, side_data + 8, atom.size) != atom.size) {
+av_log(c->fc, AV_LOG_ERROR, "failed to read the pssh atom\n");
+return AVERROR_INVALIDDATA;
+}
+
+return 0;
+}
+
 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 {
 AVStream *st;
@@ -6233,6 +6259,8 @@ 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 {
+return av_encryption_info_add_side_data(pkt, encrypted_sample);
 }
 }
 
@@ -6366,6 +6394,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

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 1/3] avformat/mov: Increase support for common encryption.

2018-01-05 Thread Jacob Trimble
- Parse schm atom to get different encryption schemes.
- Allow senc atom to appear in track fragments.
- Allow 16-byte IVs.
- Allow constant IVs (specified in tenc).
- Allow only tenc to specify encryption (i.e. no senc/saiz/saio).
- Use sample descriptor to detect clear fragments.

This doesn't support:
- Different sample descriptor holding different encryption info.
  - Only first sample descriptor can be encrypted.
- Encrypted sample groups (i.e. seig).
- Non-'cenc' encryption scheme when using -decryption_key.

This removes support for saio/saiz atoms, but it was incorrect before.
A follow-up change will add correct support for those.

Signed-off-by: Jacob Trimble <modma...@google.com>
---
 libavformat/isom.h |  20 +-
 libavformat/mov.c  | 404 +
 libavutil/aes_ctr.c|  11 +-
 libavutil/aes_ctr.h|   4 +-
 libavutil/encryption_info.c|  17 ++
 libavutil/encryption_info.h|   6 +
 libavutil/tests/aes_ctr.c  |   2 +-
 tests/fate/mov.mak |   8 +
 tests/ref/fate/mov-frag-encrypted  |  57 +
 tests/ref/fate/mov-tenc-only-encrypted |  57 +
 10 files changed, 426 insertions(+), 160 deletions(-)
 create mode 100644 tests/ref/fate/mov-frag-encrypted
 create mode 100644 tests/ref/fate/mov-tenc-only-encrypted

diff --git a/libavformat/isom.h b/libavformat/isom.h
index 65676fb0f5..3794b1f0fd 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -27,6 +27,7 @@
 #include 
 #include 
 
+#include "libavutil/encryption_info.h"
 #include "libavutil/mastering_display_metadata.h"
 #include "libavutil/spherical.h"
 #include "libavutil/stereo3d.h"
@@ -108,12 +109,20 @@ typedef struct MOVSbgp {
 unsigned int index;
 } MOVSbgp;
 
+typedef struct MOVEncryptionIndex {
+// Individual encrypted samples.  If there are no elements, then the 
default
+// settings will be used.
+unsigned int nb_encrypted_samples;
+AVEncryptionInfo **encrypted_samples;
+} MOVEncryptionIndex;
+
 typedef struct MOVFragmentStreamInfo {
 int id;
 int64_t sidx_pts;
 int64_t first_tfra_pts;
 int64_t tfdt_dts;
 int index_entry;
+MOVEncryptionIndex *encryption_index;
 } MOVFragmentStreamInfo;
 
 typedef struct MOVFragmentIndexItem {
@@ -214,15 +223,10 @@ typedef struct MOVStreamContext {
 
 int has_sidx;  // If there is an sidx entry for this stream.
 struct {
-int use_subsamples;
-uint8_t* auxiliary_info;
-uint8_t* auxiliary_info_end;
-uint8_t* auxiliary_info_pos;
-uint8_t auxiliary_info_default_size;
-uint8_t* auxiliary_info_sizes;
-size_t auxiliary_info_sizes_count;
-int64_t auxiliary_info_index;
 struct AVAESCTR* aes_ctr;
+unsigned int per_sample_iv_size;  // Either 0, 8, or 16.
+AVEncryptionInfo *default_encrypted_sample;
+MOVEncryptionIndex *encryption_index;
 } cenc;
 } MOVStreamContext;
 
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 22faecfc17..eb3fb71e2a 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -1324,6 +1324,7 @@ static int update_frag_index(MOVContext *c, int64_t 
offset)
 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
 frag_stream_info[i].index_entry = -1;
+frag_stream_info[i].encryption_index = NULL;
 }
 
 if (index < c->frag_index.nb_items)
@@ -5710,117 +5711,224 @@ static int mov_read_frma(MOVContext *c, AVIOContext 
*pb, MOVAtom atom)
 return 0;
 }
 
-static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+/**
+ * Gets the current encryption info and associated current stream context.  If
+ * we are parsing a track fragment, this will return the specific encryption
+ * info for this fragment; otherwise this will return the global encryption
+ * info for the current stream.
+ */
+static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex 
**encryption_index, MOVStreamContext **sc)
 {
+MOVFragmentStreamInfo *frag_stream_info;
 AVStream *st;
-MOVStreamContext *sc;
-size_t auxiliary_info_size;
+int i;
 
-if (c->decryption_key_len == 0 || c->fc->nb_streams < 1)
-return 0;
+frag_stream_info = get_current_frag_stream_info(>frag_index);
+if (frag_stream_info) {
+for (i = 0; i < c->fc->nb_streams; i++) {
+if (c->fc->streams[i]->id == frag_stream_info->id) {
+  st = c->fc->streams[i];
+  break;
+}
+}
+if (i == c->fc->nb_streams)
+return 0;
+*sc = st->priv_data;
 
-st = c->fc->streams[c->fc->nb_streams - 1];
-sc = st->priv_data;
+if (!frag_stream_info->encryption_index) {
+frag_stre

Re: [FFmpeg-devel] [RFC] avcodec/avcodec.h: Add encryption info side data

2018-01-05 Thread Jacob Trimble
On Tue, Jan 2, 2018 at 9:57 AM, Jacob Trimble <modma...@google.com> wrote:
> On Wed, Dec 20, 2017 at 4:31 PM, wm4 <nfx...@googlemail.com> wrote:
>> On Wed, 20 Dec 2017 15:10:43 -0800
>> Jacob Trimble <modmaker-at-google@ffmpeg.org> wrote:
>>
>>> From 1508d19e9f7acf43d76010ce54d59ff204613601 Mon Sep 17 00:00:00 2001
>>> From: Jacob Trimble <modma...@google.com>
>>> Date: Tue, 5 Dec 2017 14:52:22 -0800
>>> Subject: [PATCH] avcodec/avcodec.h: Add encryption info side data.
>>>
>>> This new side-data will contain info on how a packet is encrypted.
>>> This allows the app to handle packet decryption.
>>>
>>> Signed-off-by: Jacob Trimble <modma...@google.com>
>>> ---
>>
>> Looks generally good to me, a few minor cosmetic comments below.
>>
>>>  libavcodec/Makefile  |   2 +
>>>  libavcodec/avcodec.h |  13 
>>>  libavcodec/encryption_info.c | 139 
>>> +++
>>>  libavcodec/encryption_info.h | 121 +
>>>  4 files changed, 275 insertions(+)
>>>  create mode 100644 libavcodec/encryption_info.c
>>>  create mode 100644 libavcodec/encryption_info.h
>>>
>>> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
>>> index ab7893f560..11ad642c6c 100644
>>> --- a/libavcodec/Makefile
>>> +++ b/libavcodec/Makefile
>>> @@ -10,6 +10,7 @@ HEADERS = ac3_parser.h
>>>   \
>>>dirac.h   \
>>>dv_profile.h  \
>>>dxva2.h   \
>>> +  encryption_info.h \
>>>jni.h \
>>>mediacodec.h  \
>>>qsv.h \
>>> @@ -36,6 +37,7 @@ OBJS = ac3_parser.o   
>>>   \
>>> dirac.o  \
>>> dv_profile.o \
>>> encode.o \
>>> +   encryption_info.o\
>>> imgconvert.o \
>>> jni.o\
>>> mathtables.o \
>>> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
>>> index 5db6a81320..b43638ebc5 100644
>>> --- a/libavcodec/avcodec.h
>>> +++ b/libavcodec/avcodec.h
>>> @@ -1327,6 +1327,19 @@ enum AVPacketSideDataType {
>>>   */
>>>  AV_PKT_DATA_A53_CC,
>>>
>>> +/**
>>> + * This side data is encryption "initialization data".
>>> + * For MP4 this is the entire 'pssh' box.
>>> + * For WebM this is the key ID.
>>> + */
>>> +AV_PKT_DATA_ENCRYPTION_INIT_DATA,
>>> +
>>> +/**
>>> + * This side data contains encryption info for how to decrypt the 
>>> packet.
>>> + * The format is not part of ABI, use av_encryption_info_* methods to 
>>> access.
>>> + */
>>> +AV_PKT_DATA_ENCRYPTION_INFO,
>>> +
>>>  /**
>>>   * The number of side data types.
>>>   * This is not part of the public API/ABI in the sense that it may
>>> diff --git a/libavcodec/encryption_info.c b/libavcodec/encryption_info.c
>>> new file mode 100644
>>> index 00..59ee4c41a9
>>> --- /dev/null
>>> +++ b/libavcodec/encryption_info.c
>>> @@ -0,0 +1,139 @@
>>> +/**
>>> + * 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

Re: [FFmpeg-devel] [RFC] avcodec/avcodec.h: Add encryption info side data

2018-01-02 Thread Jacob Trimble
On Wed, Dec 20, 2017 at 4:31 PM, wm4 <nfx...@googlemail.com> wrote:
> On Wed, 20 Dec 2017 15:10:43 -0800
> Jacob Trimble <modmaker-at-google@ffmpeg.org> wrote:
>
>> From 1508d19e9f7acf43d76010ce54d59ff204613601 Mon Sep 17 00:00:00 2001
>> From: Jacob Trimble <modma...@google.com>
>> Date: Tue, 5 Dec 2017 14:52:22 -0800
>> Subject: [PATCH] avcodec/avcodec.h: Add encryption info side data.
>>
>> This new side-data will contain info on how a packet is encrypted.
>> This allows the app to handle packet decryption.
>>
>> Signed-off-by: Jacob Trimble <modma...@google.com>
>> ---
>
> Looks generally good to me, a few minor cosmetic comments below.
>
>>  libavcodec/Makefile  |   2 +
>>  libavcodec/avcodec.h |  13 
>>  libavcodec/encryption_info.c | 139 
>> +++
>>  libavcodec/encryption_info.h | 121 +
>>  4 files changed, 275 insertions(+)
>>  create mode 100644 libavcodec/encryption_info.c
>>  create mode 100644 libavcodec/encryption_info.h
>>
>> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
>> index ab7893f560..11ad642c6c 100644
>> --- a/libavcodec/Makefile
>> +++ b/libavcodec/Makefile
>> @@ -10,6 +10,7 @@ HEADERS = ac3_parser.h 
>>  \
>>dirac.h   \
>>dv_profile.h  \
>>dxva2.h   \
>> +  encryption_info.h \
>>jni.h \
>>mediacodec.h  \
>>qsv.h \
>> @@ -36,6 +37,7 @@ OBJS = ac3_parser.o
>>  \
>> dirac.o  \
>> dv_profile.o \
>> encode.o \
>> +   encryption_info.o\
>> imgconvert.o \
>> jni.o\
>> mathtables.o \
>> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
>> index 5db6a81320..b43638ebc5 100644
>> --- a/libavcodec/avcodec.h
>> +++ b/libavcodec/avcodec.h
>> @@ -1327,6 +1327,19 @@ enum AVPacketSideDataType {
>>   */
>>  AV_PKT_DATA_A53_CC,
>>
>> +/**
>> + * This side data is encryption "initialization data".
>> + * For MP4 this is the entire 'pssh' box.
>> + * For WebM this is the key ID.
>> + */
>> +AV_PKT_DATA_ENCRYPTION_INIT_DATA,
>> +
>> +/**
>> + * This side data contains encryption info for how to decrypt the 
>> packet.
>> + * The format is not part of ABI, use av_encryption_info_* methods to 
>> access.
>> + */
>> +AV_PKT_DATA_ENCRYPTION_INFO,
>> +
>>  /**
>>   * The number of side data types.
>>   * This is not part of the public API/ABI in the sense that it may
>> diff --git a/libavcodec/encryption_info.c b/libavcodec/encryption_info.c
>> new file mode 100644
>> index 00..59ee4c41a9
>> --- /dev/null
>> +++ b/libavcodec/encryption_info.c
>> @@ -0,0 +1,139 @@
>> +/**
>> + * 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
>> + */
>>

Re: [FFmpeg-devel] [RFC] avcodec/avcodec.h: Add encryption info side data

2017-12-20 Thread Jacob Trimble
On Wed, Dec 20, 2017 at 12:23 PM, wm4 <nfx...@googlemail.com> wrote:
> On Wed, 20 Dec 2017 12:07:09 -0800
> Jacob Trimble <modmaker-at-google@ffmpeg.org> wrote:
>
>> On Tue, Dec 19, 2017 at 3:05 PM, wm4 <nfx...@googlemail.com> wrote:
>> > On Tue, 19 Dec 2017 14:20:38 -0800
>> > Jacob Trimble <modmaker-at-google@ffmpeg.org> wrote:
>> >
>> >> > I don't think this is sane. So far, side data could simply be copied
>> >> > with memcpy, and having pointers to non-static data in side data would
>> >> > break this completely
>> >>
>> >> Then how about storing the data like it is now (the encryption info
>> >> followed by the subsample array), but not have a pointer?  Then there
>> >> will be several helper methods to get the subsample array from the
>> >> side-data.  For example,
>> >> av_encryption_info_get_subsamples(AVPacketEncryptionInfo*) or
>> >> av_encryption_info_get_subsamples(AVPacket*) (since there will only be
>> >> one instance of it).
>> >
>> > I guess that would work? Not particularly fond of the idea anyway. I
>> > think the functions would probably work on the side data byte array,
>> > maybe.
>>
>> I'm not fond of this either, but I can't think of a way to allow a
>> dynamic number of elements while supporting memcpy and not requiring
>> the app to "parse" the side-data.
>>
>> So here is may latest attempt.  This has a binary format inside the
>> side-data that allows memcpy to work, but there is a public struct
>> that apps will interact with.  There are two methods used to convert
>> between the two so the app doesn't have to.  Even though this is a
>> binary format, it is not actually a wire format since the subsamples
>> are stored as-is, so they are host byte ordered.  Also, as Michael
>> requested, this uses dynamic sized key ID and IV.
>
> I think your new patch idea is pretty sane. I'd explicitly document
> that the encryption side data format is not part of the ABI, and that
> applications must access it with the av_encryption_info_*() functions.
>
> Also I think it would be better to avoid the memory allocation
> messiness by copying all data, instead of implicitly referencing the
> AVPacket data. Also provide a free function. (That is assuming you're
> fine with a copy - creating AVPacket references copies all side data
> anyway, so the whole code base assumes side data copies are cheap.)
>
> If AVEncryptionInfo ever needs to be extended, it would also be better
> to just let av_encryption_info_get() return a newly allocated struct,
> and to exclude the size of the struct from the ABI. Then adding new
> fields would not require waiting for an ABI bump.

Done
From 1508d19e9f7acf43d76010ce54d59ff204613601 Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modma...@google.com>
Date: Tue, 5 Dec 2017 14:52:22 -0800
Subject: [PATCH] avcodec/avcodec.h: Add encryption info side data.

This new side-data will contain info on how a packet is encrypted.
This allows the app to handle packet decryption.

Signed-off-by: Jacob Trimble <modma...@google.com>
---
 libavcodec/Makefile  |   2 +
 libavcodec/avcodec.h |  13 
 libavcodec/encryption_info.c | 139 +++
 libavcodec/encryption_info.h | 121 +
 4 files changed, 275 insertions(+)
 create mode 100644 libavcodec/encryption_info.c
 create mode 100644 libavcodec/encryption_info.h

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index ab7893f560..11ad642c6c 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -10,6 +10,7 @@ HEADERS = ac3_parser.h  \
   dirac.h   \
   dv_profile.h  \
   dxva2.h   \
+  encryption_info.h \
   jni.h \
   mediacodec.h  \
   qsv.h \
@@ -36,6 +37,7 @@ OBJS = ac3_parser.o \
dirac.o  \
dv_profile.o \
encode.o \
+   encryption_info.o\
imgconvert.o  

Re: [FFmpeg-devel] [RFC] avcodec/avcodec.h: Add encryption info side data

2017-12-20 Thread Jacob Trimble
On Tue, Dec 19, 2017 at 3:05 PM, wm4 <nfx...@googlemail.com> wrote:
> On Tue, 19 Dec 2017 14:20:38 -0800
> Jacob Trimble <modmaker-at-google@ffmpeg.org> wrote:
>
>> > I don't think this is sane. So far, side data could simply be copied
>> > with memcpy, and having pointers to non-static data in side data would
>> > break this completely
>>
>> Then how about storing the data like it is now (the encryption info
>> followed by the subsample array), but not have a pointer?  Then there
>> will be several helper methods to get the subsample array from the
>> side-data.  For example,
>> av_encryption_info_get_subsamples(AVPacketEncryptionInfo*) or
>> av_encryption_info_get_subsamples(AVPacket*) (since there will only be
>> one instance of it).
>
> I guess that would work? Not particularly fond of the idea anyway. I
> think the functions would probably work on the side data byte array,
> maybe.

I'm not fond of this either, but I can't think of a way to allow a
dynamic number of elements while supporting memcpy and not requiring
the app to "parse" the side-data.

So here is may latest attempt.  This has a binary format inside the
side-data that allows memcpy to work, but there is a public struct
that apps will interact with.  There are two methods used to convert
between the two so the app doesn't have to.  Even though this is a
binary format, it is not actually a wire format since the subsamples
are stored as-is, so they are host byte ordered.  Also, as Michael
requested, this uses dynamic sized key ID and IV.
From 38c480a470d7f107945180968a5db237c671f7d0 Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modma...@google.com>
Date: Tue, 5 Dec 2017 14:52:22 -0800
Subject: [PATCH] avcodec/avcodec.h: Add encryption info side data.

This new side-data will contain info on how a packet is encrypted.
This allows the app to handle packet decryption.

Signed-off-by: Jacob Trimble <modma...@google.com>
---
 libavcodec/Makefile  |   2 +
 libavcodec/avcodec.h |  13 ++
 libavcodec/encryption_info.c |  70 +
 libavcodec/encryption_info.h | 105 +++
 4 files changed, 190 insertions(+)
 create mode 100644 libavcodec/encryption_info.c
 create mode 100644 libavcodec/encryption_info.h

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index ab7893f560..11ad642c6c 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -10,6 +10,7 @@ HEADERS = ac3_parser.h  \
   dirac.h   \
   dv_profile.h  \
   dxva2.h   \
+  encryption_info.h \
   jni.h \
   mediacodec.h  \
   qsv.h \
@@ -36,6 +37,7 @@ OBJS = ac3_parser.o \
dirac.o  \
dv_profile.o \
encode.o \
+   encryption_info.o\
imgconvert.o \
jni.o\
mathtables.o \
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 5db6a81320..7a5bba2687 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1327,6 +1327,19 @@ enum AVPacketSideDataType {
  */
 AV_PKT_DATA_A53_CC,
 
+/**
+ * This side data is encryption "initialization data".
+ * For MP4 this is the entire 'pssh' box.
+ * For WebM this is the key ID.
+ */
+AV_PKT_DATA_ENCRYPTION_INIT_DATA,
+
+/**
+ * This side data contains encryption info for how to decrypt the packet.
+ * Use av_encryption_info_get to get the info out of this side data.
+ */
+AV_PKT_DATA_ENCRYPTION_INFO,
+
 /**
  * The number of side data types.
  * This is not part of the public API/ABI in the sense that it may
diff --git a/libavcodec/encryption_info.c b/libavcodec/encryption_info.c
new file mode 100644
index 00..a2c11fe213
--- /dev/null
+++ b/libavcodec/encryption_info.c
@@ -0,0 +1,70 @@
+/**
+ * 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 

Re: [FFmpeg-devel] [RFC] avcodec/avcodec.h: Add encryption info side data

2017-12-19 Thread Jacob Trimble
> You pretty much did. Side data is an ffmpeg internal concept, and if
> your hypothetical streaming protocol needs special support for side
> data, it's automatically relying on ffmpeg internals.

I thought side data was public data?  Doesn't it contain public info
like display info and required decoder info?  So if someone wants to
decode frames without using the demuxers, they'll need to reconstruct
the side data so the decoder can still work.

> On that note, I wonder if we should add an AVPacket reserved field for
> this, just so we don't have to wait for the next ABI bump.

I would much prefer to have this in AVPacket since it is in no way
"optional".  Having the info in the packet ensures a custom app can
see the info and is less likely to get confused on why their packets
aren't decoding.  I did this as side-data since it would have less ABI
impact and I thought it would cause less conflict.  But having it as
another field on AVPacket would allow more control over memory so the
dynamic fields don't cause problems anymore.

> I don't think this is sane. So far, side data could simply be copied
> with memcpy, and having pointers to non-static data in side data would
> break this completely

Then how about storing the data like it is now (the encryption info
followed by the subsample array), but not have a pointer?  Then there
will be several helper methods to get the subsample array from the
side-data.  For example,
av_encryption_info_get_subsamples(AVPacketEncryptionInfo*) or
av_encryption_info_get_subsamples(AVPacket*) (since there will only be
one instance of it).
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [RFC] avcodec/avcodec.h: Add encryption info side data

2017-12-18 Thread Jacob Trimble
>> @@ -1327,6 +1384,19 @@ enum AVPacketSideDataType {
>>   */
>>  AV_PKT_DATA_A53_CC,
>>
>> +/**
>> + * This side data is encryption "initialization data".
>> + * For MP4 this is the entire 'pssh' box.
>> + * For WebM this is the key ID.
>> + */
>> +AV_PKT_DATA_ENCRYPTION_INIT_DATA,
>
> So its basically like extradata is for a codec ?
> If so it should be defined similarly as opaque encryption scheme specific 
> data.
> It should not be container specific.
> Data taken from one container should be storable in another if both support
> the features used

Yes, that's the idea.  Unfortunately the data is specific to a
container.  This isn't taken from the common encryption spec, but from
the EME spec.  The "EME initialization data registry" specifies
several fixed formats for initialization data that are all specific to
a container.  

It would be possible to parse the PSSH boxes and just push the generic
data to the app.  This would allow new containers to hold the same
data; then the app could wrap it back in a generic PSSH box for EME.
But that would remove the key ID information that exists in v1 PSSH
boxes.  Some apps parse the PSSH boxes and filter the initialization
based on whether they already have those key IDs to avoid creating too
many sessions.  So I would like to expose the whole PSSH box in the
side data so apps can do that.

I can change this to something that is specific to MP4 instead (e.g.
AV_PKT_DATA_MP4_PSSH).  The app could just pull the key ID from the
first sample in the case of WebM.

>
> thanks
>
> [...]
>
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [RFC] avcodec/avcodec.h: Add encryption info side data

2017-12-15 Thread Jacob Trimble
>> +
>> +/** The ID of the key used to encrypt the packet. */
>> +uint8_t key_id[16];
>> +
>> +/** The initialization vector. */
>> +uint8_t iv[16];
>
> what happens if the key or iv is longer ?

Both are specified by common encryption to be exactly that size.  To
be able to be
longer would require an updated spec.  Plus it avoids having to store a dynamic
string somewhere in the side data.

>
>> +
>> +/**
>> + * Only used for pattern encryption.  This is the number of 16-byte 
>> blocks
>> + * that are encrypted.
>> + */
>> +unsigned int crypt_byte_block;
>> +
>> +/**
>> + * Only used for pattern encryption.  This is the number of 16-byte 
>> blocks
>> + * that are clear.
>> + */
>> +unsigned int skip_byte_block;
>
> why is "16-byte blocks" hardcoded ?

Because that is how pattern encryption works in common encryption.  It
is specified
by number of AES blocks, not individual bytes.  I could change to
bytes, but it would
likely require the app to divide by 16 later and it runs the risk of
the value not being a
multiple of 16 like the spec requires.

>
>
>> +
>> +/**
>> + * The number of sub-samples in this packet.  If 0, then the whole 
>> sample
>> + * is encrypted.
>> + */
>> +unsigned int subsample_count;
>> +
>> +struct {
>> +  /** The number of bytes that are clear. */
>> +  unsigned int bytes_of_clear_data;
>> +
>> +  /**
>> +   * The number of bytes that are protected.  If using pattern 
>> encryption,
>> +   * the pattern applies to only the protected bytes; if not using 
>> pattern
>> +   * encryption, all these bytes are encrypted.
>> +   */
>> +  unsigned int bytes_of_protected_data;
>> +} *subsamples;
>
> Are these patterns random in practice ?
> if not they possibly would be better not repeated per packet

They are unique per packet.

For example, in H.264, certain NAL unit types should be kept in the clear, while
others should be encrypted.  Plus even for encrypted NAL units, the header
should be kept in the clear even when the payload is encrypted.

>
>
>> +} AVPacketEncryptionInfo;
>
>> +#define FF_PACKET_ENCRYPTION_INFO_SIZE(a) (sizeof(AVPacketEncryptionInfo) + 
>> sizeof(unsigned int) * a * 2)
>
> This assumes things about the padding and alignment of fields that are not
> guranteed by C i think
>

I was trying to avoid having another top-level struct.  Too bad you
can get the size
of members without an instance in c.
From a1b2cbcb7da4da69685f8f1299b70b672ce448e3 Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modma...@google.com>
Date: Tue, 5 Dec 2017 14:52:22 -0800
Subject: [PATCH] avcodec/avcodec.h: Add encryption info side data.

This new side-data will contain info on how a packet is encrypted.
This allows the app to handle packet decryption.  To allow for a
variable number of subsamples, the buffer for the side-data will be
allocated to hold both the structure and the array of subsamples.  So
the |subsamples| member will point to right after the struct.

Signed-off-by: Jacob Trimble <modma...@google.com>
---
 libavcodec/avcodec.h | 70 
 1 file changed, 70 insertions(+)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 5db6a81320..ccc89345e8 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1112,6 +1112,63 @@ typedef struct AVCPBProperties {
 uint64_t vbv_delay;
 } AVCPBProperties;
 
+typedef struct AVPacketSubsampleEncryptionInfo {
+/** The number of bytes that are clear. */
+unsigned int bytes_of_clear_data;
+
+/**
+ * The number of bytes that are protected.  If using pattern encryption,
+ * the pattern applies to only the protected bytes; if not using pattern
+ * encryption, all these bytes are encrypted.
+ */
+unsigned int bytes_of_protected_data;
+} AVPacketSubsampleEncryptionInfo;
+
+/**
+ * This describes encryption info for a packet.  This contains frame-specific
+ * info for how to decrypt the packet before passing it to the decoder.  If this
+ * side-data is present, then the packet is encrypted.
+ */
+typedef struct AVPacketEncryptionInfo {
+/** The fourcc encryption scheme. */
+uint32_t scheme;
+
+/** The ID of the key used to encrypt the packet. */
+uint8_t key_id[16];
+
+/** The initialization vector. */
+uint8_t iv[16];
+
+/**
+ * Only used for pattern encryption.  This is the number of 16-byte blocks
+ * that are encrypted.
+ */
+unsigned int crypt_byte_block;
+
+/**
+ * Only used for pattern encryption.  This is the number of 16-byte blocks
+ *

  1   2   >