1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "dm_auth_attest_common.h"
17
18 #include "dm_error_type.h"
19 #include "dm_log.h"
20
21 namespace OHOS {
22 namespace DistributedHardware {
23
24 constexpr int32_t HEX_TO_UINT8 = 2;
25
AuthAttestCommon()26 AuthAttestCommon::AuthAttestCommon()
27 {
28 LOGD("AuthAttestCommon constructor");
29 }
30
~AuthAttestCommon()31 AuthAttestCommon::~AuthAttestCommon()
32 {
33 LOGD("AuthAttestCommon destructor");
34 }
35
SerializeDmCertChain(const DmCertChain * chain)36 std::string AuthAttestCommon::SerializeDmCertChain(const DmCertChain *chain)
37 {
38 if (chain == nullptr || chain->cert == nullptr || chain->certCount != DM_CERTS_COUNT) {
39 LOGE("input param is invalid.");
40 return "{}";
41 }
42 JsonObject jsonObject;
43 jsonObject[TAG_CERT_COUNT] = chain->certCount;
44 JsonObject jsonArrayObj(JsonCreateType::JSON_CREATE_TYPE_ARRAY);
45 for (uint32_t i = 0; i < chain->certCount; ++i) {
46 const DmBlob &blob = chain->cert[i];
47 if (blob.data == nullptr || blob.size == 0 || blob.size > DM_CERTIFICATE_SIZE) {
48 LOGE("Invalid blob: null data or invalid size.");
49 return "{}";
50 }
51 const uint32_t hexLen = blob.size * HEX_TO_UINT8 + 1; // 2*blob.size + 1
52 char *hexBuffer = new char[hexLen]{0};
53 if (hexBuffer == nullptr) {
54 LOGE("hexBuffer malloc failed.");
55 return "{}";
56 }
57 int32_t ret = Crypto::ConvertBytesToHexString(hexBuffer, hexLen, blob.data, blob.size);
58 if (ret != DM_OK) {
59 LOGE("ConvertBytesToHexString failed.");
60 delete[] hexBuffer;
61 return "{}";
62 }
63 jsonArrayObj.PushBack(std::string(hexBuffer));
64 delete[] hexBuffer;
65 }
66 jsonObject.Insert(TAG_CERT, jsonArrayObj);
67 return jsonObject.Dump();
68 }
69
70 //LCOV_EXCL_START
ValidateInputJson(const std::string & data)71 bool ValidateInputJson(const std::string &data)
72 {
73 JsonObject jsonObject;
74 jsonObject.Parse(data);
75 if (!IsUint32(jsonObject, TAG_CERT_COUNT) || !jsonObject.Contains(TAG_CERT)) {
76 LOGE("Missing required fields 'certCount' or 'cert'");
77 return false;
78 }
79 const uint32_t certCount = jsonObject[TAG_CERT_COUNT].Get<uint32_t>();
80 if (certCount != DM_CERTS_COUNT) {
81 LOGE("Invalid certCount value %{public}u", certCount);
82 return false;
83 }
84 JsonObject jsonArrayObj(JsonCreateType::JSON_CREATE_TYPE_ARRAY);
85 jsonArrayObj.Parse(jsonObject[TAG_CERT].Dump());
86 const uint32_t certSize = jsonArrayObj.Items().size();
87 if (certSize != certCount) {
88 LOGE("certSize = %{public}u is invalid.", certSize);
89 return false;
90 }
91 return true;
92 }
93
ProcessCertItem(const JsonItemObject & item,DmBlob & cert,uint32_t processedIndex)94 bool ProcessCertItem(const JsonItemObject &item, DmBlob &cert, uint32_t processedIndex)
95 {
96 if (!item.IsString()) {
97 LOGE("input param is invalid.");
98 return false;
99 }
100 std::string hexStr = item.Get<std::string>();
101 const size_t hexLen = hexStr.length();
102 if (hexLen == 0 || hexLen % HEX_TO_UINT8 != 0) {
103 LOGE("Invalid HEX length %{public}zu at index %{public}u", hexLen, processedIndex);
104 return false;
105 }
106 const uint32_t binSize = hexLen / HEX_TO_UINT8;
107 if (binSize > DM_CERTIFICATE_SIZE) {
108 LOGE("binSize = %{public}u is invalid.", binSize);
109 return false;
110 }
111 cert.data = new uint8_t[binSize]{0};
112 if (cert.data == nullptr) {
113 LOGE("Data allocation failed at index %{public}u", processedIndex);
114 return false;
115 }
116 int32_t ret = Crypto::ConvertHexStringToBytes(cert.data, binSize, hexStr.c_str(), hexLen);
117 if (ret != DM_OK) {
118 LOGE("HEX conversion failed at index %{public}u, ret = %{public}d",
119 processedIndex, ret);
120 delete[] cert.data;
121 cert.data = nullptr;
122 return false;
123 }
124 cert.size = binSize;
125 return true;
126 }
127
DeserializeDmCertChain(const std::string & data,DmCertChain * outChain)128 bool AuthAttestCommon::DeserializeDmCertChain(const std::string &data, DmCertChain *outChain)
129 {
130 if (outChain == nullptr || data.empty() || !ValidateInputJson(data)) {
131 LOGE("Invalid input");
132 return false;
133 }
134 JsonObject jsonObject;
135 jsonObject.Parse(data);
136 const uint32_t certCount = jsonObject[TAG_CERT_COUNT].Get<uint32_t>();
137 JsonObject jsonArrayObj(JsonCreateType::JSON_CREATE_TYPE_ARRAY);
138 jsonArrayObj.Parse(jsonObject[TAG_CERT].Dump());
139 DmBlob *certs = new DmBlob[certCount];
140 if (certs == nullptr) {
141 LOGE("Memory allocation failed for certs array");
142 return false;
143 }
144 if (memset_s(certs, sizeof(DmBlob) * certCount, 0, sizeof(DmBlob) * certCount) != DM_OK) {
145 LOGE("memset_s failed.");
146 delete[] certs;
147 certs = nullptr;
148 return false;
149 }
150 bool success = true;
151 uint32_t processedIndex = 0;
152 for (const auto &item : jsonArrayObj.Items()) {
153 if (!ProcessCertItem(item, certs[processedIndex], processedIndex)) {
154 success = false;
155 break;
156 }
157 processedIndex++;
158 }
159 if (!success) {
160 for (uint32_t i = 0; i < processedIndex; ++i) {
161 delete[] certs[i].data;
162 }
163 delete[] certs;
164 return false;
165 }
166 FreeDmCertChain(*outChain);
167 outChain->cert = certs;
168 outChain->certCount = certCount;
169 return true;
170 }
171
FreeDmCertChain(DmCertChain & chain)172 void AuthAttestCommon::FreeDmCertChain(DmCertChain &chain)
173 {
174 if (chain.cert == nullptr) {
175 return;
176 }
177 for (uint32_t i = 0; i < chain.certCount; ++i) {
178 if (chain.cert[i].data != nullptr) {
179 delete[] chain.cert[i].data;
180 chain.cert[i].data = nullptr;
181 }
182 chain.cert[i].size = 0;
183 }
184 delete[] chain.cert;
185 chain.cert = nullptr;
186 chain.certCount = 0;
187 }
188 //LCOV_EXCL_STOP
189 } // namespace DistributedHardware
190 } // namespace OHOS
191