OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/cdm/cenc_utils.h" | 5 #include "media/cdm/cenc_utils.h" |
6 | 6 |
7 #include "media/base/bit_reader.h" | 7 #include "media/base/bit_reader.h" |
8 | 8 |
9 namespace media { | 9 namespace media { |
10 | 10 |
(...skipping 22 matching lines...) Expand all Loading... |
33 // } | 33 // } |
34 // unsigned int(32) DataSize; | 34 // unsigned int(32) DataSize; |
35 // unsigned int(8)[DataSize] Data; | 35 // unsigned int(8)[DataSize] Data; |
36 | 36 |
37 // Minimum size of a 'pssh' box includes all the required fields (size, type, | 37 // Minimum size of a 'pssh' box includes all the required fields (size, type, |
38 // version, flags, SystemID, DataSize). | 38 // version, flags, SystemID, DataSize). |
39 const int kMinimumBoxSizeInBytes = 32; | 39 const int kMinimumBoxSizeInBytes = 32; |
40 | 40 |
41 // SystemID for the Common System. | 41 // SystemID for the Common System. |
42 // https://w3c.github.io/encrypted-media/cenc-format.html#common-system | 42 // https://w3c.github.io/encrypted-media/cenc-format.html#common-system |
43 const uint8 kCommonSystemId[] = { 0x10, 0x77, 0xef, 0xec, | 43 const uint8_t kCommonSystemId[] = { 0x10, 0x77, 0xef, 0xec, |
44 0xc0, 0xb2, 0x4d, 0x02, | 44 0xc0, 0xb2, 0x4d, 0x02, |
45 0xac, 0xe3, 0x3c, 0x1e, | 45 0xac, 0xe3, 0x3c, 0x1e, |
46 0x52, 0xe2, 0xfb, 0x4b }; | 46 0x52, 0xe2, 0xfb, 0x4b }; |
47 | 47 |
48 #define RCHECK(x) \ | 48 #define RCHECK(x) \ |
49 do { \ | 49 do { \ |
50 if (!(x)) \ | 50 if (!(x)) \ |
51 return false; \ | 51 return false; \ |
52 } while (0) | 52 } while (0) |
53 | 53 |
54 // Helper function to read up to 32 bits from a bit stream. | 54 // Helper function to read up to 32 bits from a bit stream. |
55 static uint32 ReadBits(BitReader* reader, int num_bits) { | 55 static uint32_t ReadBits(BitReader* reader, int num_bits) { |
56 DCHECK_GE(reader->bits_available(), num_bits); | 56 DCHECK_GE(reader->bits_available(), num_bits); |
57 DCHECK((num_bits > 0) && (num_bits <= 32)); | 57 DCHECK((num_bits > 0) && (num_bits <= 32)); |
58 uint32 value; | 58 uint32_t value; |
59 reader->ReadBits(num_bits, &value); | 59 reader->ReadBits(num_bits, &value); |
60 return value; | 60 return value; |
61 } | 61 } |
62 | 62 |
63 // Checks whether the next 16 bytes matches the Common SystemID. | 63 // Checks whether the next 16 bytes matches the Common SystemID. |
64 // Assumes |reader| has enough data. | 64 // Assumes |reader| has enough data. |
65 static bool IsCommonSystemID(BitReader* reader) { | 65 static bool IsCommonSystemID(BitReader* reader) { |
66 for (uint32 i = 0; i < arraysize(kCommonSystemId); ++i) { | 66 for (uint32_t i = 0; i < arraysize(kCommonSystemId); ++i) { |
67 if (ReadBits(reader, 8) != kCommonSystemId[i]) | 67 if (ReadBits(reader, 8) != kCommonSystemId[i]) |
68 return false; | 68 return false; |
69 } | 69 } |
70 return true; | 70 return true; |
71 } | 71 } |
72 | 72 |
73 // Checks that |reader| contains a valid 'ppsh' box header. |reader| is updated | 73 // Checks that |reader| contains a valid 'ppsh' box header. |reader| is updated |
74 // to point to the content immediately following the box header. Returns true | 74 // to point to the content immediately following the box header. Returns true |
75 // if the header looks valid and |reader| contains enough data for the size of | 75 // if the header looks valid and |reader| contains enough data for the size of |
76 // header. |size| is updated as the computed size of the box header. Otherwise | 76 // header. |size| is updated as the computed size of the box header. Otherwise |
(...skipping 16 matching lines...) Expand all Loading... |
93 RCHECK(ReadBits(reader, 32) == 0); | 93 RCHECK(ReadBits(reader, 32) == 0); |
94 *size = ReadBits(reader, 32); | 94 *size = ReadBits(reader, 32); |
95 } else if (*size == 0) { | 95 } else if (*size == 0) { |
96 *size = available_bytes; | 96 *size = available_bytes; |
97 } | 97 } |
98 | 98 |
99 // Check that the buffer contains at least size bytes. | 99 // Check that the buffer contains at least size bytes. |
100 return available_bytes >= *size; | 100 return available_bytes >= *size; |
101 } | 101 } |
102 | 102 |
103 bool ValidatePsshInput(const uint8* input, size_t input_length) { | 103 bool ValidatePsshInput(const std::vector<uint8_t>& input) { |
104 size_t offset = 0; | 104 size_t offset = 0; |
105 while (offset < input_length) { | 105 while (offset < input.size()) { |
106 // Create a BitReader over the remaining part of the buffer. | 106 // Create a BitReader over the remaining part of the buffer. |
107 BitReader reader(input + offset, input_length - offset); | 107 BitReader reader(&input[offset], input.size() - offset); |
108 uint32 size; | 108 uint32 size; |
109 RCHECK(ValidBoxHeader(&reader, &size)); | 109 RCHECK(ValidBoxHeader(&reader, &size)); |
110 | 110 |
111 // Update offset to point at the next 'pssh' box (may not be one). | 111 // Update offset to point at the next 'pssh' box (may not be one). |
112 offset += size; | 112 offset += size; |
113 } | 113 } |
114 | 114 |
115 // Only valid if this contains 0 or more 'pssh' boxes. | 115 // Only valid if this contains 0 or more 'pssh' boxes. |
116 return offset == input_length; | 116 return offset == input.size(); |
117 } | 117 } |
118 | 118 |
119 bool GetKeyIdsForCommonSystemId(const uint8* input, | 119 bool GetKeyIdsForCommonSystemId(const std::vector<uint8_t>& input, |
120 int input_length, | 120 KeyIdList* key_ids) { |
121 std::vector<std::vector<uint8>>* key_ids) { | 121 size_t offset = 0; |
122 int offset = 0; | 122 KeyIdList result; |
123 std::vector<std::vector<uint8>> result; | |
124 | 123 |
125 while (offset < input_length) { | 124 while (offset < input.size()) { |
126 // Create a BitReader over the remaining part of the buffer. | 125 BitReader reader(&input[offset], input.size() - offset); |
127 BitReader reader(input + offset, input_length - offset); | |
128 uint32 size; | 126 uint32 size; |
129 RCHECK(ValidBoxHeader(&reader, &size)); | 127 RCHECK(ValidBoxHeader(&reader, &size)); |
130 | 128 |
131 // Update offset to point at the next 'pssh' box (may not be one). | 129 // Update offset to point at the next 'pssh' box (may not be one). |
132 offset += size; | 130 offset += size; |
133 | 131 |
134 // Check the version, as KIDs only available if version > 0. | 132 // Check the version, as KIDs only available if version > 0. |
135 uint8 version = ReadBits(&reader, 8); | 133 uint8_t version = ReadBits(&reader, 8); |
136 if (version == 0) | 134 if (version == 0) |
137 continue; | 135 continue; |
138 | 136 |
139 // flags must be 0. If not, assume incorrect 'pssh' box and move to the | 137 // flags must be 0. If not, assume incorrect 'pssh' box and move to the |
140 // next one. | 138 // next one. |
141 if (ReadBits(&reader, 24) != 0) | 139 if (ReadBits(&reader, 24) != 0) |
142 continue; | 140 continue; |
143 | 141 |
144 // Validate SystemID | 142 // Validate SystemID |
145 RCHECK(static_cast<uint32>(reader.bits_available()) >= | 143 RCHECK(static_cast<uint32_t>(reader.bits_available()) >= |
146 arraysize(kCommonSystemId) * 8); | 144 arraysize(kCommonSystemId) * 8); |
147 if (!IsCommonSystemID(&reader)) | 145 if (!IsCommonSystemID(&reader)) |
148 continue; // Not Common System, so try the next pssh box. | 146 continue; // Not Common System, so try the next pssh box. |
149 | 147 |
150 // Since version > 0, next field is the KID_count. | 148 // Since version > 0, next field is the KID_count. |
151 RCHECK(static_cast<uint32>(reader.bits_available()) >= sizeof(uint32) * 8); | 149 RCHECK(static_cast<uint32_t>(reader.bits_available()) >= |
152 uint32 count = ReadBits(&reader, 32); | 150 sizeof(uint32_t) * 8); |
| 151 uint32_t count = ReadBits(&reader, 32); |
153 | 152 |
154 if (count == 0) | 153 if (count == 0) |
155 continue; | 154 continue; |
156 | 155 |
157 // Make sure there is enough data for all the KIDs specified, and then | 156 // Make sure there is enough data for all the KIDs specified, and then |
158 // extract them. | 157 // extract them. |
159 RCHECK(static_cast<uint32>(reader.bits_available()) > count * 16 * 8); | 158 RCHECK(static_cast<uint32_t>(reader.bits_available()) > count * 16 * 8); |
160 while (count > 0) { | 159 while (count > 0) { |
161 std::vector<uint8> key; | 160 std::vector<uint8_t> key; |
162 key.reserve(16); | 161 key.reserve(16); |
163 for (int i = 0; i < 16; ++i) { | 162 for (int i = 0; i < 16; ++i) { |
164 key.push_back(ReadBits(&reader, 8)); | 163 key.push_back(ReadBits(&reader, 8)); |
165 } | 164 } |
166 result.push_back(key); | 165 result.push_back(key); |
167 --count; | 166 --count; |
168 } | 167 } |
169 | 168 |
170 // Don't bother checking DataSize and Data. | 169 // Don't bother checking DataSize and Data. |
171 } | 170 } |
172 | 171 |
173 key_ids->swap(result); | 172 key_ids->swap(result); |
174 | 173 |
175 // TODO(jrummell): This should return true only if there was at least one | 174 // TODO(jrummell): This should return true only if there was at least one |
176 // key ID present. However, numerous test files don't contain the 'pssh' box | 175 // key ID present. However, numerous test files don't contain the 'pssh' box |
177 // for Common Format, so no keys are found. http://crbug.com/460308 | 176 // for Common Format, so no keys are found. http://crbug.com/460308 |
178 return true; | 177 return true; |
179 } | 178 } |
180 | 179 |
181 } // namespace media | 180 } // namespace media |
OLD | NEW |