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_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
HcsSwapToUint64(uint64_t * value,const char * realValue,uint32_t type)158 bool HcsSwapToUint64(uint64_t *value, const char *realValue, uint32_t type)
159 {
160 uint32_t data;
161 if (type == CONFIG_QWORD) {
162 *value = HcsByteCodeToUint64(realValue);
163 return true;
164 }
165 if (HcsSwapToUint32(&data, realValue, type)) {
166 *value = data;
167 return true;
168 }
169 HDF_LOGE("%{public}s failed, type: %{public}u", __func__, type);
170 return false;
171 }
172
CheckHcsBlobLength(uint32_t length,struct HbcHeader * header)173 static bool CheckHcsBlobLength(uint32_t length, struct HbcHeader *header)
174 {
175 uint32_t rootNodeLen = HCS_STRING_LENGTH(HBC_ROOT_NAME) + HCS_PREFIX_LENGTH + HCS_DWORD_LENGTH;
176 uint32_t minLength = rootNodeLen + HBC_HEADER_LENGTH;
177 uint32_t blobLength;
178 if (header->totalSize >= 0) {
179 blobLength = (uint32_t)(HBC_HEADER_LENGTH + header->totalSize);
180 g_byteAlign = false;
181 HDF_LOGI("%{public}s: the blobLength: %{public}u, byteAlign: %{public}d", __func__, blobLength, g_byteAlign);
182 } else {
183 blobLength = (uint32_t)(HBC_HEADER_LENGTH - header->totalSize);
184 g_byteAlign = true;
185 HDF_LOGI("%{public}s: the blobLength: %{public}u, byteAlign: %{public}d", __func__, blobLength, g_byteAlign);
186 }
187 if ((length != blobLength) || (blobLength < minLength)) {
188 HDF_LOGE("%{public}s failed, Hcsblob file length is %{public}u, but the calculated length is %u",
189 __func__, length, blobLength);
190 return false;
191 }
192 return true;
193 }
194
HcsCheckBlobFormat(const char * start,uint32_t length)195 bool HcsCheckBlobFormat(const char *start, uint32_t length)
196 {
197 struct HbcHeader *header = NULL;
198 if ((start == NULL) || (length < HBC_HEADER_LENGTH) || (length > HBC_BLOB_MAX_LENGTH)) {
199 HDF_LOGE("%{public}s failed, Hcsblob file length is %{public}u", __func__, length);
200 return false;
201 }
202 header = (struct HbcHeader *)start;
203 if (header->magicNumber != HBC_MAGIC_NUMBER) {
204 HDF_LOGE("%{public}s failed, the magic number of HBC is %{public}x", __func__, header->magicNumber);
205 return false;
206 }
207 if (!CheckHcsBlobLength(length, header)) {
208 return false;
209 }
210 return true;
211 }
212