InitDataParser.cpp revision 6b3c1473199927264691bb50445cf0b35c2f8892
16b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce/* 26b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce * Copyright (C) 2014 The Android Open Source Project 36b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce * 46b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce * Licensed under the Apache License, Version 2.0 (the "License"); 56b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce * you may not use this file except in compliance with the License. 66b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce * You may obtain a copy of the License at 76b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce * 86b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce * http://www.apache.org/licenses/LICENSE-2.0 96b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce * 106b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce * Unless required by applicable law or agreed to in writing, software 116b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce * distributed under the License is distributed on an "AS IS" BASIS, 126b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce * See the License for the specific language governing permissions and 146b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce * limitations under the License. 156b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce */ 166b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 176b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce//#define LOG_NDEBUG 0 186b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce#define LOG_TAG "ClearKeyCryptoPlugin" 196b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce#include <utils/Log.h> 206b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 216b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce#include <endian.h> 226b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce#include <media/stagefright/foundation/AString.h> 236b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce#include <media/stagefright/foundation/base64.h> 246b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce#include <media/stagefright/MediaErrors.h> 256b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce#include <string.h> 266b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 276b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce#include "InitDataParser.h" 286b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 296b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce#include "ClearKeyUUID.h" 306b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce#include "Utils.h" 316b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 326b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Brucenamespace clearkeydrm { 336b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 346b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruceusing android::AString; 356b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruceusing android::String8; 366b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruceusing android::Vector; 376b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 386b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Brucenamespace { 396b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce const size_t kKeyIdSize = 16; 406b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce const size_t kSystemIdSize = 16; 416b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce} 426b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 436b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruceandroid::status_t InitDataParser::parse(const Vector<uint8_t>& initData, 446b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce const String8& initDataType, 456b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce Vector<uint8_t>* licenseRequest) { 466b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce // Build a list of the key IDs 476b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce Vector<const uint8_t*> keyIds; 486b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce if (initDataType == "cenc") { 496b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce android::status_t res = parsePssh(initData, &keyIds); 506b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce if (res != android::OK) { 516b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce return res; 526b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce } 536b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce } else if (initDataType == "webm") { 546b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce // WebM "init data" is just a single key ID 556b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce if (initData.size() != kKeyIdSize) { 566b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce return android::ERROR_DRM_CANNOT_HANDLE; 576b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce } 586b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce keyIds.push(initData.array()); 596b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce } else { 606b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce return android::ERROR_DRM_CANNOT_HANDLE; 616b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce } 626b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 636b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce // Build the request 646b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce String8 requestJson = generateRequest(keyIds); 656b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce licenseRequest->clear(); 666b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce licenseRequest->appendArray( 676b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce reinterpret_cast<const uint8_t*>(requestJson.string()), 686b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce requestJson.size()); 696b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce return android::OK; 706b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce} 716b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 726b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruceandroid::status_t InitDataParser::parsePssh(const Vector<uint8_t>& initData, 736b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce Vector<const uint8_t*>* keyIds) { 746b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce size_t readPosition = 0; 756b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 766b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce // Validate size field 776b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce uint32_t expectedSize = initData.size(); 786b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce expectedSize = htonl(expectedSize); 796b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce if (memcmp(&initData[readPosition], &expectedSize, 806b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce sizeof(expectedSize)) != 0) { 816b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce return android::ERROR_DRM_CANNOT_HANDLE; 826b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce } 836b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce readPosition += sizeof(expectedSize); 846b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 856b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce // Validate PSSH box identifier 866b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce const char psshIdentifier[4] = {'p', 's', 's', 'h'}; 876b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce if (memcmp(&initData[readPosition], psshIdentifier, 886b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce sizeof(psshIdentifier)) != 0) { 896b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce return android::ERROR_DRM_CANNOT_HANDLE; 906b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce } 916b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce readPosition += sizeof(psshIdentifier); 926b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 936b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce // Validate EME version number 946b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce const uint8_t psshVersion1[4] = {1, 0, 0, 0}; 956b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce if (memcmp(&initData[readPosition], psshVersion1, 966b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce sizeof(psshVersion1)) != 0) { 976b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce return android::ERROR_DRM_CANNOT_HANDLE; 986b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce } 996b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce readPosition += sizeof(psshVersion1); 1006b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 1016b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce // Validate system ID 1026b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce if (!isClearKeyUUID(&initData[readPosition])) { 1036b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce return android::ERROR_DRM_CANNOT_HANDLE; 1046b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce } 1056b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce readPosition += kSystemIdSize; 1066b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 1076b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce // Read key ID count 1086b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce uint32_t keyIdCount; 1096b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce memcpy(&keyIdCount, &initData[readPosition], sizeof(keyIdCount)); 1106b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce keyIdCount = ntohl(keyIdCount); 1116b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce readPosition += sizeof(keyIdCount); 1126b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce if (readPosition + (keyIdCount * kKeyIdSize) != 1136b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce initData.size() - sizeof(uint32_t)) { 1146b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce return android::ERROR_DRM_CANNOT_HANDLE; 1156b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce } 1166b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 1176b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce // Calculate the key ID offsets 1186b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce for (uint32_t i = 0; i < keyIdCount; ++i) { 1196b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce size_t keyIdPosition = readPosition + (i * kKeyIdSize); 1206b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce keyIds->push(&initData[keyIdPosition]); 1216b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce } 1226b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce return android::OK; 1236b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce} 1246b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 1256b3c1473199927264691bb50445cf0b35c2f8892John "Juce" BruceString8 InitDataParser::generateRequest(const Vector<const uint8_t*>& keyIds) { 1266b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce const String8 kRequestPrefix("{\"kids\":["); 1276b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce const String8 kRequestSuffix("],\"type\":\"temporary\"}"); 1286b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce const String8 kBase64Padding("="); 1296b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 1306b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce String8 request(kRequestPrefix); 1316b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce AString encodedId; 1326b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce for (size_t i = 0; i < keyIds.size(); ++i) { 1336b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce encodedId.clear(); 1346b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce android::encodeBase64(keyIds[i], kKeyIdSize, &encodedId); 1356b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce if (i != 0) { 1366b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce request.append(","); 1376b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce } 1386b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce request.appendFormat("\"%s\"", encodedId.c_str()); 1396b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce } 1406b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce request.append(kRequestSuffix); 1416b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 1426b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce // Android's Base64 encoder produces padding. EME forbids padding. 1436b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce request.removeAll(kBase64Padding); 1446b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce return request; 1456b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce} 1466b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce 1476b3c1473199927264691bb50445cf0b35c2f8892John "Juce" Bruce} // namespace clearkeydrm 148