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: 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 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 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 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 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 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 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 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 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 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 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 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