1 /*
2 * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "hcs_blob_if.h"
10 #include "hdf_core_log.h"
11
12 #define HDF_LOG_TAG hcs_blob_if
13
14 static bool g_byteAlign = false;
15
HcsIsByteAlign(void)16 bool HcsIsByteAlign(void)
17 {
18 return g_byteAlign;
19 }
20
HcsGetDataTypeOffset(const char * start)21 int32_t HcsGetDataTypeOffset(const char *start)
22 {
23 int32_t len;
24 switch (HcsGetPrefix(start)) {
25 case CONFIG_BYTE:
26 len = HCS_BYTE_LENGTH + HCS_PREFIX_LENGTH;
27 break;
28 case CONFIG_WORD:
29 len = HCS_WORD_LENGTH + HCS_PREFIX_LENGTH;
30 break;
31 case CONFIG_DWORD:
32 case CONFIG_REFERENCE:
33 len = HCS_DWORD_LENGTH + HCS_PREFIX_LENGTH;
34 break;
35 case CONFIG_QWORD:
36 len = HCS_QWORD_LENGTH + HCS_PREFIX_LENGTH;
37 break;
38 case CONFIG_STRING:
39 len = HCS_STRING_LENGTH(start + HCS_PREFIX_LENGTH) + HCS_PREFIX_LENGTH;
40 break;
41 default:
42 len = HDF_FAILURE;
43 break;
44 }
45 return len;
46 }
47
HcsGetArrayLength(const char * start)48 static int32_t HcsGetArrayLength(const char *start)
49 {
50 int32_t arrayLen = HCS_PREFIX_LENGTH + HCS_WORD_LENGTH;
51 uint16_t count;
52 uint16_t i;
53 if (!HcsSwapToUint16(&count, start + HCS_PREFIX_LENGTH, CONFIG_WORD)) {
54 HDF_LOGE("%{public}s failed", __func__);
55 return HDF_FAILURE;
56 }
57 for (i = 0; i < count; i++) {
58 int32_t lenData = HcsGetDataTypeOffset(start + arrayLen);
59 if (lenData < 0) {
60 return HDF_FAILURE;
61 }
62 arrayLen += lenData;
63 }
64 return arrayLen;
65 }
66
HcsGetAttrLength(const char * start)67 int32_t HcsGetAttrLength(const char *start)
68 {
69 int32_t length = HCS_PREFIX_LENGTH + HCS_STRING_LENGTH(start + HCS_PREFIX_LENGTH);
70 int32_t dataLen;
71 switch (HcsGetPrefix(start + length)) {
72 case CONFIG_BYTE:
73 case CONFIG_WORD:
74 case CONFIG_DWORD:
75 case CONFIG_QWORD:
76 case CONFIG_STRING:
77 case CONFIG_REFERENCE:
78 dataLen = HcsGetDataTypeOffset(start + length);
79 break;
80 case CONFIG_ARRAY:
81 dataLen = HcsGetArrayLength(start + length);
82 break;
83 default:
84 dataLen = HDF_FAILURE;
85 break;
86 }
87 return (dataLen < 0) ? HDF_FAILURE : (dataLen + length);
88 }
89
HcsGetNodeOrAttrLength(const char * start)90 int32_t HcsGetNodeOrAttrLength(const char *start)
91 {
92 int32_t length;
93 switch (HcsGetPrefix(start)) {
94 case CONFIG_NODE:
95 length = HCS_STRING_LENGTH(start + HCS_PREFIX_LENGTH) + HCS_PREFIX_LENGTH + HCS_DWORD_LENGTH;
96 break;
97 case CONFIG_ATTR:
98 length = HcsGetAttrLength(start);
99 break;
100 default:
101 length = HDF_FAILURE;
102 break;
103 }
104 return length;
105 }
106
HcsGetNodeLength(const char * blob)107 int32_t HcsGetNodeLength(const char *blob)
108 {
109 int32_t rootLen = HcsGetNodeOrAttrLength(blob);
110 if (rootLen < 0) {
111 HDF_LOGE("%{public}s failed, the rootLen is %{public}d", __func__, rootLen);
112 return HDF_FAILURE;
113 }
114 rootLen += (int32_t)HcsByteCodeToUint32(blob + HCS_PREFIX_LENGTH + HCS_STRING_LENGTH(blob + HCS_PREFIX_LENGTH));
115 return rootLen;
116 }
117
HcsSwapToUint8(uint8_t * value,const char * realValue,uint32_t type)118 bool HcsSwapToUint8(uint8_t *value, const char *realValue, uint32_t type)
119 {
120 if (type == CONFIG_BYTE) {
121 *value = g_byteAlign ? (uint8_t)HcsByteCodeToUint32(realValue) : HcsByteCodeToUint8(realValue);
122 return true;
123 }
124 HDF_LOGE("%{public}s failed, type: %{public}u", __func__, type);
125 return false;
126 }
127
HcsSwapToUint16(uint16_t * value,const char * realValue,uint32_t type)128 bool HcsSwapToUint16(uint16_t *value, const char *realValue, uint32_t type)
129 {
130 uint8_t data;
131 if (type == CONFIG_WORD) {
132 *value = g_byteAlign ? (uint16_t)HcsByteCodeToUint32(realValue) : HcsByteCodeToUint16(realValue);
133 return true;
134 }
135 if (HcsSwapToUint8(&data, realValue, type)) {
136 *value = data;
137 return true;
138 }
139 HDF_LOGE("%{public}s failed, type: %{public}u", __func__, type);
140 return false;
141 }
142
HcsSwapToUint32(uint32_t * value,const char * realValue,uint32_t type)143 bool HcsSwapToUint32(uint32_t *value, const char *realValue, uint32_t type)
144 {
145 uint16_t data;
146 if (type == CONFIG_DWORD) {
147 *value = HcsByteCodeToUint32(realValue);
148 return true;
149 }
150 if (HcsSwapToUint16(&data, realValue, type)) {
151 *value = data;
152 return true;
153 }
154 HDF_LOGE("%{public}s failed, type: %{public}u", __func__, type);
155 return false;
156 }
157
158 // LCOV_EXCL_START
HcsSwapToUint64(uint64_t * value,const char * realValue,uint32_t type)159 bool HcsSwapToUint64(uint64_t *value, const char *realValue, uint32_t type)
160 {
161 uint32_t data;
162 if (type == CONFIG_QWORD) {
163 *value = HcsByteCodeToUint64(realValue);
164 return true;
165 }
166 if (HcsSwapToUint32(&data, realValue, type)) {
167 *value = data;
168 return true;
169 }
170 HDF_LOGE("%{public}s failed, type: %{public}u", __func__, type);
171 return false;
172 }
173 // LCOV_EXCL_STOP
174
CheckHcsBlobLength(uint32_t length,struct HbcHeader * header)175 static bool CheckHcsBlobLength(uint32_t length, struct HbcHeader *header)
176 {
177 uint32_t rootNodeLen = HCS_STRING_LENGTH(HBC_ROOT_NAME) + HCS_PREFIX_LENGTH + HCS_DWORD_LENGTH;
178 uint32_t minLength = rootNodeLen + HBC_HEADER_LENGTH;
179 uint32_t blobLength;
180 if (header->totalSize >= 0) {
181 blobLength = (uint32_t)(HBC_HEADER_LENGTH + header->totalSize);
182 g_byteAlign = false;
183 HDF_LOGI("%{public}s: the blobLength: %{public}u, byteAlign: %{public}d", __func__, blobLength, g_byteAlign);
184 } else {
185 blobLength = (uint32_t)(HBC_HEADER_LENGTH - header->totalSize);
186 g_byteAlign = true;
187 HDF_LOGI("%{public}s: the blobLength: %{public}u, byteAlign: %{public}d", __func__, blobLength, g_byteAlign);
188 }
189 if ((length != blobLength) || (blobLength < minLength)) {
190 HDF_LOGE("%{public}s failed, Hcsblob file length is %{public}u, but the calculated length is %u",
191 __func__, length, blobLength);
192 return false;
193 }
194 return true;
195 }
196
HcsCheckBlobFormat(const char * start,uint32_t length)197 bool HcsCheckBlobFormat(const char *start, uint32_t length)
198 {
199 struct HbcHeader *header = NULL;
200 if ((start == NULL) || (length < HBC_HEADER_LENGTH) || (length > HBC_BLOB_MAX_LENGTH)) {
201 HDF_LOGE("%{public}s failed, Hcsblob file length is %{public}u", __func__, length);
202 return false;
203 }
204 header = (struct HbcHeader *)start;
205 if (header->magicNumber != HBC_MAGIC_NUMBER) {
206 HDF_LOGE("%{public}s failed, the magic number of HBC is %{public}x", __func__, header->magicNumber);
207 return false;
208 }
209 if (!CheckHcsBlobLength(length, header)) {
210 return false;
211 }
212 return true;
213 }
214