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 }