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 if (ATTEST_DEBUG_MEMORY_LEAK) {
299 ret = InitMemNodeList();
300 ATTEST_LOG_INFO("[ProcAttest] Init mem node list, ret = %d.", ret);
301 }
302 // init network server info
303 ret = InitNetworkServerInfo();
304 if (ret != ATTEST_OK) {
305 ATTEST_LOG_ERROR("[ProcAttest] InitNetworkServerInfo failed, ret = %d.", ret);
306 }
307 // 主流程
308 ret = ProcAttestImpl();
309 if (ret != ATTEST_OK) {
310 ATTEST_LOG_ERROR("[ProcAttest] Proc Attest failed, ret = %d.", ret);
311 }
312 if (ATTEST_DEBUG_MEMORY_LEAK) {
313 PrintMemNodeList();
314 ret = DestroyMemNodeList();
315 ATTEST_LOG_INFO("[ProcAttest] Destroy mem node list, ret = %d.", ret);
316 }
317 PrintCurrentTime();
318 pthread_mutex_unlock(&g_mtxAttest);
319 return ret;
320 }
321
AttestStatusTrans(int32_t attestStatus)322 static int32_t AttestStatusTrans(int32_t attestStatus)
323 {
324 return (attestStatus == 0) ? 0 : -1;
325 }
326
CopyResultArray(AuthStatus * authStatus,int32_t ** resultArray)327 static int32_t CopyResultArray(AuthStatus* authStatus, int32_t** resultArray)
328 {
329 if (authStatus == NULL || resultArray == NULL) {
330 return ATTEST_ERR;
331 }
332 int32_t *head = *resultArray;
333 head[ATTEST_RESULT_AUTH] = AttestStatusTrans(authStatus->hardwareResult);
334 head[ATTEST_RESULT_SOFTWARE] = AttestStatusTrans(authStatus->softwareResult);
335 SoftwareResultDetail *softwareResultDetail = (SoftwareResultDetail *)authStatus->softwareResultDetail;
336 if (softwareResultDetail == NULL) {
337 ATTEST_LOG_ERROR("[CopyResultArray] failed to get softwareResultDetail");
338 return ATTEST_ERR;
339 }
340 head[ATTEST_RESULT_VERSIONID] = AttestStatusTrans(softwareResultDetail->versionIdResult);
341 head[ATTEST_RESULT_PATCHLEVEL] = AttestStatusTrans(softwareResultDetail->patchLevelResult);
342 head[ATTEST_RESULT_ROOTHASH] = AttestStatusTrans(softwareResultDetail->rootHashResult);
343 head[ATTEST_RESULT_PCID] = AttestStatusTrans(softwareResultDetail->pcidResult);
344 head[ATTEST_RESULT_RESERVE] = DEVICE_ATTEST_INIT; // Always equal to DEVICE_ATTEST_INIT
345 return ATTEST_OK;
346 }
347
SetAttestResultArray(int32_t ** resultArray,int32_t value)348 static int32_t SetAttestResultArray(int32_t** resultArray, int32_t value)
349 {
350 if (resultArray == NULL) {
351 return ATTEST_ERR;
352 }
353 int32_t *head = *resultArray;
354 for (int32_t i = 0; i < ATTEST_RESULT_MAX; i++) {
355 head[i] = value;
356 }
357 head[ATTEST_RESULT_RESERVE] = DEVICE_ATTEST_INIT; // Always equal to DEVICE_ATTEST_INIT
358 return ATTEST_OK;
359 }
360
SetAttestStatusDefault(int32_t ** resultArray,char ** ticket,int32_t * ticketLength)361 static int32_t SetAttestStatusDefault(int32_t** resultArray, char** ticket, int32_t* ticketLength)
362 {
363 int32_t ret = SetAttestResultArray(resultArray, DEVICE_ATTEST_INIT);
364 *ticket = "";
365 *ticketLength = 0;
366 return ret;
367 }
368
SetAttestStatusFailed(int32_t ** resultArray,char ** ticket,int32_t * ticketLength)369 static int32_t SetAttestStatusFailed(int32_t** resultArray, char** ticket, int32_t* ticketLength)
370 {
371 int32_t ret = SetAttestResultArray(resultArray, DEVICE_ATTEST_FAIL);
372 *ticket = "";
373 *ticketLength = 0;
374 return ret;
375 }
376
SetAttestStatusSucc(int32_t ** resultArray,char ** ticket,int32_t * ticketLength)377 static int32_t SetAttestStatusSucc(int32_t** resultArray, char** ticket, int32_t* ticketLength)
378 {
379 char* authStatusBase64 = NULL;
380 AuthStatus* authStatus = CreateAuthStatus();
381 int32_t ret = ATTEST_OK;
382 do {
383 *ticket = "";
384 *ticketLength = 0;
385 // 获取认证结果
386 if (GetAuthStatus(&authStatusBase64) != ATTEST_OK) {
387 ATTEST_LOG_ERROR("[SetAttestStatusSucc] Load Auth Status failed, auth file not exist");
388 ret = ATTEST_ERR;
389 break;
390 }
391 if (DecodeAuthStatus((const char*)authStatusBase64, authStatus) != ATTEST_OK) {
392 ATTEST_LOG_ERROR("[SetAttestStatusSucc] Decode Auth Status failed");
393 ret = ATTEST_ERR;
394 break;
395 }
396 if (authStatus->hardwareResult != 0) {
397 break;
398 }
399 // 获取token
400 char* decryptedTicket = (char *)ATTEST_MEM_MALLOC(MAX_TICKET_LEN + 1);
401 if (decryptedTicket == NULL) {
402 ATTEST_LOG_ERROR("[SetAttestStatusSucc] buff malloc memory failed");
403 ret = ATTEST_ERR;
404 break;
405 }
406 if (ReadTicketFromDevice(decryptedTicket, MAX_TICKET_LEN) != ATTEST_OK) {
407 ATTEST_LOG_ERROR("[SetAttestStatusSucc] read ticket from device failed");
408 ATTEST_MEM_FREE(decryptedTicket);
409 ret = ATTEST_ERR;
410 break;
411 }
412 *ticket = decryptedTicket;
413 *ticketLength = strlen(*ticket);
414 } while (0);
415 ATTEST_MEM_FREE(authStatusBase64);
416 if (ret != ATTEST_OK) {
417 DestroyAuthStatus(&authStatus);
418 return ret;
419 }
420 ret = CopyResultArray(authStatus, resultArray);
421 DestroyAuthStatus(&authStatus);
422 return ret;
423 }
424
QueryAttestStatusSwitch(int32_t ** resultArray,int32_t arraySize,char ** ticket,int32_t * ticketLength)425 static int32_t QueryAttestStatusSwitch(int32_t** resultArray, int32_t arraySize, char** ticket, int32_t* ticketLength)
426 {
427 if (resultArray == NULL || arraySize != ATTEST_RESULT_MAX || ticket == NULL) {
428 ATTEST_LOG_ERROR("[QueryAttestStatusSwitch] parameter wrong");
429 return ATTEST_ERR;
430 }
431 int32_t ret = ATTEST_ERR;
432 int32_t authResultCode = GetAuthResultCode();
433 switch (authResultCode) {
434 case (AUTH_UNKNOWN):
435 ret = SetAttestStatusDefault(resultArray, ticket, ticketLength);
436 ATTEST_LOG_INFO("[QueryAttestStatusSwitch] authResultCode is 2, ret = %d", ret);
437 break;
438 case (AUTH_FAILED):
439 ret = SetAttestStatusFailed(resultArray, ticket, ticketLength);
440 ATTEST_LOG_INFO("[QueryAttestStatusSwitch] authResultCode is 1, ret = %d", ret);
441 break;
442 case (AUTH_SUCCESS):
443 ret = SetAttestStatusSucc(resultArray, ticket, ticketLength);
444 ATTEST_LOG_INFO("[QueryAttestStatusSwitch] authResultCode is 0, ret = %d", ret);
445 break;
446 default:
447 ATTEST_LOG_WARN("[QueryAttestStatusSwitch] authResultCode is invalid");
448 break;
449 }
450 return ret;
451 }
452
QueryAttestStatus(int32_t ** resultArray,int32_t arraySize,char ** ticket,int32_t * ticketLength)453 int32_t QueryAttestStatus(int32_t** resultArray, int32_t arraySize, char** ticket, int32_t* ticketLength)
454 {
455 pthread_mutex_lock(&g_mtxAttest);
456 int32_t ret = QueryAttestStatusSwitch(resultArray, arraySize, ticket, ticketLength);
457 if (ret != ATTEST_OK) {
458 ATTEST_LOG_ERROR("[QueryAttestStatus] failed ret = %d.", ret);
459 }
460 pthread_mutex_unlock(&g_mtxAttest);
461 return ret;
462 }
463
AttestWaitTaskOverImpl(void)464 int32_t AttestWaitTaskOverImpl(void)
465 {
466 pthread_mutex_lock(&g_mtxAttest);
467 int32_t ret = ATTEST_OK;
468 pthread_mutex_unlock(&g_mtxAttest);
469 return ret;
470 }