1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "security_auth_enhance.h"
33 #include <securec.h>
34 #include "securectype.h"
35 #include "tc_client_sub_driver.h"
36 #include "tc_ns_client.h"
37 #include "tc_ns_log.h"
38 #include "teek_client_constants.h"
39 #include "teek_client_type.h"
40 #include "tzdriver_compat.h"
41
42 #if !defined(UINT64_MAX)
43 #define UINT64_MAX ((uint64_t)0xFFFFFFFFFFFFFFFFULL)
44 #endif
45
46 #ifdef SECURITY_AUTH_ENHANCE
47 #define GLOBAL_CMD_ID_SSA 0x2DCB /* SSA cmdId 11723 */
48 #define GLOBAL_CMD_ID_MT 0x2DCC /* MT cmdId 11724 */
49 #define GLOBAL_CMD_ID_MT_UPDATE 0x2DCD /* MT_IPDATE cmdId 11725 */
50 #define TEEC_PENDING2_AGENT 0xFFFF2001
51
IsTokenEmpty(const uint8_t * token,uint32_t tokenLen)52 static bool IsTokenEmpty(const uint8_t *token, uint32_t tokenLen)
53 {
54 uint32_t i;
55
56 if (token == NULL) {
57 tloge("bad parameters, token is null\n");
58 return true;
59 }
60 for (i = 0; i < tokenLen; i++) {
61 if (*(token + i)) {
62 return false;
63 }
64 }
65 return true;
66 }
67
ScramblingTimestamp(const void * in,void * out,uint32_t dataLen,const void * key,uint32_t keyLen)68 static TeecResult ScramblingTimestamp(const void *in, void *out,
69 uint32_t dataLen, const void *key, uint32_t keyLen)
70 {
71 uint32_t i;
72 bool checkValue = false;
73
74 if (in == NULL || out == NULL || key == NULL) {
75 tloge("bad parameters, input_data is null\n");
76 return TEEC_ERROR_BAD_PARAMETERS;
77 }
78 checkValue = (dataLen == 0 || dataLen > SECUREC_MEM_MAX_LEN ||
79 keyLen > SECUREC_MEM_MAX_LEN || keyLen == 0);
80 if (checkValue) {
81 tloge("bad parameters, dataLen is %u, scrambling_len is %u\n",
82 dataLen, keyLen);
83 return TEEC_ERROR_BAD_PARAMETERS;
84 }
85 for (i = 0; i < dataLen; i++) {
86 *((uint8_t *)out + i) =
87 *((uint8_t *)in + i) ^ *((uint8_t *)key + i % keyLen);
88 }
89
90 return TEEC_SUCCESS;
91 }
92
ChangeTimeStamp(uint8_t flag,uint64_t * timeStamp)93 static int32_t ChangeTimeStamp(uint8_t flag, uint64_t *timeStamp)
94 {
95 if (flag == INC) {
96 if (*timeStamp < UINT64_MAX) {
97 (*timeStamp)++;
98 } else {
99 tloge("val overflow\n");
100 return -EFAULT;
101 }
102 } else if (flag == DEC) {
103 if (*timeStamp > 0) {
104 (*timeStamp)--;
105 } else {
106 tloge("val down overflow\n");
107 return -EFAULT;
108 }
109 } else {
110 tloge("flag error , 0x%x\n", flag);
111 return -EFAULT;
112 }
113 return EOK;
114 }
115
DescramblingTimestamp(uint8_t * inTokenBuf,const struct SessionSecureInfo * secureInfo,uint8_t flag)116 static int32_t DescramblingTimestamp(uint8_t *inTokenBuf,
117 const struct SessionSecureInfo *secureInfo, uint8_t flag)
118 {
119 uint64_t timeStamp = 0;
120 int32_t ret;
121
122 if (inTokenBuf == NULL || secureInfo == NULL) {
123 tloge("invalid params!\n");
124 return -EINVAL;
125 }
126 if (ScramblingTimestamp(&inTokenBuf[TIMESTAMP_BUFFER_INDEX],
127 &timeStamp, TIMESTAMP_LEN_DEFAULT, secureInfo->scrambling, SCRAMBLING_KEY_LEN)) {
128 tloge("DescramblingTimestamp failed\n");
129 return -EFAULT;
130 }
131 ret = ChangeTimeStamp(flag, &timeStamp);
132 if (ret != EOK) {
133 return ret;
134 }
135
136 tlogd("timestamp is %llu\n", timeStamp);
137 if (ScramblingTimestamp(&timeStamp, &inTokenBuf[TIMESTAMP_BUFFER_INDEX],
138 TIMESTAMP_LEN_DEFAULT, secureInfo->scrambling, SCRAMBLING_KEY_LEN)) {
139 tloge("DescramblingTimestamp failed\n");
140 return -EFAULT;
141 }
142 return EOK;
143 }
144
UpdateTimestamp(const TcNsSmcCmd * cmd)145 TeecResult UpdateTimestamp(const TcNsSmcCmd *cmd)
146 {
147 TcNsSession *session = NULL;
148 struct SessionSecureInfo *secureInfo = NULL;
149 uint8_t *tokenBuffer = NULL;
150 bool filterFlag = false;
151 bool needCheckFlag = false;
152
153 if (cmd == NULL) {
154 tloge("cmd is NULL, error!");
155 return TEEC_ERROR_BAD_PARAMETERS;
156 }
157 /* if cmd is agent, not check uuid. and sometime uuid canot access it */
158 filterFlag = (cmd->agentId != 0) ||
159 (cmd->retVal == TEEC_PENDING2_AGENT);
160 if (filterFlag) {
161 return TEEC_SUCCESS;
162 }
163
164 needCheckFlag = (cmd->globalCmd == false) && (cmd->agentId == 0) &&
165 (cmd->retVal != TEEC_PENDING2_AGENT);
166 if (needCheckFlag) {
167 tokenBuffer = (void *)LOS_PaddrToKVaddr((paddr_t)(cmd->tokenPhys));
168 if (tokenBuffer == NULL ||
169 IsTokenEmpty(tokenBuffer, TOKEN_BUFFER_LEN)) {
170 tloge("token is NULL or token is empyt, error!\n");
171 return TEEC_ERROR_GENERIC;
172 }
173
174 session = TcFindSession2(cmd->devFileId, cmd);
175 if (session == NULL) {
176 tlogd("tc_find_session_key find session FAILURE\n");
177 return TEEC_ERROR_GENERIC;
178 }
179 secureInfo = &session->secureInfo;
180 if (DescramblingTimestamp(tokenBuffer, secureInfo, INC) != EOK) {
181 PutSessionStruct(session);
182 tloge("update tokenBuffer error\n");
183 return TEEC_ERROR_GENERIC;
184 }
185 PutSessionStruct(session);
186 tokenBuffer[SYNC_INDEX] = UN_SYNCED;
187 } else {
188 tlogd("global cmd or agent, do not update timestamp\n");
189 }
190 return TEEC_SUCCESS;
191 }
192
SyncTimestamp(const TcNsSmcCmd * cmd,uint8_t * token,uint32_t tokenLen,bool global)193 TeecResult SyncTimestamp(const TcNsSmcCmd *cmd, uint8_t *token,
194 uint32_t tokenLen, bool global)
195 {
196 TcNsSession *session = NULL;
197 bool checkVal = false;
198
199 checkVal = (cmd == NULL || token == NULL || tokenLen <= SYNC_INDEX);
200 if (checkVal) {
201 tloge("parameters is NULL, error!\n");
202 return TEEC_ERROR_BAD_PARAMETERS;
203 }
204 if (cmd->cmdId == GLOBAL_CMD_ID_OPEN_SESSION && global) {
205 tlogd("OpenSession would not need sync timestamp\n");
206 return TEEC_SUCCESS;
207 }
208
209 if (token[SYNC_INDEX] == UN_SYNCED) {
210 tlogd("flag is UN_SYNC, to sync timestamp!\n");
211
212 session = TcFindSession2(cmd->devFileId, cmd);
213 if (session == NULL) {
214 tloge("SyncTimestamp find session FAILURE\n");
215 return TEEC_ERROR_GENERIC;
216 }
217 if (DescramblingTimestamp(token, &session->secureInfo, DEC) != EOK) {
218 PutSessionStruct(session);
219 tloge("sync tokenBuffer error\n");
220 return TEEC_ERROR_GENERIC;
221 }
222 PutSessionStruct(session);
223 return TEEC_SUCCESS;
224 } else if (token[SYNC_INDEX] == IS_SYNCED) {
225 return TEEC_SUCCESS;
226 } else {
227 tloge("sync flag error! 0x%x\n", token[SYNC_INDEX]);
228 }
229 return TEEC_ERROR_GENERIC;
230 }
231
232 /* scrambling operation and pid */
ScramblingOperation(TcNsSmcCmd * cmd,uint32_t scrambler)233 static void ScramblingOperation(TcNsSmcCmd *cmd, uint32_t scrambler)
234 {
235 if (cmd == NULL) {
236 return;
237 }
238 if (cmd->operationPhys != 0 || cmd->operationHphys != 0) {
239 cmd->operationPhys = cmd->operationPhys ^ scrambler;
240 cmd->operationHphys = cmd->operationHphys ^ scrambler;
241 }
242 cmd->pid = cmd->pid ^ scrambler;
243 }
244
AgentMsg(uint32_t cmdId)245 static bool AgentMsg(uint32_t cmdId)
246 {
247 bool agent = cmdId == GLOBAL_CMD_ID_SSA ||
248 cmdId == GLOBAL_CMD_ID_MT ||
249 cmdId == GLOBAL_CMD_ID_MT_UPDATE;
250
251 return agent;
252 }
253
254 /* calculate cmd checksum and scrambling operation */
UpdateChksum(TcNsSmcCmd * cmd)255 TeecResult UpdateChksum(TcNsSmcCmd *cmd)
256 {
257 TcNsSession *session = NULL;
258 struct SessionSecureInfo *secureInfo = NULL;
259 uint32_t ScramblerOper;
260 bool checkValue = false;
261
262 if (cmd == NULL) {
263 tloge("cmd is NULL, error\n");
264 return TEEC_ERROR_BAD_PARAMETERS;
265 }
266 /*
267 * if cmd is agent, do not check uuid.
268 * and sometimes uuid cannot access it
269 */
270 checkValue = (cmd->agentId != 0 || cmd->retVal == TEEC_PENDING2_AGENT);
271 if (checkValue == true) {
272 return TEEC_SUCCESS;
273 }
274
275 if (AgentMsg(cmd->cmdId)) {
276 tlogd("SSA cmd, no need to UpdateChksum\n");
277 return TEEC_SUCCESS;
278 }
279 /* cmd is invoke command */
280 checkValue = (cmd->globalCmd == false) && (cmd->agentId == 0) &&
281 (cmd->retVal != TEEC_PENDING2_AGENT);
282
283 if (checkValue) {
284 session = TcFindSession2(cmd->devFileId, cmd);
285 if (session != NULL) {
286 secureInfo = &session->secureInfo;
287 ScramblerOper =
288 secureInfo->scrambling[SCRAMBLING_OPERATION];
289 ScramblingOperation(cmd, ScramblerOper);
290 PutSessionStruct(session);
291 }
292 }
293 return TEEC_SUCCESS;
294 }
295
VerifyChksum(const TcNsSmcCmd * cmd)296 TeecResult VerifyChksum(const TcNsSmcCmd *cmd)
297 {
298 TcNsSession *session = NULL;
299 bool checkFlag = false;
300
301 if (cmd == NULL) {
302 tloge("cmd is NULL, error\n");
303 return TEEC_ERROR_BAD_PARAMETERS;
304 }
305 if (AgentMsg(cmd->cmdId)) {
306 tlogd("SSA cmd, no need to UpdateChksum\n");
307 return TEEC_SUCCESS;
308 }
309
310 /* cmd is invoke command */
311 checkFlag = cmd->globalCmd == false &&
312 cmd->cmdId != GLOBAL_CMD_ID_CLOSE_SESSION &&
313 cmd->cmdId != GLOBAL_CMD_ID_KILL_TASK &&
314 cmd->agentId == 0;
315 if (checkFlag) {
316 session = TcFindSession2(cmd->devFileId, cmd);
317 if (session) {
318 PutSessionStruct(session);
319 }
320 }
321 return TEEC_SUCCESS;
322 }
323 #endif
324