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