1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/cdm/cenc_utils.h"
7 #include "media/base/bit_reader.h"
11 // The initialization data for encrypted media files using the ISO Common
12 // Encryption ('cenc') protection scheme may contain one or more protection
13 // system specific header ('pssh') boxes.
14 // ref: https://w3c.github.io/encrypted-media/cenc-format.html
16 // The format of a 'pssh' box is as follows:
17 // unsigned int(32) size;
18 // unsigned int(32) type = "pssh";
20 // unsigned int(64) largesize;
21 // } else if (size==0) {
22 // -- box extends to end of file
24 // unsigned int(8) version;
26 // unsigned int(8)[16] SystemID;
29 // unsigned int(32) KID_count;
31 // unsigned int(8)[16] KID;
34 // unsigned int(32) DataSize;
35 // unsigned int(8)[DataSize] Data;
37 // Minimum size of a 'pssh' box includes all the required fields (size, type,
38 // version, flags, SystemID, DataSize).
39 const int kMinimumBoxSizeInBytes
= 32;
41 // SystemID for the Common System.
42 // https://w3c.github.io/encrypted-media/cenc-format.html#common-system
43 const uint8 kCommonSystemId
[] = { 0x10, 0x77, 0xef, 0xec,
44 0xc0, 0xb2, 0x4d, 0x02,
45 0xac, 0xe3, 0x3c, 0x1e,
46 0x52, 0xe2, 0xfb, 0x4b };
54 // Helper function to read up to 32 bits from a bit stream.
55 static uint32
ReadBits(BitReader
* reader
, int num_bits
) {
56 DCHECK_GE(reader
->bits_available(), num_bits
);
57 DCHECK((num_bits
> 0) && (num_bits
<= 32));
59 reader
->ReadBits(num_bits
, &value
);
63 // Checks whether the next 16 bytes matches the Common SystemID.
64 // Assumes |reader| has enough data.
65 static bool IsCommonSystemID(BitReader
* reader
) {
66 for (uint32 i
= 0; i
< arraysize(kCommonSystemId
); ++i
) {
67 if (ReadBits(reader
, 8) != kCommonSystemId
[i
])
73 bool GetKeyIdsForCommonSystemId(const uint8
* input
,
75 std::vector
<std::vector
<uint8
>>* key_ids
) {
77 std::vector
<std::vector
<uint8
>> result
;
79 while (offset
< input_length
) {
80 BitReader
reader(input
+ offset
, input_length
- offset
);
82 // Enough data for a miniumum size 'pssh' box?
83 RCHECK(reader
.bits_available() >= kMinimumBoxSizeInBytes
* 8);
85 uint32 size
= ReadBits(&reader
, 32);
87 // Must be a 'pssh' box or else fail.
88 RCHECK(ReadBits(&reader
, 8) == 'p');
89 RCHECK(ReadBits(&reader
, 8) == 's');
90 RCHECK(ReadBits(&reader
, 8) == 's');
91 RCHECK(ReadBits(&reader
, 8) == 'h');
94 // If largesize > 2**32 it is too big.
95 RCHECK(ReadBits(&reader
, 32) == 0);
96 size
= ReadBits(&reader
, 32);
97 } else if (size
== 0) {
98 size
= input_length
- offset
;
101 // Check that the buffer contains at least size bytes.
102 RCHECK(static_cast<uint32
>(input_length
- offset
) >= size
);
104 // Update offset to point at the next 'pssh' box (may not be one).
107 // Check the version, as KIDs only available if version > 0.
108 uint8 version
= ReadBits(&reader
, 8);
112 // flags must be 0. If not, assume incorrect 'pssh' box and move to the
114 if (ReadBits(&reader
, 24) != 0)
118 RCHECK(static_cast<uint32
>(reader
.bits_available()) >=
119 arraysize(kCommonSystemId
) * 8);
120 if (!IsCommonSystemID(&reader
))
121 continue; // Not Common System, so try the next pssh box.
123 // Since version > 0, next field is the KID_count.
124 RCHECK(static_cast<uint32
>(reader
.bits_available()) >= sizeof(uint32
) * 8);
125 uint32 count
= ReadBits(&reader
, 32);
130 // Make sure there is enough data for all the KIDs specified, and then
132 RCHECK(static_cast<uint32
>(reader
.bits_available()) > count
* 16 * 8);
134 std::vector
<uint8
> key
;
136 for (int i
= 0; i
< 16; ++i
) {
137 key
.push_back(ReadBits(&reader
, 8));
139 result
.push_back(key
);
143 // Don't bother checking DataSize and Data.
146 key_ids
->swap(result
);
148 // TODO(jrummell): This should return true only if there was at least one
149 // key ID present. However, numerous test files don't contain the 'pssh' box
150 // for Common Format, so no keys are found. http://crbug.com/460308