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