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