1 /*
2 * Copyright (C) 2022 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 <string.h>
17 #include <securec.h>
18 #include "pthread.h"
19 #include "time.h"
20 #include "attest_type.h"
21 #include "attest_utils.h"
22 #include "attest_utils_memleak.h"
23 #include "attest_utils_log.h"
24 #include "attest_security_token.h"
25 #include "attest_security_ticket.h"
26 #include "attest_adapter.h"
27 #include "attest_adapter_mock.h"
28 #include "attest_service_auth.h"
29 #include "attest_service_reset.h"
30 #include "attest_service_active.h"
31 #include "attest_service_device.h"
32 #include "attest_service_challenge.h"
33 #include "attest_network.h"
34 #include "attest_service.h"
35
36 pthread_mutex_t g_mtxAttest = PTHREAD_MUTEX_INITIALIZER;
37 pthread_mutex_t g_authStatusMutex;
38 static uint8_t g_authResultCode = 2;
39
GetAuthResultCode(void)40 static int32_t GetAuthResultCode(void)
41 {
42 int32_t ret;
43 pthread_mutex_lock(&g_authStatusMutex);
44 AttestReadAuthResultCode((char*)&g_authResultCode, 1);
45 ret = g_authResultCode;
46 pthread_mutex_unlock(&g_authStatusMutex);
47 return ret;
48 }
49
UpdateAuthResultCode(uint8_t authResultCode)50 static void UpdateAuthResultCode(uint8_t authResultCode)
51 {
52 pthread_mutex_lock(&g_authStatusMutex);
53 AttestWriteAuthResultCode((char*)&authResultCode, 1);
54 g_authResultCode = authResultCode;
55 pthread_mutex_unlock(&g_authStatusMutex);
56 }
57
ResetDevice(void)58 static int32_t ResetDevice(void)
59 {
60 ATTEST_LOG_DEBUG("[ResetDevice] Begin.");
61 int32_t ret = ATTEST_OK;
62 ChallengeResult* challenge = NULL;
63 DevicePacket* reqMsg = NULL;
64 char* respMsg = NULL;
65 do {
66 ATTEST_LOG_DEBUG("[ResetDevice] Get challenge begin.");
67 ret = GetChallenge(&challenge, ATTEST_ACTION_RESET);
68 if (ret != ATTEST_OK) {
69 ATTEST_LOG_ERROR("[ResetDevice] Get challenge failed, ret = %d.", ret);
70 break;
71 }
72 ATTEST_LOG_DEBUG("[ResetDevice] Generate challenge begin.");
73 ret = GenResetMsg(challenge, &reqMsg);
74 if (ret != ATTEST_OK) {
75 ATTEST_LOG_ERROR("[ResetDevice] Generate reset request message failed, ret = %d.", ret);
76 break;
77 }
78 ATTEST_LOG_DEBUG("[ResetDevice] Send reset msg begin.");
79 ret = SendResetMsg(reqMsg, &respMsg);
80 if (ret != ATTEST_OK) {
81 ATTEST_LOG_ERROR("[ResetDevice] Send reset request message failed, ret = %d.", ret);
82 break;
83 }
84 ATTEST_LOG_DEBUG("[ResetDevice] Parse reset msg begin.");
85 ret = ParseResetResult((const char*)respMsg);
86 if (ret != ATTEST_OK) {
87 ATTEST_LOG_ERROR("[ResetDevice] Parse reset result message failed, ret = %d.", ret);
88 break;
89 }
90 }while (0);
91 FREE_CHALLENGE_RESULT(challenge);
92 FREE_DEVICE_PACKET(reqMsg);
93 ATTEST_MEM_FREE(respMsg);
94 ATTEST_LOG_DEBUG("[ResetDevice] End.");
95 return ret;
96 }
97
AuthDevice(AuthResult * authResult)98 static int32_t AuthDevice(AuthResult* authResult)
99 {
100 ATTEST_LOG_DEBUG("[AuthDevice] Begin.");
101 if (authResult == NULL) {
102 ATTEST_LOG_ERROR("[AuthDevice] Invalid parameter");
103 return ATTEST_ERR;
104 }
105
106 int32_t ret;
107 ChallengeResult* challenge = NULL;
108 DevicePacket* reqMsg = NULL;
109 char* respMsg = NULL;
110 do {
111 ATTEST_LOG_DEBUG("[AuthDevice] Get challenge begin.");
112 ret = GetChallenge(&challenge, ATTEST_ACTION_AUTHORIZE);
113 if (ret != ATTEST_OK) {
114 ATTEST_LOG_ERROR("[AuthDevice] Get challenge ret = %d.", ret);
115 break;
116 }
117 ATTEST_LOG_DEBUG("[AuthDevice] Generate challenge begin.");
118 ret = GenAuthMsg(challenge, &reqMsg);
119 if (ret != ATTEST_OK) {
120 ATTEST_LOG_ERROR("[AuthDevice] Generate auth request message failed, ret = %d.", ret);
121 break;
122 }
123 ATTEST_LOG_DEBUG("[AuthDevice] Send auth msg begin.");
124 ret = SendAuthMsg(reqMsg, &respMsg);
125 if (ret != ATTEST_OK) {
126 ATTEST_LOG_ERROR("[AuthDevice] Send auth request message failed, ret = %d.", ret);
127 break;
128 }
129 ATTEST_LOG_DEBUG("[AuthDevice] Parse auth msg begin.");
130 ret = ParseAuthResultResp(respMsg, authResult);
131 if (ret != ATTEST_OK) {
132 ATTEST_LOG_ERROR("[AuthDevice] Parse auth result message failed, ret = %d.", ret);
133 break;
134 }
135 }while (0);
136 FREE_CHALLENGE_RESULT(challenge);
137 FREE_DEVICE_PACKET(reqMsg);
138 ATTEST_MEM_FREE(respMsg);
139 ATTEST_LOG_DEBUG("[AuthDevice] End.");
140 return ret;
141 }
142
ActiveToken(AuthResult * authResult)143 static int32_t ActiveToken(AuthResult* authResult)
144 {
145 ATTEST_LOG_DEBUG("[ActiveToken] Begin.");
146 if (authResult == NULL) {
147 ATTEST_LOG_ERROR("[ActiveToken] Invalid parameter");
148 return ATTEST_ERR;
149 }
150
151 int32_t ret = FlushToken(authResult);
152 if (ret != ATTEST_OK) {
153 ATTEST_LOG_ERROR("[ActiveToken] Flush Token failed, ret = %d.", ret);
154 return ATTEST_ERR;
155 }
156
157 ChallengeResult* challenge = NULL;
158 DevicePacket* reqMsg = NULL;
159 char* respMsg = NULL;
160 do {
161 ATTEST_LOG_DEBUG("[ActiveToken] Get challenge begin.");
162 ret = GetChallenge(&challenge, ATTEST_ACTION_ACTIVATE);
163 if (ret != ATTEST_OK) {
164 ATTEST_LOG_ERROR("[ActiveToken] Get challenge ret = %d.", ret);
165 break;
166 }
167 ATTEST_LOG_DEBUG("[ActiveToken] Generate active request message begin.");
168 ret = GenActiveMsg(authResult, (const ChallengeResult*)challenge, &reqMsg);
169 if (ret != ATTEST_OK) {
170 ATTEST_LOG_ERROR("[ActiveToken] Generate active request message failed, ret = %d.", ret);
171 break;
172 }
173 ATTEST_LOG_DEBUG("[ActiveToken] Send active request message begin.");
174 ret = SendActiveMsg(reqMsg, &respMsg);
175 if (ret != ATTEST_OK) {
176 ATTEST_LOG_ERROR("[ActiveToken] Send active request message failed, ret = %d.", ret);
177 break;
178 }
179 ATTEST_LOG_DEBUG("[ActiveToken] Parse active request message begin.");
180 ret = ParseActiveResult(respMsg);
181 if (ret != ATTEST_OK) {
182 ATTEST_LOG_ERROR("[ActiveToken] Parse active result message failed, ret = %d.", ret);
183 break;
184 }
185 }while (0);
186 FREE_CHALLENGE_RESULT(challenge);
187 FREE_DEVICE_PACKET(reqMsg);
188 ATTEST_MEM_FREE(respMsg);
189 ATTEST_LOG_DEBUG("[ActiveToken] End.");
190 return ret;
191 }
192
FlushAttestData(const char * ticket,const char * authStatus)193 static void FlushAttestData(const char* ticket, const char* authStatus)
194 {
195 // ticket is not always need to write, and we don't care about writing it succeed or not.
196 if (authStatus == NULL) {
197 ATTEST_LOG_ERROR("[FlushAttestData] Invalid parameter");
198 return;
199 }
200
201 // 结果保存到本地
202 if (FlushAuthResult(ticket, authStatus) != ATTEST_OK) {
203 ATTEST_LOG_WARN("[FlushAttestData] Flush auth result failed");
204 }
205 // 结果保存到启动子系统parameter,方便展示
206 if (FlushAttestStatusPara(authStatus) != ATTEST_OK) {
207 ATTEST_LOG_WARN("[FlushAttestData] Flush attest para failed");
208 }
209 }
210
AttestStartup(AuthResult * authResult)211 static int32_t AttestStartup(AuthResult *authResult)
212 {
213 if (authResult == NULL) {
214 ATTEST_LOG_ERROR("[AttestStartup] Invalid parameter");
215 return ATTEST_ERR;
216 }
217 int32_t ret = ATTEST_OK;
218 // 重置设备
219 ATTEST_LOG_INFO("[AttestStartup] Reset device.");
220 if (!AttestIsResetFlagExist()) {
221 for (int32_t i = 0; i <= WISE_RETRY_CNT; i++) {
222 ret = ResetDevice();
223 if (!IS_WISE_RETRY(-ret)) {
224 break;
225 }
226 }
227 if (ret == ATTEST_OK) {
228 AttestCreateResetFlag();
229 }
230 }
231 // token认证
232 ATTEST_LOG_INFO("[AttestStartup] Auth device.");
233 for (int32_t i = 0; i <= WISE_RETRY_CNT; i++) {
234 ret = AuthDevice(authResult);
235 if (!IS_WISE_RETRY(-ret)) {
236 break;
237 }
238 }
239 if (ret != ATTEST_OK) {
240 UpdateAuthResultCode(AUTH_FAILED);
241 AttestSetParameter(STARTSUP_PARA_ATTEST_KEY, STARTSUP_PARA_ATTEST_ERROR);
242 ATTEST_LOG_ERROR("[AttestStartup] Auth token failed, ret = %d.", ret);
243 return ATTEST_ERR;
244 }
245 // 保存结果
246 ATTEST_LOG_INFO("[AttestStartup] Flush auth result.");
247 FlushAttestData(authResult->ticket, authResult->authStatus);
248 UpdateAuthResultCode(AUTH_SUCCESS);
249 AttestCreateResetFlag();
250 // token激活
251 ATTEST_LOG_INFO("[AttestStartup] Active token.");
252 for (int32_t i = 0; i <= WISE_RETRY_CNT; i++) {
253 ret = ActiveToken(authResult);
254 if (!IS_WISE_RETRY(-ret)) {
255 break;
256 }
257 }
258 if (ret != ATTEST_OK) {
259 ATTEST_LOG_ERROR("[AttestStartup] Active token failed, ret = %d.", ret);
260 return ATTEST_ERR;
261 }
262 return ATTEST_OK;
263 }
264
ProcAttestImpl(void)265 static int32_t ProcAttestImpl(void)
266 {
267 // 初始化系统参数
268 int32_t ret = InitSysData();
269 if (ret != ATTEST_OK) {
270 ATTEST_LOG_ERROR("[ProcAttestImpl] Init system device param failed, ret = %d.", ret);
271 DestroySysData();
272 return ATTEST_ERR;
273 }
274 // 检查本地数据是否修改或过期,进行重新认证
275 if (!IsAuthStatusChg()) {
276 ATTEST_LOG_WARN("[ProcAttestImpl] There is no change on auth status.");
277 UpdateAuthResultCode(AUTH_SUCCESS);
278 DestroySysData();
279 return ATTEST_OK;
280 }
281 AuthResult *authResult = CreateAuthResult();
282 if (authResult == NULL) {
283 ATTEST_LOG_ERROR("[ProcAttestImpl] Create auth result failed");
284 DestroySysData();
285 return ATTEST_ERR;
286 }
287 ret = AttestStartup(authResult);
288 DestroySysData();
289 DestroyAuthResult(&authResult);
290 return ret;
291 }
292
ProcAttest(void)293 int32_t ProcAttest(void)
294 {
295 pthread_mutex_lock(&g_mtxAttest);
296 PrintCurrentTime();
297 int32_t ret;
298 int32_t retValue;
299 if (ATTEST_DEBUG_MEMORY_LEAK) {
300 retValue = InitMemNodeList();
301 ATTEST_LOG_INFO("[ProcAttest] Init mem node list, retValue = %d.", retValue);
302 }
303 do {
304 // init network server info
305 ret = InitNetworkServerInfo();
306 if (ret != ATTEST_OK) {
307 ATTEST_LOG_ERROR("[ProcAttest] InitNetworkServerInfo failed, ret = %d.", ret);
308 }
309
310 ret = CheckNetworkConnectted();
311 if (ret != ATTEST_OK) {
312 ATTEST_LOG_ERROR("[ProcAttest] Network does not connetted, ret = %d.", ret);
313 break;
314 }
315 // 主流程
316 ret = ProcAttestImpl();
317 if (ret != ATTEST_OK) {
318 ATTEST_LOG_ERROR("[ProcAttest] Proc Attest failed, ret = %d.", ret);
319 }
320 }while (0);
321 if (ATTEST_DEBUG_MEMORY_LEAK) {
322 PrintMemNodeList();
323 retValue = DestroyMemNodeList();
324 ATTEST_LOG_INFO("[ProcAttest] Destroy mem node list, retValue = %d.", retValue);
325 }
326 PrintCurrentTime();
327 pthread_mutex_unlock(&g_mtxAttest);
328 return ret;
329 }
330
AttestStatusTrans(int32_t attestStatus)331 static int32_t AttestStatusTrans(int32_t attestStatus)
332 {
333 if (attestStatus == DEVICE_ATTEST_INIT) {
334 return DEVICE_ATTEST_INIT;
335 }
336 return (attestStatus == DEVICE_ATTEST_PASS) ? DEVICE_ATTEST_PASS : DEVICE_ATTEST_FAIL;
337 }
338
CopyResultArray(AuthStatus * authStatus,int32_t ** resultArray)339 static int32_t CopyResultArray(AuthStatus* authStatus, int32_t** resultArray)
340 {
341 if (authStatus == NULL || resultArray == NULL) {
342 return ATTEST_ERR;
343 }
344 int32_t *head = *resultArray;
345 head[ATTEST_RESULT_AUTH] = AttestStatusTrans(authStatus->hardwareResult);
346 head[ATTEST_RESULT_SOFTWARE] = AttestStatusTrans(authStatus->softwareResult);
347 SoftwareResultDetail *softwareResultDetail = (SoftwareResultDetail *)authStatus->softwareResultDetail;
348 if (softwareResultDetail == NULL) {
349 ATTEST_LOG_ERROR("[CopyResultArray] failed to get softwareResultDetail");
350 return ATTEST_ERR;
351 }
352 head[ATTEST_RESULT_VERSIONID] = AttestStatusTrans(softwareResultDetail->versionIdResult);
353 head[ATTEST_RESULT_PATCHLEVEL] = AttestStatusTrans(softwareResultDetail->patchLevelResult);
354 head[ATTEST_RESULT_ROOTHASH] = AttestStatusTrans(softwareResultDetail->rootHashResult);
355 head[ATTEST_RESULT_PCID] = AttestStatusTrans(softwareResultDetail->pcidResult);
356 head[ATTEST_RESULT_RESERVE] = DEVICE_ATTEST_INIT; // Always equal to DEVICE_ATTEST_INIT
357 return ATTEST_OK;
358 }
359
SetAttestResultArray(int32_t ** resultArray,int32_t value)360 static int32_t SetAttestResultArray(int32_t** resultArray, int32_t value)
361 {
362 if (resultArray == NULL) {
363 return ATTEST_ERR;
364 }
365 int32_t *head = *resultArray;
366 for (int32_t i = 0; i < ATTEST_RESULT_MAX; i++) {
367 head[i] = value;
368 }
369 head[ATTEST_RESULT_RESERVE] = DEVICE_ATTEST_INIT; // Always equal to DEVICE_ATTEST_INIT
370 return ATTEST_OK;
371 }
372
SetAttestStatusDefault(int32_t ** resultArray,char ** ticket,int32_t * ticketLength)373 static int32_t SetAttestStatusDefault(int32_t** resultArray, char** ticket, int32_t* ticketLength)
374 {
375 int32_t ret = SetAttestResultArray(resultArray, DEVICE_ATTEST_INIT);
376 *ticket = "";
377 *ticketLength = 0;
378 return ret;
379 }
380
SetAttestStatusFailed(int32_t ** resultArray,char ** ticket,int32_t * ticketLength)381 static int32_t SetAttestStatusFailed(int32_t** resultArray, char** ticket, int32_t* ticketLength)
382 {
383 int32_t ret = SetAttestResultArray(resultArray, DEVICE_ATTEST_FAIL);
384 *ticket = "";
385 *ticketLength = 0;
386 return ret;
387 }
388
SetAttestStatusSucc(int32_t ** resultArray,char ** ticket,int32_t * ticketLength)389 static int32_t SetAttestStatusSucc(int32_t** resultArray, char** ticket, int32_t* ticketLength)
390 {
391 char* authStatusBase64 = NULL;
392 AuthStatus* authStatus = CreateAuthStatus();
393 int32_t ret = ATTEST_OK;
394 do {
395 *ticket = "";
396 *ticketLength = 0;
397 // 获取认证结果
398 if (GetAuthStatus(&authStatusBase64) != ATTEST_OK) {
399 ATTEST_LOG_ERROR("[SetAttestStatusSucc] Load Auth Status failed, auth file not exist");
400 ret = ATTEST_ERR;
401 break;
402 }
403 if (DecodeAuthStatus((const char*)authStatusBase64, authStatus) != ATTEST_OK) {
404 ATTEST_LOG_ERROR("[SetAttestStatusSucc] Decode Auth Status failed");
405 ret = ATTEST_ERR;
406 break;
407 }
408 if (authStatus->hardwareResult != 0) {
409 break;
410 }
411 // 获取token
412 char* decryptedTicket = (char *)ATTEST_MEM_MALLOC(MAX_TICKET_LEN + 1);
413 if (decryptedTicket == NULL) {
414 ATTEST_LOG_ERROR("[SetAttestStatusSucc] buff malloc memory failed");
415 ret = ATTEST_ERR;
416 break;
417 }
418 if (ReadTicketFromDevice(decryptedTicket, MAX_TICKET_LEN) != ATTEST_OK) {
419 ATTEST_LOG_ERROR("[SetAttestStatusSucc] read ticket from device failed");
420 ATTEST_MEM_FREE(decryptedTicket);
421 ret = ATTEST_ERR;
422 break;
423 }
424 *ticket = decryptedTicket;
425 *ticketLength = strlen(*ticket);
426 } while (0);
427 ATTEST_MEM_FREE(authStatusBase64);
428 if (ret != ATTEST_OK) {
429 DestroyAuthStatus(&authStatus);
430 return ret;
431 }
432 ret = CopyResultArray(authStatus, resultArray);
433 DestroyAuthStatus(&authStatus);
434 return ret;
435 }
436
QueryAttestStatusSwitch(int32_t ** resultArray,int32_t arraySize,char ** ticket,int32_t * ticketLength)437 static int32_t QueryAttestStatusSwitch(int32_t** resultArray, int32_t arraySize, char** ticket, int32_t* ticketLength)
438 {
439 if (resultArray == NULL || arraySize != ATTEST_RESULT_MAX || ticket == NULL) {
440 ATTEST_LOG_ERROR("[QueryAttestStatusSwitch] parameter wrong");
441 return ATTEST_ERR;
442 }
443 int32_t ret = ATTEST_ERR;
444 int32_t authResultCode = GetAuthResultCode();
445 switch (authResultCode) {
446 case (AUTH_UNKNOWN):
447 ret = SetAttestStatusDefault(resultArray, ticket, ticketLength);
448 ATTEST_LOG_INFO("[QueryAttestStatusSwitch] authResultCode is 2, ret = %d", ret);
449 break;
450 case (AUTH_FAILED):
451 ret = SetAttestStatusFailed(resultArray, ticket, ticketLength);
452 ATTEST_LOG_INFO("[QueryAttestStatusSwitch] authResultCode is 1, ret = %d", ret);
453 break;
454 case (AUTH_SUCCESS):
455 ret = SetAttestStatusSucc(resultArray, ticket, ticketLength);
456 ATTEST_LOG_INFO("[QueryAttestStatusSwitch] authResultCode is 0, ret = %d", ret);
457 break;
458 default:
459 ATTEST_LOG_WARN("[QueryAttestStatusSwitch] authResultCode is invalid");
460 break;
461 }
462 return ret;
463 }
464
QueryAttestStatus(int32_t ** resultArray,int32_t arraySize,char ** ticket,int32_t * ticketLength)465 int32_t QueryAttestStatus(int32_t** resultArray, int32_t arraySize, char** ticket, int32_t* ticketLength)
466 {
467 pthread_mutex_lock(&g_mtxAttest);
468 int32_t ret = QueryAttestStatusSwitch(resultArray, arraySize, ticket, ticketLength);
469 if (ret != ATTEST_OK) {
470 ATTEST_LOG_ERROR("[QueryAttestStatus] failed ret = %d.", ret);
471 }
472 pthread_mutex_unlock(&g_mtxAttest);
473 return ret;
474 }
475
AttestWaitTaskOverImpl(void)476 int32_t AttestWaitTaskOverImpl(void)
477 {
478 pthread_mutex_lock(&g_mtxAttest);
479 int32_t ret = ATTEST_OK;
480 pthread_mutex_unlock(&g_mtxAttest);
481 return ret;
482 }