• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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