1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <gtest/gtest.h>
18 #include <string.h>
19
20 #include <media/stagefright/foundation/AString.h>
21 #include <media/stagefright/foundation/base64.h>
22 #include <utils/String8.h>
23 #include <utils/Vector.h>
24
25 #include "InitDataParser.h"
26
27 namespace clearkeydrm {
28
29 using namespace android;
30
31 namespace {
32 const size_t kKeyIdSize = 16;
33 const String8 kCencMimeType("video/mp4");
34 const String8 kWebmMimeType("video/webm");
35 const String8 kBase64Padding("=");
36 }
37
38 class InitDataParserTest : public ::testing::Test {
39 protected:
attemptParse(const Vector<uint8_t> & initData,const String8 & mimeType,Vector<uint8_t> * licenseRequest)40 status_t attemptParse(const Vector<uint8_t>& initData,
41 const String8& mimeType,
42 Vector<uint8_t>* licenseRequest) {
43 InitDataParser parser;
44 return parser.parse(initData, mimeType, licenseRequest);
45 }
46
attemptParseExpectingSuccess(const Vector<uint8_t> & initData,const String8 & mimeType,const Vector<String8> & expectedKeys)47 void attemptParseExpectingSuccess(const Vector<uint8_t>& initData,
48 const String8& mimeType,
49 const Vector<String8>& expectedKeys) {
50 const String8 kRequestPrefix("{\"kids\":[");
51 const String8 kRequestSuffix("],\"type\":\"temporary\"}");
52 Vector<uint8_t> request;
53 ASSERT_EQ(android::OK, attemptParse(initData, mimeType, &request));
54
55 String8 requestString(reinterpret_cast<const char*>(request.array()),
56 request.size());
57 EXPECT_EQ(0, requestString.find(kRequestPrefix));
58 EXPECT_EQ(requestString.size() - kRequestSuffix.size(),
59 (size_t)requestString.find(kRequestSuffix));
60 for (size_t i = 0; i < expectedKeys.size(); ++i) {
61 AString encodedIdAString;
62 android::encodeBase64Url(expectedKeys[i], kKeyIdSize,
63 &encodedIdAString);
64 String8 encodedId(encodedIdAString.c_str());
65 encodedId.removeAll(kBase64Padding);
66 EXPECT_TRUE(requestString.contains(encodedId));
67 }
68 }
69
attemptParseExpectingFailure(const Vector<uint8_t> & initData,const String8 & mimeType)70 void attemptParseExpectingFailure(const Vector<uint8_t>& initData,
71 const String8& mimeType) {
72 Vector<uint8_t> request;
73 ASSERT_NE(android::OK, attemptParse(initData, mimeType, &request));
74 EXPECT_EQ(0u, request.size());
75 }
76 };
77
TEST_F(InitDataParserTest,ParsesSingleKeyPssh)78 TEST_F(InitDataParserTest, ParsesSingleKeyPssh) {
79 uint8_t pssh[52] = {
80 0, 0, 0, 52, // Total Size
81 'p', 's', 's', 'h', // PSSH
82 1, 0, 0, 0, // Version
83 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, // System ID
84 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b,
85 0, 0, 0, 1, // Key Count
86 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // Key ID #1
87 0x38, 0x39, 0x30, 0x41, 0x42, 0x43, 0x44, 0x45, // "01234567890ABCDE"
88 0, 0, 0, 0 // Data Size (always 0)
89 };
90 Vector<uint8_t> initData;
91 initData.appendArray(pssh, 52);
92
93 Vector<String8> expectedKeys;
94 expectedKeys.push(String8("01234567890ABCDE"));
95
96 attemptParseExpectingSuccess(initData, kCencMimeType, expectedKeys);
97 }
98
TEST_F(InitDataParserTest,ParsesMultipleKeyPssh)99 TEST_F(InitDataParserTest, ParsesMultipleKeyPssh) {
100 uint8_t pssh[84] = {
101 0, 0, 0, 84, // Total Size
102 'p', 's', 's', 'h', // PSSH
103 1, 0, 0, 0, // Version
104 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, // System ID
105 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b,
106 0, 0, 0, 3, // Key Count
107 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // Key ID #1
108 0x38, 0x39, 0x30, 0x41, 0x42, 0x43, 0x44, 0x45, // "01234567890ABCDE"
109 0x43, 0x6c, 0x65, 0x61, 0x72, 0x4b, 0x65, 0x79, // Key ID #2
110 0x43, 0x6c, 0x65, 0x61, 0x72, 0x4b, 0x65, 0x79, // "ClearKeyClearKey"
111 0x20, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x20, // Key ID #3
112 0x20, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x20, // " GOOGLE GOOGLE "
113 0, 0, 0, 0 // Data Size (always 0)
114 };
115 Vector<uint8_t> initData;
116 initData.appendArray(pssh, 84);
117
118 Vector<String8> expectedKeys;
119 expectedKeys.push(String8("01234567890ABCDE"));
120 expectedKeys.push(String8("ClearKeyClearKey"));
121 expectedKeys.push(String8(" GOOGLE GOOGLE "));
122
123 attemptParseExpectingSuccess(initData, kCencMimeType, expectedKeys);
124 }
125
TEST_F(InitDataParserTest,ParsesWebM)126 TEST_F(InitDataParserTest, ParsesWebM) {
127 uint8_t initDataRaw[16] = {
128 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // Key ID
129 0x38, 0x39, 0x30, 0x41, 0x42, 0x43, 0x44, 0x45, // "01234567890ABCDE"
130 };
131 Vector<uint8_t> initData;
132 initData.appendArray(initDataRaw, 16);
133
134 Vector<String8> expectedKeys;
135 expectedKeys.push(String8("01234567890ABCDE"));
136
137 attemptParseExpectingSuccess(initData, kWebmMimeType, expectedKeys);
138 }
139
TEST_F(InitDataParserTest,FailsForPsshTooSmall)140 TEST_F(InitDataParserTest, FailsForPsshTooSmall) {
141 uint8_t pssh[16] = {
142 0, 0, 0, 52,
143 'p', 's', 's', 'h',
144 1, 0, 0, 0,
145 0x10, 0x77, 0xef, 0xec
146 };
147 Vector<uint8_t> initData;
148 initData.appendArray(pssh, 16);
149
150 attemptParseExpectingFailure(initData, kCencMimeType);
151 }
152
TEST_F(InitDataParserTest,FailsForWebMTooSmall)153 TEST_F(InitDataParserTest, FailsForWebMTooSmall) {
154 uint8_t initDataRaw[8] = {
155 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
156 };
157 Vector<uint8_t> initData;
158 initData.appendArray(initDataRaw, 8);
159
160 attemptParseExpectingFailure(initData, kWebmMimeType);
161 }
162
TEST_F(InitDataParserTest,FailsForPsshBadSystemId)163 TEST_F(InitDataParserTest, FailsForPsshBadSystemId) {
164 uint8_t pssh[52] = {
165 0, 0, 0, 52, // Total Size
166 'p', 's', 's', 'h', // PSSH
167 1, 0, 0, 0, // Version
168 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b, // System ID
169 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02,
170 0, 0, 0, 1, // Key Count
171 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // Key ID #1
172 0x38, 0x39, 0x30, 0x41, 0x42, 0x43, 0x44, 0x45, // "01234567890ABCDE"
173 0, 0, 0, 0 // Data Size (always 0)
174 };
175 Vector<uint8_t> initData;
176 initData.appendArray(pssh, 52);
177
178 attemptParseExpectingFailure(initData, kCencMimeType);
179 }
180
TEST_F(InitDataParserTest,FailsForPsshBadSize)181 TEST_F(InitDataParserTest, FailsForPsshBadSize) {
182 uint8_t pssh[52] = {
183 0, 0, 70, 200, // Total Size
184 'p', 's', 's', 'h', // PSSH
185 1, 0, 0, 0, // Version
186 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, // System ID
187 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b,
188 0, 0, 0, 1, // Key Count
189 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // Key ID #1
190 0x38, 0x39, 0x30, 0x41, 0x42, 0x43, 0x44, 0x45, // "01234567890ABCDE"
191 0, 0, 0, 0 // Data Size (always 0)
192 };
193 Vector<uint8_t> initData;
194 initData.appendArray(pssh, 52);
195
196 attemptParseExpectingFailure(initData, kCencMimeType);
197 }
198
TEST_F(InitDataParserTest,FailsForPsshWrongVersion)199 TEST_F(InitDataParserTest, FailsForPsshWrongVersion) {
200 uint8_t pssh[52] = {
201 0, 0, 0, 52, // Total Size
202 'p', 's', 's', 'h', // PSSH
203 0, 0, 0, 0, // Version
204 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, // System ID
205 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b,
206 0, 0, 0, 1, // Key Count
207 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // Key ID #1
208 0x38, 0x39, 0x30, 0x41, 0x42, 0x43, 0x44, 0x45, // "01234567890ABCDE"
209 0, 0, 0, 0 // Data Size (always 0)
210 };
211 Vector<uint8_t> initData;
212 initData.appendArray(pssh, 52);
213
214 attemptParseExpectingFailure(initData, kCencMimeType);
215 }
216
TEST_F(InitDataParserTest,FailsForPsshBadKeyCount)217 TEST_F(InitDataParserTest, FailsForPsshBadKeyCount) {
218 uint8_t pssh[52] = {
219 0, 0, 0, 52, // Total Size
220 'p', 's', 's', 'h', // PSSH
221 1, 0, 0, 0, // Version
222 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, // System ID
223 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b,
224 0, 0, 0, 7, // Key Count
225 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // Key ID #1
226 0x38, 0x39, 0x30, 0x41, 0x42, 0x43, 0x44, 0x45, // "01234567890ABCDE"
227 0, 0, 0, 0 // Data Size (always 0)
228 };
229 Vector<uint8_t> initData;
230 initData.appendArray(pssh, 52);
231
232 attemptParseExpectingFailure(initData, kCencMimeType);
233 }
234 } // namespace clearkeydrm
235