1 /*****************************************************************
2 |
3 |    AP4 - Common Encryption support
4 |
5 |    Copyright 2002-2017 Axiomatic Systems, LLC
6 |
7 |
8 |    This file is part of Bento4/AP4 (MP4 Atom Processing Library).
9 |
10 |    Unless you have obtained Bento4 under a difference license,
11 |    this version of Bento4 is Bento4|GPL.
12 |    Bento4|GPL is free software; you can redistribute it and/or modify
13 |    it under the terms of the GNU General Public License as published by
14 |    the Free Software Foundation; either version 2, or (at your option)
15 |    any later version.
16 |
17 |    Bento4|GPL is distributed in the hope that it will be useful,
18 |    but WITHOUT ANY WARRANTY; without even the implied warranty of
19 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 |    GNU General Public License for more details.
21 |
22 |    You should have received a copy of the GNU General Public License
23 |    along with Bento4|GPL; see the file COPYING.  If not, write to the
24 |    Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 |    02111-1307, USA.
26 |
27 ****************************************************************/
28 
29 #ifndef _AP4_COMMON_ENCRYPTION_H_
30 #define _AP4_COMMON_ENCRYPTION_H_
31 
32 /*----------------------------------------------------------------------
33 |   includes
34 +---------------------------------------------------------------------*/
35 #include "Ap4Atom.h"
36 #include "Ap4ByteStream.h"
37 #include "Ap4Utils.h"
38 #include "Ap4Processor.h"
39 #include "Ap4Protection.h"
40 #include "Ap4PsshAtom.h"
41 
42 /*----------------------------------------------------------------------
43 |   class declarations
44 +---------------------------------------------------------------------*/
45 class AP4_StreamCipher;
46 class AP4_SaizAtom;
47 class AP4_SaioAtom;
48 class AP4_CencSampleInfoTable;
49 class AP4_AvcFrameParser;
50 class AP4_HevcFrameParser;
51 
52 /*----------------------------------------------------------------------
53 |   constants
54 +---------------------------------------------------------------------*/
55 const AP4_UI32 AP4_PROTECTION_SCHEME_TYPE_CENC = AP4_ATOM_TYPE('c','e','n','c');
56 const AP4_UI32 AP4_PROTECTION_SCHEME_TYPE_CENS = AP4_ATOM_TYPE('c','e','n','s');
57 const AP4_UI32 AP4_PROTECTION_SCHEME_TYPE_CBC1 = AP4_ATOM_TYPE('c','b','c','1');
58 const AP4_UI32 AP4_PROTECTION_SCHEME_TYPE_CBCS = AP4_ATOM_TYPE('c','b','c','s');
59 const AP4_UI32 AP4_PROTECTION_SCHEME_VERSION_CENC_10 = 0x00010000;
60 
61 const AP4_UI32 AP4_CENC_CIPHER_NONE         = 0;
62 const AP4_UI32 AP4_CENC_CIPHER_AES_128_CTR  = 1;
63 const AP4_UI32 AP4_CENC_CIPHER_AES_128_CBC  = 2;
64 
65 const AP4_UI32 AP4_CENC_SAMPLE_ENCRYPTION_FLAG_OVERRIDE_TRACK_ENCRYPTION_DEFAULTS = 1;
66 const AP4_UI32 AP4_CENC_SAMPLE_ENCRYPTION_FLAG_USE_SUB_SAMPLE_ENCRYPTION          = 2;
67 
68 typedef enum {
69     AP4_CENC_VARIANT_PIFF_CTR,
70     AP4_CENC_VARIANT_PIFF_CBC,
71     AP4_CENC_VARIANT_MPEG_CENC,
72     AP4_CENC_VARIANT_MPEG_CBC1,
73     AP4_CENC_VARIANT_MPEG_CENS,
74     AP4_CENC_VARIANT_MPEG_CBCS
75 } AP4_CencVariant;
76 
77 /*----------------------------------------------------------------------
78 |   AP4_CencTrackEncryption
79 +---------------------------------------------------------------------*/
80 class AP4_CencTrackEncryption {
81 public:
AP4_IMPLEMENT_DYNAMIC_CAST(AP4_CencTrackEncryption)82     AP4_IMPLEMENT_DYNAMIC_CAST(AP4_CencTrackEncryption)
83 
84     virtual ~AP4_CencTrackEncryption() {}
85 
86     // methods
87     AP4_Result Parse(AP4_ByteStream& stream);
88     AP4_Result DoInspectFields(AP4_AtomInspector& inspector);
89     AP4_Result DoWriteFields(AP4_ByteStream& stream);
90 
91     // accessors
GetDefaultIsProtected()92     AP4_UI32        GetDefaultIsProtected()     { return m_DefaultIsProtected;     }
GetDefaultPerSampleIvSize()93     AP4_UI08        GetDefaultPerSampleIvSize() { return m_DefaultPerSampleIvSize; }
GetDefaultConstantIvSize()94     AP4_UI08        GetDefaultConstantIvSize()  { return m_DefaultConstantIvSize;  }
GetDefaultConstantIv()95     const AP4_UI08* GetDefaultConstantIv()      { return m_DefaultConstantIv;      }
GetDefaultKid()96     const AP4_UI08* GetDefaultKid()             { return m_DefaultKid;             }
GetDefaultCryptByteBlock()97     AP4_UI08        GetDefaultCryptByteBlock()  { return m_DefaultCryptByteBlock;  }
GetDefaultSkipByteBlock()98     AP4_UI08        GetDefaultSkipByteBlock()   { return m_DefaultSkipByteBlock;   }
99 
100 protected:
101     // constructors
102     AP4_CencTrackEncryption(AP4_UI08 version);
103     AP4_CencTrackEncryption(AP4_UI08        version,
104                             AP4_UI08        default_is_protected,
105                             AP4_UI08        default_per_sample_iv_size,
106                             const AP4_UI08* default_kid,
107                             AP4_UI08        default_constant_iv_size = 0,
108                             const AP4_UI08* default_constant_iv = NULL,
109                             AP4_UI08        default_crypt_byte_block = 0,
110                             AP4_UI08        default_skip_byte_block = 0);
111 
112 private:
113     // members
114     AP4_UI08 m_Version_; // cannot be called m_Version because it would conflict with AP4_Atom::m_Version
115     AP4_UI08 m_DefaultIsProtected;
116     AP4_UI08 m_DefaultPerSampleIvSize;
117     AP4_UI08 m_DefaultConstantIvSize;
118     AP4_UI08 m_DefaultConstantIv[16];
119     AP4_UI08 m_DefaultKid[16];
120     AP4_UI08 m_DefaultCryptByteBlock;
121     AP4_UI08 m_DefaultSkipByteBlock;
122 };
123 
124 /*----------------------------------------------------------------------
125 |   AP4_CencSampleEncryption
126 +---------------------------------------------------------------------*/
127 class AP4_CencSampleEncryption {
128 public:
AP4_IMPLEMENT_DYNAMIC_CAST(AP4_CencSampleEncryption)129     AP4_IMPLEMENT_DYNAMIC_CAST(AP4_CencSampleEncryption)
130 
131     virtual ~AP4_CencSampleEncryption() {}
132 
133     // methods
134     AP4_Result DoInspectFields(AP4_AtomInspector& inspector);
135     AP4_Result DoWriteFields(AP4_ByteStream& stream);
136 
137     // accessors
GetOuter()138     AP4_Atom&       GetOuter()              { return m_Outer;           }
GetAlgorithmId()139     AP4_UI32        GetAlgorithmId()        { return m_AlgorithmId;     }
GetPerSampleIvSize()140     AP4_UI08        GetPerSampleIvSize()    { return m_PerSampleIvSize; }
141     AP4_Result      SetPerSampleIvSize(AP4_UI08 iv_size);
GetConstantIvSize()142     AP4_UI08        GetConstantIvSize()     { return m_ConstantIvSize;  }
143     AP4_Result      SetConstantIvSize(AP4_UI08 iv_size);
GetCryptByteBlock()144     AP4_UI08        GetCryptByteBlock()     { return m_CryptByteBlock;  }
GetSkipByteBlock()145     AP4_UI08        GetSkipByteBlock()      { return m_SkipByteBlock;   }
GetConstantIv()146     const AP4_UI08* GetConstantIv()         { return m_ConstantIv;      }
GetKid()147     const AP4_UI08* GetKid()                { return m_Kid;             }
GetSampleInfoCount()148     AP4_Cardinal    GetSampleInfoCount()    { return m_SampleInfoCount; }
149     AP4_Result      AddSampleInfo(const AP4_UI08* iv, AP4_DataBuffer& subsample_info);
150     AP4_Result      SetSampleInfosSize(AP4_Size size);
151     AP4_Result      CreateSampleInfoTable(AP4_UI08                  flags,
152                                           AP4_UI08                  default_crypt_byte_block,
153                                           AP4_UI08                  default_skip_byte_block,
154                                           AP4_UI08                  default_per_sample_iv_size,
155                                           AP4_UI08                  default_constant_iv_size,
156                                           const AP4_UI08*           default_constant_iv,
157                                           AP4_CencSampleInfoTable*& table);
158 
159 protected:
160     // constructors
161     AP4_CencSampleEncryption(AP4_Atom&       outer,
162                              AP4_UI08        per_sample_iv_size,
163                              AP4_UI08        constant_iv_size = 0,
164                              const AP4_UI08* constant_iv = NULL,
165                              AP4_UI08        crypt_byte_block = 0,
166                              AP4_UI08        skip_byte_block = 0);
167     AP4_CencSampleEncryption(AP4_Atom& outer, AP4_Size size, AP4_ByteStream& stream);
168     AP4_CencSampleEncryption(AP4_Atom&       outer,
169                              AP4_UI32        algorithm_id,
170                              AP4_UI08        per_sample_iv_size,
171                              const AP4_UI08* kid);
172 
173 protected:
174     // members
175     AP4_Atom&      m_Outer;
176     AP4_UI32       m_AlgorithmId;
177     AP4_UI08       m_PerSampleIvSize;
178     AP4_UI08       m_ConstantIvSize;
179     AP4_UI08       m_ConstantIv[16];
180     AP4_UI08       m_CryptByteBlock;
181     AP4_UI08       m_SkipByteBlock;
182     AP4_UI08       m_Kid[16];
183     AP4_Cardinal   m_SampleInfoCount;
184     AP4_DataBuffer m_SampleInfos;
185     unsigned int   m_SampleInfoCursor;
186 };
187 
188 /*----------------------------------------------------------------------
189 |   AP4_CencSampleInfoTable
190 +---------------------------------------------------------------------*/
191 class AP4_CencSampleInfoTable {
192 public:
193     // class methods
194     static AP4_Result Create(AP4_ProtectedSampleDescription* sample_description,
195                              AP4_ContainerAtom*              traf,
196                              AP4_UI32&                       cipher_type,
197                              bool&                           reset_iv_at_each_subsample,
198                              AP4_ByteStream&                 aux_info_data,
199                              AP4_Position                    aux_info_data_offset,
200                              AP4_CencSampleInfoTable*&       sample_info_table);
201 
202     static AP4_Result Create(AP4_ProtectedSampleDescription* sample_description,
203                              AP4_ContainerAtom*              traf,
204                              AP4_SaioAtom*&                  saio,
205                              AP4_SaizAtom*&                  saiz,
206                              AP4_CencSampleEncryption*&      sample_encryption_atom,
207                              AP4_UI32&                       cipher_type,
208                              bool&                           reset_iv_at_each_subsample,
209                              AP4_ByteStream&                 aux_info_data,
210                              AP4_Position                    aux_info_data_offset,
211                              AP4_CencSampleInfoTable*&       sample_info_table);
212 
213     static AP4_Result Create(AP4_UI08                  flags,
214                              AP4_UI08                  crypt_byte_block,
215                              AP4_UI08                  skip_byte_block,
216                              AP4_UI08                  per_sample_iv_size,
217                              AP4_UI08                  constant_iv_size,
218                              const AP4_UI08*           constant_iv,
219                              AP4_ContainerAtom&        traf,
220                              AP4_SaioAtom&             saio,
221                              AP4_SaizAtom&             saiz,
222                              AP4_ByteStream&           aux_info_data,
223                              AP4_Position              aux_info_data_offset,
224                              AP4_CencSampleInfoTable*& sample_info_table);
225 
226 
227     // see note below regarding the serialization format
228     static AP4_Result Create(const AP4_UI08*           serialized,
229                              unsigned int              serialized_size,
230                              AP4_CencSampleInfoTable*& sample_info_table);
231 
232     // constructor
233     AP4_CencSampleInfoTable(AP4_UI08 flags,
234                             AP4_UI08 crypt_byte_block,
235                             AP4_UI08 skip_byte_block,
236                             AP4_UI32 sample_count,
237                             AP4_UI08 iv_size);
238 
239     // methods
GetFlags()240     AP4_UI08        GetFlags()          { return m_Flags;          }
GetCryptByteBlock()241     AP4_UI08        GetCryptByteBlock() { return m_CryptByteBlock; }
GetSkipByteBlock()242     AP4_UI08        GetSkipByteBlock()  { return m_SkipByteBlock;  }
GetSampleCount()243     AP4_UI32        GetSampleCount()    { return m_SampleCount;    }
GetIvSize()244     AP4_UI08        GetIvSize()         { return m_IvSize;         }
245     AP4_Result      SetIv(AP4_Ordinal sample_index, const AP4_UI08* iv);
246     const AP4_UI08* GetIv(AP4_Ordinal sample_index);
247     AP4_Result      AddSubSampleData(AP4_Cardinal    subsample_count,
248                                      const AP4_UI08* subsample_data);
HasSubSampleInfo()249     bool            HasSubSampleInfo() {
250         return m_SubSampleMapStarts.ItemCount() != 0;
251     }
GetSubsampleCount(AP4_Cardinal sample_index)252     unsigned int    GetSubsampleCount(AP4_Cardinal sample_index) {
253         if (sample_index < m_SampleCount) {
254             return m_SubSampleMapLengths[sample_index];
255         } else {
256             return 0;
257         }
258     }
259     AP4_Result GetSampleInfo(AP4_Cardinal     sample_index,
260                              AP4_Cardinal&    subsample_count,
261                              const AP4_UI16*& bytes_of_cleartext_data,
262                              const AP4_UI32*& bytes_of_encrypted_data);
263 
264     AP4_Result GetSubsampleInfo(AP4_Cardinal sample_index,
265                                 AP4_Cardinal subsample_index,
266                                 AP4_UI16&    bytes_of_cleartext_data,
267                                 AP4_UI32&    bytes_of_encrypted_data);
268 
269     // see note below regarding the serialization format
270     AP4_Result Serialize(AP4_DataBuffer& buffer);
271 
272 private:
273     AP4_UI32                m_SampleCount;
274     AP4_UI08                m_Flags;
275     AP4_UI08                m_CryptByteBlock;
276     AP4_UI08                m_SkipByteBlock;
277     AP4_UI08                m_IvSize;
278     AP4_DataBuffer          m_IvData;
279     AP4_Array<AP4_UI16>     m_BytesOfCleartextData;
280     AP4_Array<AP4_UI32>     m_BytesOfEncryptedData;
281     AP4_Array<unsigned int> m_SubSampleMapStarts;
282     AP4_Array<unsigned int> m_SubSampleMapLengths;
283 };
284 
285 /*----------------------------------------------------------------------
286 |   AP4_CencSampleInfoTable serialization format
287 |
288 |   (All integers are stored in big-endian byte order)
289 |
290 |   +---------------+----------------+------------------------------------+
291 |   | Size          |  Type          |  Description                       |
292 |   +---------------+----------------+------------------------------------+
293 |
294 |   +---------------+----------------+------------------------------------+
295 |   | 4 bytes       | 32-bit integer | sample_count                       |
296 |   +---------------+----------------+------------------------------------+
297 |   | 1 byte        | 8-bit integer  | flags                              |
298 |   +---------------+----------------+------------------------------------+
299 |   | 1 byte        | 8-bit integer  | crypt_byte_block                   |
300 |   +---------------+----------------+------------------------------------+
301 |   | 1 byte        | 8-bit integer  | skip_byte_block                    |
302 |   +---------------+----------------+------------------------------------+
303 |   | 1 byte        | 8-bit integer  | iv_size                            |
304 |   +---------------+----------------+------------------------------------+
305 |
306 |   repeat sample_count times:
307 |   +---------------+----------------+------------------------------------+
308 |   | iv_size bytes | byte array     | IV[i]                              |
309 |   +---------------+----------------+------------------------------------+
310 |
311 |   +---------------+----------------+------------------------------------+
312 |   | 4 bytes       | 32-bit integer | entry_count                        |
313 |   +---------------+----------------+------------------------------------+
314 |
315 |   repeat entry_count times:
316 |   +---------------+----------------+------------------------------------+
317 |   | 2 bytes       | 16-bit integer | bytes_of_cleartext_data[i]         |
318 |   +---------------+----------------+------------------------------------+
319 |
320 |   repeat entry_count times:
321 |   +---------------+----------------+------------------------------------+
322 |   | 4 bytes       | 32-bit integer | bytes_of_encrypted_data[i]         |
323 |   +---------------+----------------+------------------------------------+
324 |
325 |   +---------------+----------------+------------------------------------+
326 |   | 4 bytes       | 32-bit flags   | 1 if subsamples are used, 0 if not |
327 |   +---------------+----------------+------------------------------------+
328 |
329 |   if subsamples are used, repeat sample_count times:
330 |   +---------------+----------------+------------------------------------+
331 |   | 4 bytes       | 32-bit integer | subsample_map_start[i]             |
332 |   +---------------+----------------+------------------------------------+
333 |
334 |   if subsamples are used, repeat sample_count times:
335 |   +---------------+----------------+------------------------------------+
336 |   | 4 bytes       | 32-bit integer | subsample_map_length[i]            |
337 |   +---------------+----------------+------------------------------------+
338 |
339 |   NOTES: subsample_map_start[i] ans subsample_map_length[i] are, respectively,
340 |   the index and the length the i'th subsample map sequence in the
341 |   bytes_of_cleartext_data anb bytes_of_encrypted_data arrays.
342 |   For example, if we have:
343 |   bytes_of_cleartext_data[] = { 10,   15, 13, 17, 12 }
344 |   bytes_of_encrypted_data[] = { 100, 200, 50, 80, 32 }
345 |   subsample_map_start  = { 0, 3 }
346 |   subsample_map_length = { 3, 2 }
347 |   It means that the (bytes_of_cleartext_data, bytes_of_encrypted_data)
348 |   sequences for the two subsamples are:
349 |   subsample[0] --> [(10,100), (15, 200), (13, 50)]
350 |   subsample[1] --> [(17, 80), (12,  32)]
351 |
352 +---------------------------------------------------------------------*/
353 
354 
355 /*----------------------------------------------------------------------
356 |   AP4_CencSampleEncrypter
357 +---------------------------------------------------------------------*/
358 class AP4_CencSampleEncrypter
359 {
360 public:
361     // constructor and destructor
AP4_CencSampleEncrypter(AP4_StreamCipher * cipher,bool constant_iv)362     AP4_CencSampleEncrypter(AP4_StreamCipher* cipher,
363                             bool              constant_iv) :
364         m_Cipher(cipher),
365         m_ConstantIv(constant_iv) {
366         AP4_SetMemory(m_Iv, 0, 16);
367     };
368     virtual ~AP4_CencSampleEncrypter();
369 
370     // methods
371     virtual AP4_Result EncryptSampleData(AP4_DataBuffer& data_in,
372                                          AP4_DataBuffer& data_out,
373                                          AP4_DataBuffer& sample_infos) = 0;
374 
SetIv(const AP4_UI08 * iv)375     void            SetIv(const AP4_UI08* iv) { AP4_CopyMemory(m_Iv, iv, 16); }
GetIv()376     const AP4_UI08* GetIv()                   { return m_Iv;                  }
UseSubSamples()377     virtual bool    UseSubSamples()           { return false;                 }
GetSubSampleMap(AP4_DataBuffer &,AP4_Array<AP4_UI16> &,AP4_Array<AP4_UI32> &)378     virtual AP4_Result GetSubSampleMap(AP4_DataBuffer&      /* sample_data */,
379                                        AP4_Array<AP4_UI16>& /* bytes_of_cleartext_data */,
380                                        AP4_Array<AP4_UI32>& /* bytes_of_encrypted_data */) {
381         return AP4_SUCCESS;
382     }
383 
384 protected:
385     AP4_UI08          m_Iv[16];
386     AP4_StreamCipher* m_Cipher;
387     bool              m_ConstantIv;
388 };
389 
390 /*----------------------------------------------------------------------
391 |   AP4_CencCtrSampleEncrypter
392 +---------------------------------------------------------------------*/
393 class AP4_CencCtrSampleEncrypter : public AP4_CencSampleEncrypter
394 {
395 public:
396     // constructor and destructor
AP4_CencCtrSampleEncrypter(AP4_StreamCipher * cipher,bool constant_iv,unsigned int iv_size)397     AP4_CencCtrSampleEncrypter(AP4_StreamCipher* cipher,
398                                bool              constant_iv,
399                                unsigned int      iv_size) :
400         AP4_CencSampleEncrypter(cipher, constant_iv),
401         m_IvSize(iv_size) {}
402 
403     // methods
404     virtual AP4_Result EncryptSampleData(AP4_DataBuffer& data_in,
405                                          AP4_DataBuffer& data_out,
406                                          AP4_DataBuffer& sample_infos);
407 
408 protected:
409     unsigned int m_IvSize;
410 };
411 
412 /*----------------------------------------------------------------------
413 |   AP4_CencCbcSampleEncrypter
414 +---------------------------------------------------------------------*/
415 class AP4_CencCbcSampleEncrypter : public AP4_CencSampleEncrypter
416 {
417 public:
418     // constructor and destructor
AP4_CencCbcSampleEncrypter(AP4_StreamCipher * cipher,bool constant_iv)419     AP4_CencCbcSampleEncrypter(AP4_StreamCipher* cipher,
420                                bool              constant_iv) :
421         AP4_CencSampleEncrypter(cipher, constant_iv) {}
422 
423     // methods
424     virtual AP4_Result EncryptSampleData(AP4_DataBuffer& data_in,
425                                          AP4_DataBuffer& data_out,
426                                          AP4_DataBuffer& sample_infos);
427 };
428 
429 /*----------------------------------------------------------------------
430 |   AP4_CencSubSampleMapper
431 +---------------------------------------------------------------------*/
432 class AP4_CencSubSampleMapper
433 {
434 public:
435     // constructor and destructor
AP4_CencSubSampleMapper(AP4_Size nalu_length_size,AP4_UI32 format)436     AP4_CencSubSampleMapper(AP4_Size nalu_length_size, AP4_UI32 format) :
437         m_NaluLengthSize(nalu_length_size),
438         m_Format(format) {}
~AP4_CencSubSampleMapper()439     virtual ~AP4_CencSubSampleMapper() {}
440 
441     // methods
442     virtual AP4_Result GetSubSampleMap(AP4_DataBuffer&      sample_data,
443                                        AP4_Array<AP4_UI16>& bytes_of_cleartext_data,
444                                        AP4_Array<AP4_UI32>& bytes_of_encrypted_data) = 0;
445 
446 protected:
447     // members
448     AP4_Size m_NaluLengthSize;
449     AP4_UI32 m_Format;
450 };
451 
452 /*----------------------------------------------------------------------
453 |   AP4_CencBasicSubSampleMapper
454 +---------------------------------------------------------------------*/
455 class AP4_CencBasicSubSampleMapper : public AP4_CencSubSampleMapper
456 {
457 public:
458     // constructor and destructor
AP4_CencBasicSubSampleMapper(AP4_Size nalu_length_size,AP4_UI32 format)459     AP4_CencBasicSubSampleMapper(AP4_Size nalu_length_size, AP4_UI32 format) :
460         AP4_CencSubSampleMapper(nalu_length_size, format) {}
461 
462     // methods
463     virtual AP4_Result GetSubSampleMap(AP4_DataBuffer&      sample_data,
464                                        AP4_Array<AP4_UI16>& bytes_of_cleartext_data,
465                                        AP4_Array<AP4_UI32>& bytes_of_encrypted_data);
466 };
467 
468 /*----------------------------------------------------------------------
469 |   AP4_CencAdvancedSubSampleMapper
470 +---------------------------------------------------------------------*/
471 class AP4_CencAdvancedSubSampleMapper : public AP4_CencSubSampleMapper
472 {
473 public:
474     // constructor and destructor
AP4_CencAdvancedSubSampleMapper(AP4_Size nalu_length_size,AP4_UI32 format)475     AP4_CencAdvancedSubSampleMapper(AP4_Size nalu_length_size, AP4_UI32 format) :
476         AP4_CencSubSampleMapper(nalu_length_size, format) {}
477 
478     // methods
479     virtual AP4_Result GetSubSampleMap(AP4_DataBuffer&      sample_data,
480                                        AP4_Array<AP4_UI16>& bytes_of_cleartext_data,
481                                        AP4_Array<AP4_UI32>& bytes_of_encrypted_data);
482 };
483 
484 /*----------------------------------------------------------------------
485 |   AP4_CencCbcsSubSampleMapper
486 +---------------------------------------------------------------------*/
487 class AP4_CencCbcsSubSampleMapper : public AP4_CencSubSampleMapper
488 {
489 public:
490     // constructor and destructor
491     AP4_CencCbcsSubSampleMapper(AP4_Size nalu_length_size, AP4_UI32 format, AP4_TrakAtom* trak);
492     ~AP4_CencCbcsSubSampleMapper();
493 
494     // methods
495     virtual AP4_Result GetSubSampleMap(AP4_DataBuffer&      sample_data,
496                                        AP4_Array<AP4_UI16>& bytes_of_cleartext_data,
497                                        AP4_Array<AP4_UI32>& bytes_of_encrypted_data);
498 
499 private:
500     // members
501     AP4_AvcFrameParser*  m_AvcParser;
502     AP4_HevcFrameParser* m_HevcParser;
503 
504     // methods
505     AP4_Result ParseAvcData(const AP4_UI08* data, AP4_Size data_size);
506     AP4_Result ParseHevcData(const AP4_UI08* data, AP4_Size data_size);
507 };
508 
509 /*----------------------------------------------------------------------
510 |   AP4_CencSubSampleEncrypter
511 +---------------------------------------------------------------------*/
512 class AP4_CencSubSampleEncrypter : public AP4_CencSampleEncrypter
513 {
514 public:
515     // constructor and destructor
AP4_CencSubSampleEncrypter(AP4_StreamCipher * cipher,bool constant_iv,bool reset_iv_at_each_subsample,AP4_CencSubSampleMapper * subsample_mapper)516     AP4_CencSubSampleEncrypter(AP4_StreamCipher*        cipher,
517                                bool                     constant_iv,
518                                bool                     reset_iv_at_each_subsample,
519                                AP4_CencSubSampleMapper* subsample_mapper) :
520         AP4_CencSampleEncrypter(cipher, constant_iv),
521         m_ResetIvForEachSubsample(reset_iv_at_each_subsample),
522         m_SubSampleMapper(subsample_mapper) {}
~AP4_CencSubSampleEncrypter()523     virtual ~AP4_CencSubSampleEncrypter() {
524         delete m_SubSampleMapper;
525     }
526 
527     // methods
UseSubSamples()528     virtual bool UseSubSamples() { return true; }
GetSubSampleMap(AP4_DataBuffer & sample_data,AP4_Array<AP4_UI16> & bytes_of_cleartext_data,AP4_Array<AP4_UI32> & bytes_of_encrypted_data)529     virtual AP4_Result GetSubSampleMap(AP4_DataBuffer&      sample_data,
530                                        AP4_Array<AP4_UI16>& bytes_of_cleartext_data,
531                                        AP4_Array<AP4_UI32>& bytes_of_encrypted_data) {
532         return m_SubSampleMapper->GetSubSampleMap(sample_data, bytes_of_cleartext_data, bytes_of_encrypted_data);
533     }
534 
535     // members
536     bool                     m_ResetIvForEachSubsample;
537     AP4_CencSubSampleMapper* m_SubSampleMapper;
538 };
539 
540 /*----------------------------------------------------------------------
541 |   AP4_CencCtrSubSampleEncrypter
542 +---------------------------------------------------------------------*/
543 class AP4_CencCtrSubSampleEncrypter : public AP4_CencSubSampleEncrypter
544 {
545 public:
546     // constructor and destructor
AP4_CencCtrSubSampleEncrypter(AP4_StreamCipher * cipher,bool constant_iv,bool reset_iv_at_each_subsample,unsigned int iv_size,AP4_CencSubSampleMapper * subsample_mapper)547     AP4_CencCtrSubSampleEncrypter(AP4_StreamCipher*        cipher,
548                                   bool                     constant_iv,
549                                   bool                     reset_iv_at_each_subsample,
550                                   unsigned int             iv_size,
551                                   AP4_CencSubSampleMapper* subsample_mapper) :
552         AP4_CencSubSampleEncrypter(cipher,
553                                    constant_iv,
554                                    reset_iv_at_each_subsample,
555                                    subsample_mapper),
556         m_IvSize(iv_size) {}
557 
558     // methods
559     virtual AP4_Result EncryptSampleData(AP4_DataBuffer& data_in,
560                                          AP4_DataBuffer& data_out,
561                                          AP4_DataBuffer& sample_infos);
562 
563 protected:
564     unsigned int m_IvSize;
565 };
566 
567 /*----------------------------------------------------------------------
568 |   AP4_CencCbcSubSampleEncrypter
569 +---------------------------------------------------------------------*/
570 class AP4_CencCbcSubSampleEncrypter : public AP4_CencSubSampleEncrypter
571 {
572 public:
573     // constructor and destructor
AP4_CencCbcSubSampleEncrypter(AP4_StreamCipher * cipher,bool constant_iv,bool reset_iv_at_each_subsample,AP4_CencSubSampleMapper * subsample_mapper)574     AP4_CencCbcSubSampleEncrypter(AP4_StreamCipher*        cipher,
575                                   bool                     constant_iv,
576                                   bool                     reset_iv_at_each_subsample,
577                                   AP4_CencSubSampleMapper* subsample_mapper) :
578         AP4_CencSubSampleEncrypter(cipher,
579                                    constant_iv,
580                                    reset_iv_at_each_subsample,
581                                    subsample_mapper) {}
582 
583     // methods
584     virtual AP4_Result EncryptSampleData(AP4_DataBuffer& data_in,
585                                          AP4_DataBuffer& data_out,
586                                          AP4_DataBuffer& sample_infos);
587 };
588 
589 /*----------------------------------------------------------------------
590 |   AP4_CencEncryptingProcessor
591 +---------------------------------------------------------------------*/
592 class AP4_CencEncryptingProcessor : public AP4_Processor
593 {
594 public:
595     // class constants
596     static const AP4_UI32 OPTION_EME_PSSH           = 0x01; ///< Include a 'standard EME' pssh atom in the output
597     static const AP4_UI32 OPTION_PIFF_COMPATIBILITY = 0x02; ///< Attempt to create an output that is compatible with the PIFF format
598     static const AP4_UI32 OPTION_PIFF_IV_SIZE_16    = 0x04; ///< With the PIFF-compatibiity option, use an IV of size 16 when possible (instead of 8)
599     static const AP4_UI32 OPTION_IV_SIZE_8          = 0x08; ///< Use an IV of size 8 when possible (instead of 16 by default).
600     static const AP4_UI32 OPTION_NO_SENC            = 0x10; ///< Don't output an 'senc' atom
601 
602     // types
603     struct Encrypter {
EncrypterEncrypter604         Encrypter(AP4_UI32 track_id, AP4_UI32 cleartext_fragments, AP4_CencSampleEncrypter* sample_encrypter) :
605             m_TrackId(track_id),
606             m_CurrentFragment(0),
607             m_CleartextFragments(cleartext_fragments),
608             m_SampleEncrypter(sample_encrypter) {}
~EncrypterEncrypter609         ~Encrypter() { delete m_SampleEncrypter; }
610         AP4_UI32                 m_TrackId;
611         AP4_UI32                 m_CurrentFragment;
612         AP4_UI32                 m_CleartextFragments;
613         AP4_CencSampleEncrypter* m_SampleEncrypter;
614     };
615 
616     // constructor
617     AP4_CencEncryptingProcessor(AP4_CencVariant         variant,
618                                 AP4_UI32                options = 0,
619                                 AP4_BlockCipherFactory* block_cipher_factory = NULL);
620     ~AP4_CencEncryptingProcessor();
621 
622     // accessors
GetKeyMap()623     AP4_ProtectionKeyMap&     GetKeyMap()      { return m_KeyMap;      }
GetPropertyMap()624     AP4_TrackPropertyMap&     GetPropertyMap() { return m_PropertyMap; }
GetPsshAtoms()625     AP4_Array<AP4_PsshAtom*>& GetPsshAtoms()   { return m_PsshAtoms;   }
626 
627     // AP4_Processor methods
628     virtual AP4_Result Initialize(AP4_AtomParent&   top_level,
629                                   AP4_ByteStream&   stream,
630                                   AP4_Processor::ProgressListener* listener = NULL);
631     virtual AP4_Processor::TrackHandler*    CreateTrackHandler(AP4_TrakAtom* trak);
632     virtual AP4_Processor::FragmentHandler* CreateFragmentHandler(AP4_TrakAtom*      trak,
633                                                                   AP4_TrexAtom*      trex,
634                                                                   AP4_ContainerAtom* traf,
635                                                                   AP4_ByteStream&    moof_data,
636                                                                   AP4_Position       moof_offset);
637 
638 protected:
639     // members
640     AP4_CencVariant          m_Variant;
641     AP4_UI32                 m_Options;
642     AP4_BlockCipherFactory*  m_BlockCipherFactory;
643     AP4_ProtectionKeyMap     m_KeyMap;
644     AP4_TrackPropertyMap     m_PropertyMap;
645     AP4_Array<AP4_PsshAtom*> m_PsshAtoms;
646     AP4_List<Encrypter>      m_Encrypters;
647 };
648 
649 /*----------------------------------------------------------------------
650 |   AP4_CencDecryptingProcessor
651 +---------------------------------------------------------------------*/
652 class AP4_CencDecryptingProcessor : public AP4_Processor
653 {
654 public:
655     // constructor
656     AP4_CencDecryptingProcessor(const AP4_ProtectionKeyMap* key_map,
657                                 AP4_BlockCipherFactory*     block_cipher_factory = NULL);
658 
659     // AP4_Processor methods
660     virtual AP4_Processor::TrackHandler*    CreateTrackHandler(AP4_TrakAtom* trak);
661     virtual AP4_Processor::FragmentHandler* CreateFragmentHandler(AP4_TrakAtom*      trak,
662                                                                   AP4_TrexAtom*      trex,
663                                                                   AP4_ContainerAtom* traf,
664                                                                   AP4_ByteStream&    moof_data,
665                                                                   AP4_Position       moof_offset);
666 
667 protected:
668     // methods
669     const AP4_DataBuffer* GetKeyForTrak(AP4_UI32 track_id, AP4_ProtectedSampleDescription* sample_description);
670 
671     // members
672     AP4_BlockCipherFactory*     m_BlockCipherFactory;
673     const AP4_ProtectionKeyMap* m_KeyMap;
674 };
675 
676 /*----------------------------------------------------------------------
677 |   AP4_CencSingleSampleDecrypter
678 +---------------------------------------------------------------------*/
679 class AP4_CencSingleSampleDecrypter
680 {
681 public:
682     static AP4_Result Create(AP4_UI32                        cipher_type,
683                              const AP4_UI08*                 key,
684                              AP4_Size                        key_size,
685                              AP4_UI08                        crypt_byte_block,
686                              AP4_UI08                        skip_byte_block,
687                              AP4_BlockCipherFactory*         block_cipher_factory,
688                              bool                            reset_iv_at_each_subsample,
689                              AP4_CencSingleSampleDecrypter*& decrypter);
690 
691     // methods
AP4_CencSingleSampleDecrypter(AP4_StreamCipher * cipher)692     AP4_CencSingleSampleDecrypter(AP4_StreamCipher* cipher) :
693         m_Cipher(cipher),
694         m_FullBlocksOnly(false) {}
695     virtual ~AP4_CencSingleSampleDecrypter();
696     virtual AP4_Result DecryptSampleData(AP4_DataBuffer& data_in,
697                                          AP4_DataBuffer& data_out,
698 
699                                          // always 16 bytes
700                                          const AP4_UI08* iv,
701 
702                                          // pass 0 for full decryption
703                                          unsigned int    subsample_count,
704 
705                                          // array of <subsample_count> integers. NULL if subsample_count is 0
706                                          const AP4_UI16* bytes_of_cleartext_data,
707 
708                                          // array of <subsample_count> integers. NULL if subsample_count is 0
709                                          const AP4_UI32* bytes_of_encrypted_data);
710 
711 private:
712     // constructor
AP4_CencSingleSampleDecrypter(AP4_StreamCipher * cipher,bool full_blocks_only,bool reset_iv_at_each_subsample)713     AP4_CencSingleSampleDecrypter(AP4_StreamCipher* cipher,
714                                   bool              full_blocks_only,
715                                   bool              reset_iv_at_each_subsample) :
716         m_Cipher(cipher),
717         m_FullBlocksOnly(full_blocks_only),
718         m_ResetIvAtEachSubsample(reset_iv_at_each_subsample) {}
719 
720     // members
721     AP4_StreamCipher* m_Cipher;
722     bool              m_FullBlocksOnly;
723     bool              m_ResetIvAtEachSubsample;
724 };
725 
726 /*----------------------------------------------------------------------
727 |   AP4_CencSampleDecrypter
728 +---------------------------------------------------------------------*/
729 class AP4_CencSampleDecrypter : public AP4_SampleDecrypter
730 {
731 public:
732     static AP4_Result Create(AP4_ProtectedSampleDescription* sample_description,
733                              AP4_ContainerAtom*              traf,
734                              AP4_ByteStream&                 moof_data,
735                              AP4_Position                    moof_offset,
736                              const AP4_UI08*                 key,
737                              AP4_Size                        key_size,
738                              AP4_BlockCipherFactory*         block_cipher_factory,
739                              AP4_SaioAtom*&                  saio_atom,              // [out]
740                              AP4_SaizAtom*&                  saiz_atom,              // [out]
741                              AP4_CencSampleEncryption*&      sample_encryption_atom, // [out]
742                              AP4_CencSampleDecrypter*&       decrypter);
743 
744     static AP4_Result Create(AP4_ProtectedSampleDescription* sample_description,
745                              AP4_ContainerAtom*              traf,
746                              AP4_ByteStream&                 moof_data,
747                              AP4_Position                    moof_offset,
748                              const AP4_UI08*                 key,
749                              AP4_Size                        key_size,
750                              AP4_BlockCipherFactory*         block_cipher_factory,
751                              AP4_CencSampleDecrypter*&       decrypter);
752 
753     static AP4_Result Create(AP4_CencSampleInfoTable*  sample_info_table,
754                              AP4_UI32                  cipher_type,
755                              const AP4_UI08*           key,
756                              AP4_Size                  key_size,
757                              AP4_BlockCipherFactory*   block_cipher_factory,
758                              bool                      reset_iv_at_each_subsample,
759                              AP4_CencSampleDecrypter*& decrypter);
760 
761     // methods
AP4_CencSampleDecrypter(AP4_CencSingleSampleDecrypter * single_sample_decrypter,AP4_CencSampleInfoTable * sample_info_table)762     AP4_CencSampleDecrypter(AP4_CencSingleSampleDecrypter* single_sample_decrypter,
763                             AP4_CencSampleInfoTable*       sample_info_table) :
764         m_SingleSampleDecrypter(single_sample_decrypter),
765         m_SampleInfoTable(sample_info_table),
766         m_SampleCursor(0) {}
767     virtual ~AP4_CencSampleDecrypter();
768     virtual AP4_Result SetSampleIndex(AP4_Ordinal sample_index);
769     virtual AP4_Result DecryptSampleData(AP4_DataBuffer& data_in,
770                                          AP4_DataBuffer& data_out,
771                                          const AP4_UI08* iv);
772 
773 protected:
774     AP4_CencSingleSampleDecrypter* m_SingleSampleDecrypter;
775     AP4_CencSampleInfoTable*       m_SampleInfoTable;
776     AP4_Ordinal                    m_SampleCursor;
777 };
778 
779 /*----------------------------------------------------------------------
780 |   AP4_CencSampleEncryptionInformationGroupEntry
781 +---------------------------------------------------------------------*/
782 class AP4_CencSampleEncryptionInformationGroupEntry {
783 public:
784     AP4_CencSampleEncryptionInformationGroupEntry(const AP4_UI08* data);
785 
786     // accessors
IsEncrypted()787     bool            IsEncrypted() const { return m_IsEncrypted; }
GetIvSize()788     AP4_UI08        GetIvSize()   const { return m_IvSize;      }
GetKid()789     const AP4_UI08* GetKid()      const { return &m_KID[9];     }
790 
791 private:
792     // members
793     bool     m_IsEncrypted;
794     AP4_UI08 m_IvSize;
795     AP4_UI08 m_KID[16];
796 };
797 
798 #endif // _AP4_COMMON_ENCRYPTION_H_
799