1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License.
5094332d3Sopenharmony_ci * You may obtain a copy of the License at
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8094332d3Sopenharmony_ci *
9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and
13094332d3Sopenharmony_ci * limitations under the License.
14094332d3Sopenharmony_ci */
15094332d3Sopenharmony_ci
16094332d3Sopenharmony_ci#include <arpa/inet.h>
17094332d3Sopenharmony_ci#include <hdf_base.h>
18094332d3Sopenharmony_ci#include <hdf_log.h>
19094332d3Sopenharmony_ci#include <string>
20094332d3Sopenharmony_ci#include "clearplay_uuid.h"
21094332d3Sopenharmony_ci#include "mime_type.h"
22094332d3Sopenharmony_ci#include "base64_utils.h"
23094332d3Sopenharmony_ci#include "data_parser.h"
24094332d3Sopenharmony_ci#include "cJSON.h"
25094332d3Sopenharmony_ci#include "securec.h"
26094332d3Sopenharmony_ci
27094332d3Sopenharmony_ci#define HDF_LOG_TAG data_parse
28094332d3Sopenharmony_ci
29094332d3Sopenharmony_cinamespace OHOS {
30094332d3Sopenharmony_cinamespace HDI {
31094332d3Sopenharmony_cinamespace Drm {
32094332d3Sopenharmony_cinamespace V1_0 {
33094332d3Sopenharmony_ciint32_t ParsePssh(const std::vector<uint8_t> &initData, std::vector<std::vector<uint8_t>> &keyIds)
34094332d3Sopenharmony_ci{
35094332d3Sopenharmony_ci    HDF_LOGD("%{public}s: start", __func__);
36094332d3Sopenharmony_ci    size_t readPosition = 0;
37094332d3Sopenharmony_ci
38094332d3Sopenharmony_ci    // Validate size field
39094332d3Sopenharmony_ci    uint32_t expectedSize = initData.size();
40094332d3Sopenharmony_ci    expectedSize = htonl(expectedSize);
41094332d3Sopenharmony_ci    if (memcmp(&initData[readPosition], &expectedSize, sizeof(expectedSize)) != 0) {
42094332d3Sopenharmony_ci        HDF_LOGD("%{public}s: memcmp(&initData[readPosition], &expectedSize, sizeof(expectedSize)) != 0", __func__);
43094332d3Sopenharmony_ci    }
44094332d3Sopenharmony_ci    readPosition += sizeof(expectedSize);
45094332d3Sopenharmony_ci
46094332d3Sopenharmony_ci    // Validate PSSH box identifier
47094332d3Sopenharmony_ci    const char psshIdentifier[4] = {'p', 's', 's', 'h'};
48094332d3Sopenharmony_ci    if (memcmp(&initData[readPosition], psshIdentifier, sizeof(psshIdentifier)) != 0) {
49094332d3Sopenharmony_ci        HDF_LOGD("%{public}s: without \"pssh\"", __func__);
50094332d3Sopenharmony_ci    }
51094332d3Sopenharmony_ci    readPosition += sizeof(psshIdentifier);
52094332d3Sopenharmony_ci
53094332d3Sopenharmony_ci    // Validate EME version number
54094332d3Sopenharmony_ci    const uint8_t psshVersion1[4] = {1, 0, 0, 0};
55094332d3Sopenharmony_ci    const uint8_t psshVersion0[4] = {0, 0, 0, 0};
56094332d3Sopenharmony_ci    int psshVersionId = 0;
57094332d3Sopenharmony_ci    if (memcmp(&initData[readPosition], psshVersion0, sizeof(psshVersion0)) != 0) {
58094332d3Sopenharmony_ci        if (memcmp(&initData[readPosition], psshVersion1, sizeof(psshVersion1)) != 0) {
59094332d3Sopenharmony_ci            HDF_LOGD("%{public}s: psshVersion error", __func__);
60094332d3Sopenharmony_ci        }
61094332d3Sopenharmony_ci        psshVersionId = 1;
62094332d3Sopenharmony_ci    }
63094332d3Sopenharmony_ci    readPosition += sizeof(psshVersion1);
64094332d3Sopenharmony_ci
65094332d3Sopenharmony_ci    // Validate system ID
66094332d3Sopenharmony_ci    std::string uuid((reinterpret_cast<const char*>(initData.data())) + readPosition, CLEARPLAY_NAME.size());
67094332d3Sopenharmony_ci    if (IsClearPlayUuid(uuid)) {
68094332d3Sopenharmony_ci        HDF_LOGD("%{public}s: uuid error", __func__);
69094332d3Sopenharmony_ci    }
70094332d3Sopenharmony_ci    readPosition += SYSTEM_ID_SIZE;
71094332d3Sopenharmony_ci
72094332d3Sopenharmony_ci    if (psshVersionId == 0) {
73094332d3Sopenharmony_ci        std::vector<uint8_t> keyIdString = { 'k', 'i', 'd', 's' };
74094332d3Sopenharmony_ci        int32_t keyIdPos = findSubVector(initData, keyIdString);
75094332d3Sopenharmony_ci        if (keyIdPos == -1) {
76094332d3Sopenharmony_ci            HDF_LOGD("%{public}s: without \"kids\"", __func__);
77094332d3Sopenharmony_ci        }
78094332d3Sopenharmony_ci        while (keyIdPos < initData.size() && initData[keyIdPos] != '[') {
79094332d3Sopenharmony_ci            ++keyIdPos;
80094332d3Sopenharmony_ci        }
81094332d3Sopenharmony_ci        std::string keyIdBase64 = "";
82094332d3Sopenharmony_ci        bool isLeft = false;
83094332d3Sopenharmony_ci        while (keyIdPos < initData.size() && initData[keyIdPos] != ']') {
84094332d3Sopenharmony_ci            if (initData[keyIdPos] == '"') {
85094332d3Sopenharmony_ci                isLeft = !isLeft;
86094332d3Sopenharmony_ci                if (!isLeft) {
87094332d3Sopenharmony_ci                    std::string keyIdString = Decode(keyIdBase64);
88094332d3Sopenharmony_ci                    keyIdBase64 = "";
89094332d3Sopenharmony_ci                    std::vector<uint8_t> keyId(keyIdString.begin(), keyIdString.end());
90094332d3Sopenharmony_ci                    keyIds.push_back(keyId);
91094332d3Sopenharmony_ci                }
92094332d3Sopenharmony_ci            } else if (isLeft) {
93094332d3Sopenharmony_ci                keyIdBase64 += initData[keyIdPos];
94094332d3Sopenharmony_ci            }
95094332d3Sopenharmony_ci            ++keyIdPos;
96094332d3Sopenharmony_ci        }
97094332d3Sopenharmony_ci        if (keyIdPos == initData.size()) {
98094332d3Sopenharmony_ci            HDF_LOGD("%{public}s: kids parse error", __func__);
99094332d3Sopenharmony_ci        }
100094332d3Sopenharmony_ci    } else if (psshVersionId == 1) {
101094332d3Sopenharmony_ci        // Read key ID count
102094332d3Sopenharmony_ci        uint32_t keyIdCount;
103094332d3Sopenharmony_ci        int32_t ret = HDF_FAILURE;
104094332d3Sopenharmony_ci        ret = memcpy_s(&keyIdCount, sizeof(keyIdCount), &initData[readPosition], sizeof(keyIdCount));
105094332d3Sopenharmony_ci        if(ret != 0) {
106094332d3Sopenharmony_ci            HDF_LOGE("%{public}s: memcpy_s faild", __func__);
107094332d3Sopenharmony_ci            return HDF_ERR_INVALID_PARAM;
108094332d3Sopenharmony_ci        }
109094332d3Sopenharmony_ci        keyIdCount = ntohl(keyIdCount);
110094332d3Sopenharmony_ci        readPosition += sizeof(keyIdCount);
111094332d3Sopenharmony_ci
112094332d3Sopenharmony_ci        // Calculate the key ID offsets
113094332d3Sopenharmony_ci        for (uint32_t i = 0; i < keyIdCount; ++i) {
114094332d3Sopenharmony_ci            std::vector<uint8_t> keyId;
115094332d3Sopenharmony_ci            for (size_t j = 0; i < KEY_ID_SIZE; ++j) {
116094332d3Sopenharmony_ci                keyId.push_back(initData[readPosition + i * KEY_ID_SIZE + j]);
117094332d3Sopenharmony_ci            }
118094332d3Sopenharmony_ci            keyIds.push_back(keyId);
119094332d3Sopenharmony_ci        }
120094332d3Sopenharmony_ci    }
121094332d3Sopenharmony_ci    return HDF_SUCCESS;
122094332d3Sopenharmony_ci}
123094332d3Sopenharmony_ci
124094332d3Sopenharmony_ciint32_t generateRequest(const MediaKeyType keyType, const std::vector<std::vector<uint8_t>> &keyIds,
125094332d3Sopenharmony_ci    std::string *request)
126094332d3Sopenharmony_ci{
127094332d3Sopenharmony_ci    // begin
128094332d3Sopenharmony_ci    *request = "{\"kids\":[";
129094332d3Sopenharmony_ci    std::string encodedKeyId;
130094332d3Sopenharmony_ci    for (size_t i = 0; i < keyIds.size(); ++i) {
131094332d3Sopenharmony_ci        encodedKeyId.clear();
132094332d3Sopenharmony_ci        std::string keyId(keyIds[i].begin(), keyIds[i].end());
133094332d3Sopenharmony_ci        encodedKeyId = Encode(keyId);
134094332d3Sopenharmony_ci        if (i != 0) {
135094332d3Sopenharmony_ci            request->append(",");
136094332d3Sopenharmony_ci        }
137094332d3Sopenharmony_ci        request->append("\"");
138094332d3Sopenharmony_ci        request->append(encodedKeyId);
139094332d3Sopenharmony_ci        request->append("\"");
140094332d3Sopenharmony_ci    }
141094332d3Sopenharmony_ci    if (keyType == MEDIA_KEY_TYPE_ONLINE) {
142094332d3Sopenharmony_ci        request->append("],\"type\":\"temporary\"}");
143094332d3Sopenharmony_ci    } else if (keyType == MEDIA_KEY_TYPE_OFFLINE) {
144094332d3Sopenharmony_ci        request->append("],\"type\":\"persistent-license\"}");
145094332d3Sopenharmony_ci    } else {
146094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
147094332d3Sopenharmony_ci    }
148094332d3Sopenharmony_ci    return HDF_SUCCESS;
149094332d3Sopenharmony_ci}
150094332d3Sopenharmony_ci
151094332d3Sopenharmony_ciint32_t findSubVector(const std::vector<uint8_t> &main, const std::vector<uint8_t> &sub)
152094332d3Sopenharmony_ci{
153094332d3Sopenharmony_ci    for (size_t i = 0; i < main.size(); ++i) {
154094332d3Sopenharmony_ci        size_t j = 0;
155094332d3Sopenharmony_ci        for (j = 0; j < sub.size() && main[i + j] == sub[j]; ++j) {
156094332d3Sopenharmony_ci        }
157094332d3Sopenharmony_ci        // for j end
158094332d3Sopenharmony_ci        if (j == sub.size()) {
159094332d3Sopenharmony_ci            return i;
160094332d3Sopenharmony_ci        }
161094332d3Sopenharmony_ci    }
162094332d3Sopenharmony_ci    return -1;
163094332d3Sopenharmony_ci}
164094332d3Sopenharmony_ci} // V1_0
165094332d3Sopenharmony_ci} // Drm
166094332d3Sopenharmony_ci} // HDI
167094332d3Sopenharmony_ci} // OHOS