1 /*
2 * Copyright (c) 2020 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 "dmslite_parser.h"
17
18 #include <stdlib.h>
19 #include <unistd.h>
20
21 #include "dmsfwk_interface.h"
22 #include "dmslite_log.h"
23 #include "dmslite_msg_handler.h"
24 #include "dmslite_tlv_common.h"
25 #include "securec.h"
26
27 #define MIN_VALID_NODES 2
28
29 #define HIGH_BIT_MASK 0xFF
30 #define LOW_BIT_MASK 0x7F
31 #define TLV_LENGTH_SHIFT_BITS 7
32
33 #define BREAK_IF_FAILURE(errCode); \
34 if ((errCode) != DMS_TLV_SUCCESS) { \
35 break; \
36 } \
37
IsNextTlvLength(uint8_t num)38 static inline bool IsNextTlvLength(uint8_t num)
39 {
40 /* 128-16383 : 0b1xxxxxxx 0b0xxxxxxx */
41 return (((num) & HIGH_BIT_MASK) >> TLV_LENGTH_SHIFT_BITS) == 0x00;
42 }
43
TlvByteToLength(uint8_t byte,uint16_t * len)44 static inline void TlvByteToLength(uint8_t byte, uint16_t *len)
45 {
46 *len = ((*len) << TLV_LENGTH_SHIFT_BITS) | (byte & LOW_BIT_MASK);
47 }
48
TlvBytesToLength(const uint8_t * bytesBuffer,uint16_t bufLength,uint16_t * length,uint8_t * bytesNumber)49 static TlvErrorCode TlvBytesToLength(const uint8_t *bytesBuffer, uint16_t bufLength,
50 uint16_t *length, uint8_t *bytesNumber)
51 {
52 uint8_t bytesNum = 0;
53 uint16_t len = 0;
54 /* compute TLV's L, when value > 127, the L should be two bytes, else L is one byte long
55 0-127 : 0b0xxxxxxx
56 128-16383 : 0b1xxxxxxx 0b0xxxxxxx */
57 for (uint8_t i = 0; i < bufLength; i++) {
58 TlvByteToLength(bytesBuffer[i], &len);
59 bytesNum++;
60 if (IsNextTlvLength(bytesBuffer[i])) {
61 HILOGD("[bytesNum = %hhu, byte = %x]", bytesNum, bytesBuffer[i]);
62 break;
63 }
64 if (bytesNum >= TLV_MAX_LENGTH_BYTES) {
65 return DMS_TLV_ERR_LEN;
66 }
67 }
68 /* it is meaningless to have a node with length being zero */
69 if (len == 0) {
70 HILOGE("[Invalid zero-size length]");
71 return DMS_TLV_ERR_LEN;
72 }
73
74 *length = len;
75 *bytesNumber = bytesNum;
76
77 return DMS_TLV_SUCCESS;
78 }
79
TlvFillNode(const uint8_t * byteBuffer,uint16_t bufLength,TlvNode * node,uint16_t * actualHandledLen)80 static TlvErrorCode TlvFillNode(const uint8_t *byteBuffer, uint16_t bufLength,
81 TlvNode *node, uint16_t *actualHandledLen)
82 {
83 if (bufLength <= TLV_TYPE_LEN) {
84 HILOGE("[Bad bufLength %hu]", bufLength);
85 return DMS_TLV_ERR_LEN;
86 }
87
88 /* fill TLV's T(type) */
89 node->type = *byteBuffer;
90 uint16_t curTlvNodeLen = TLV_TYPE_LEN;
91
92 /* fill TLV's L(length) */
93 uint16_t length = 0;
94 uint8_t bytesNum = 0;
95 const uint8_t *lengthPartAddr = byteBuffer + curTlvNodeLen;
96 TlvErrorCode errCode = TlvBytesToLength(lengthPartAddr, bufLength - curTlvNodeLen,
97 &length, &bytesNum);
98 if (errCode != DMS_TLV_SUCCESS) {
99 return DMS_TLV_ERR_LEN;
100 }
101 node->length = length;
102 curTlvNodeLen += bytesNum;
103
104 /* fill TLV's V(value) */
105 node->value = byteBuffer + curTlvNodeLen;
106 curTlvNodeLen += length;
107 if (curTlvNodeLen > bufLength) {
108 return DMS_TLV_ERR_LEN;
109 } else {
110 *actualHandledLen = curTlvNodeLen;
111 }
112
113 return DMS_TLV_SUCCESS;
114 }
115
TlvFreeNodeList(TlvNode * node)116 static void TlvFreeNodeList(TlvNode *node)
117 {
118 TlvNode *next = NULL;
119 while (node != NULL) {
120 next = node->next;
121 free(node);
122 node = next;
123 }
124 }
125
MallocTlvNode()126 static inline TlvNode* MallocTlvNode()
127 {
128 TlvNode *node = (TlvNode *)malloc(sizeof(TlvNode));
129 if (node == NULL) {
130 HILOGE("[Out of memory]");
131 return NULL;
132 }
133 /* won't fail */
134 (void) memset_s(node, sizeof(TlvNode), 0x00, sizeof(TlvNode));
135
136 return node;
137 }
138
CheckNodeSequence(const TlvNode * lastNode,const TlvNode * curNode)139 static inline TlvErrorCode CheckNodeSequence(const TlvNode *lastNode, const TlvNode *curNode)
140 {
141 if (lastNode == curNode) {
142 return DMS_TLV_SUCCESS;
143 }
144 if (lastNode->type >= curNode->type) {
145 HILOGE("[Bad node type sequence '%hhu' is expected but '%hhu' appears]",
146 lastNode->type, curNode->type);
147 return DMS_TLV_ERR_OUT_OF_ORDER;
148 }
149
150 return DMS_TLV_SUCCESS;
151 }
152
MoveToNextTlvNode(TlvNode ** curNode)153 static inline TlvErrorCode MoveToNextTlvNode(TlvNode **curNode)
154 {
155 TlvNode *next = MallocTlvNode();
156 if (next == NULL) {
157 return DMS_TLV_ERR_NO_MEM;
158 }
159
160 (*curNode)->next = next;
161 *curNode = next;
162 return DMS_TLV_SUCCESS;
163 }
164
TlvBytesToNode(const uint8_t * byteBuffer,uint16_t bufLength,TlvNode ** tlv)165 TlvErrorCode TlvBytesToNode(const uint8_t *byteBuffer, uint16_t bufLength, TlvNode **tlv)
166 {
167 if ((tlv == NULL) || (byteBuffer == NULL)) {
168 HILOGE("[Bad parameter]");
169 return DMS_TLV_ERR_PARAM;
170 }
171 /* bufLength is longer than TLV_TYPE_LEN + 1(means length should be at least 1 byte) */
172 if (bufLength <= (TLV_TYPE_LEN + 1)) {
173 HILOGE("[Bad Length %hu]", bufLength);
174 return DMS_TLV_ERR_LEN;
175 }
176
177 TlvNode *head = MallocTlvNode();
178 if (head == NULL) {
179 return DMS_TLV_ERR_NO_MEM;
180 }
181 TlvNode *curNode = head;
182 TlvNode *lastNode = curNode;
183
184 /* translate bytes to tlv node until the end of buffer */
185 uint16_t remainingLen = bufLength;
186 uint8_t handledNodeNum = 0;
187 const uint8_t *nodeStartAddr = byteBuffer;
188 TlvErrorCode errCode = DMS_TLV_SUCCESS;
189 while (true) {
190 uint16_t curTlvNodeLen = 0;
191 errCode = TlvFillNode(nodeStartAddr, remainingLen, curNode, &curTlvNodeLen);
192 BREAK_IF_FAILURE(errCode);
193
194 /* check whether there is need to continue processing the remaining nodes */
195 handledNodeNum++;
196
197 /* check node type sequence: the type of node must appear in strictly increasing order */
198 errCode = CheckNodeSequence(lastNode, curNode);
199 BREAK_IF_FAILURE(errCode);
200
201 remainingLen -= curTlvNodeLen;
202 if (remainingLen == 0) {
203 break;
204 }
205
206 HILOGD("[curNode length:%hu type:%hhu handledNodeNum:%hhu]", curNode->length,
207 curNode->type, handledNodeNum);
208 /* if all is ok, then move to the T part of the next tlv node */
209 nodeStartAddr += curTlvNodeLen;
210 lastNode = curNode;
211 errCode = MoveToNextTlvNode(&curNode);
212 BREAK_IF_FAILURE(errCode);
213 }
214
215 if (errCode == DMS_TLV_SUCCESS && handledNodeNum < MIN_VALID_NODES) {
216 HILOGE("[Parse done, but node num is invalid]");
217 errCode = DMS_TLV_ERR_BAD_NODE_NUM;
218 }
219
220 if (errCode != DMS_TLV_SUCCESS) {
221 TlvFreeNodeList(head);
222 head = NULL;
223 }
224 *tlv = head;
225
226 return errCode;
227 }
228
Parse(const uint8_t * payload,uint16_t length,TlvNode ** head)229 static int32_t Parse(const uint8_t *payload, uint16_t length, TlvNode **head)
230 {
231 if (length > MAX_DMS_MSG_LENGTH) {
232 HILOGE("[Bad parameters][length = %hu]", length);
233 return DMS_TLV_ERR_PARAM;
234 }
235
236 TlvNode *tlvHead = NULL;
237 TlvErrorCode errCode = TlvBytesToNode(payload, length, &tlvHead);
238 *head = tlvHead;
239 HILOGI("[errCode = %d]", errCode);
240 return errCode;
241 }
242
CanCall()243 static bool CanCall()
244 {
245 #ifndef WEARABLE_PRODUCT
246 uid_t callerUid = getuid();
247 /* only foundation and xts (shell-enabled mode only) is reasonable to call ProcessCommuMsg directly */
248 if (callerUid != FOUNDATION_UID && callerUid != SHELL_UID) {
249 HILOGD("[Caller uid is not allowed, uid = %u]", callerUid);
250 return false;
251 }
252 #endif
253 return true;
254 }
255
ProcessCommuMsg(const CommuMessage * commuMessage,const IDmsFeatureCallback * dmsFeatureCallback)256 int32_t ProcessCommuMsg(const CommuMessage *commuMessage, const IDmsFeatureCallback *dmsFeatureCallback)
257 {
258 if (!CanCall()) {
259 return DMS_EC_FAILURE;
260 }
261
262 if (commuMessage == NULL || commuMessage->payload == NULL || dmsFeatureCallback == NULL) {
263 return DMS_EC_FAILURE;
264 }
265
266 TlvNode *tlvHead = NULL;
267 int32_t errCode = Parse(commuMessage->payload, commuMessage->payloadLength, &tlvHead);
268 /* mainly for xts testsuit convenient, in non-test mode the onTlvParseDone should be set NULL */
269 if (dmsFeatureCallback->onTlvParseDone != NULL) {
270 dmsFeatureCallback->onTlvParseDone(errCode, tlvHead);
271 }
272 if (errCode != DMS_TLV_SUCCESS) {
273 return DMS_EC_PARSE_TLV_FAILURE;
274 }
275
276 uint16_t commandId = UnMarshallUint16(tlvHead, COMMAND_ID);
277 HILOGI("[ProcessCommuMsg commandId %hu]", commandId);
278 switch (commandId) {
279 case DMS_MSG_CMD_START_FA: {
280 errCode = StartAbilityFromRemoteHandler(tlvHead, dmsFeatureCallback->onStartAbilityDone);
281 break;
282 }
283 case DMS_MSG_CMD_REPLY: {
284 errCode = ReplyMsgHandler(tlvHead);
285 break;
286 }
287 default: {
288 HILOGW("[Unknown command id %hu]", commandId);
289 errCode = DMS_EC_UNKNOWN_COMMAND_ID;
290 break;
291 }
292 }
293 TlvFreeNodeList(tlvHead);
294 return errCode;
295 }