• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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