• 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     // token激活
247     ATTEST_LOG_INFO("[AttestStartup] Active token.");
248     for (int32_t i = 0; i <= WISE_RETRY_CNT; i++) {
249         ret = ActiveToken(authResult);
250         if (!IS_WISE_RETRY(-ret)) {
251             break;
252         }
253     }
254     if (ret != ATTEST_OK) {
255         ATTEST_LOG_ERROR("[AttestStartup] Active token failed, ret = %d.", ret);
256         return ATTEST_ERR;
257     }
258     return ATTEST_OK;
259 }
260 
ProcAttestImpl(void)261 static int32_t ProcAttestImpl(void)
262 {
263     // 初始化系统参数
264     int32_t ret = InitSysData();
265     if (ret != ATTEST_OK) {
266         ATTEST_LOG_ERROR("[ProcAttestImpl] Init system device param failed, ret = %d.", ret);
267         DestroySysData();
268         return ATTEST_ERR;
269     }
270     // 检查本地数据是否修改或过期,进行重新认证
271     if (!IsAuthStatusChg()) {
272         ATTEST_LOG_WARN("[ProcAttestImpl] There is no change on auth status.");
273         UpdateAuthResultCode(AUTH_SUCCESS);
274         DestroySysData();
275         return ATTEST_OK;
276     }
277     AuthResult *authResult = CreateAuthResult();
278     if (authResult == NULL) {
279         ATTEST_LOG_ERROR("[ProcAttestImpl] Create auth result failed");
280         DestroySysData();
281         return ATTEST_ERR;
282     }
283     ret = AttestStartup(authResult);
284     DestroySysData();
285     DestroyAuthResult(&authResult);
286     return ret;
287 }
288 
ProcAttest(void)289 int32_t ProcAttest(void)
290 {
291     pthread_mutex_lock(&g_mtxAttest);
292     PrintCurrentTime();
293     int32_t ret;
294     if (ATTEST_DEBUG_MEMORY_LEAK) {
295         ret = InitMemNodeList();
296         ATTEST_LOG_INFO("[ProcAttest] Init mem node list, ret = %d.", ret);
297     }
298     // init network server info
299     ret = InitNetworkServerInfo();
300     if (ret != ATTEST_OK) {
301         ATTEST_LOG_ERROR("[ProcAttest] InitNetworkServerInfo failed, ret = %d.", ret);
302     }
303     // 主流程
304     ret = ProcAttestImpl();
305     if (ret != ATTEST_OK) {
306         ATTEST_LOG_ERROR("[ProcAttest] Proc Attest failed, ret = %d.", ret);
307     }
308     if (ATTEST_DEBUG_MEMORY_LEAK) {
309         PrintMemNodeList();
310         ret = DestroyMemNodeList();
311         ATTEST_LOG_INFO("[ProcAttest] Destroy mem node list,  ret = %d.", ret);
312     }
313     PrintCurrentTime();
314     pthread_mutex_unlock(&g_mtxAttest);
315     return ret;
316 }
317 
AttestStatusTrans(int32_t attestStatus)318 static int32_t AttestStatusTrans(int32_t attestStatus)
319 {
320     return (attestStatus == 0) ? 0 : -1;
321 }
322 
CopyResultArray(AuthStatus * authStatus,int32_t ** resultArray)323 static int32_t CopyResultArray(AuthStatus* authStatus, int32_t** resultArray)
324 {
325     if (authStatus == NULL || resultArray == NULL) {
326         return ATTEST_ERR;
327     }
328     int32_t *head = *resultArray;
329     head[ATTEST_RESULT_AUTH] = AttestStatusTrans(authStatus->hardwareResult);
330     head[ATTEST_RESULT_SOFTWARE] = AttestStatusTrans(authStatus->softwareResult);
331     SoftwareResultDetail *softwareResultDetail = (SoftwareResultDetail *)authStatus->softwareResultDetail;
332     if (softwareResultDetail == NULL) {
333         ATTEST_LOG_ERROR("[CopyResultArray] failed to get softwareResultDetail");
334         return ATTEST_ERR;
335     }
336     head[ATTEST_RESULT_VERSIONID] = AttestStatusTrans(softwareResultDetail->versionIdResult);
337     head[ATTEST_RESULT_PATCHLEVEL] = AttestStatusTrans(softwareResultDetail->patchLevelResult);
338     head[ATTEST_RESULT_ROOTHASH] = AttestStatusTrans(softwareResultDetail->rootHashResult);
339     head[ATTEST_RESULT_PCID] = AttestStatusTrans(softwareResultDetail->pcidResult);
340     head[ATTEST_RESULT_RESERVE] = DEVICE_ATTEST_INIT;
341     return ATTEST_OK;
342 }
343 
SetAttestResultArray(int32_t ** resultArray,int32_t value)344 static int32_t SetAttestResultArray(int32_t** resultArray, int32_t value)
345 {
346     if (resultArray == NULL) {
347         return ATTEST_ERR;
348     }
349     int32_t *head = *resultArray;
350     for (int32_t i = 0; i < ATTEST_RESULT_MAX; i++) {
351         head[i] = value;
352     }
353     return ATTEST_OK;
354 }
355 
SetAttestStatusDefault(int32_t ** resultArray,char ** ticket,int32_t * ticketLength)356 static int32_t SetAttestStatusDefault(int32_t** resultArray, char** ticket, int32_t* ticketLength)
357 {
358     int32_t ret = SetAttestResultArray(resultArray, DEVICE_ATTEST_INIT);
359     *ticket = "";
360     *ticketLength = 0;
361     return ret;
362 }
363 
SetAttestStatusFailed(int32_t ** resultArray,char ** ticket,int32_t * ticketLength)364 static int32_t SetAttestStatusFailed(int32_t** resultArray, char** ticket, int32_t* ticketLength)
365 {
366     int32_t ret = SetAttestResultArray(resultArray, DEVICE_ATTEST_FAIL);
367     *ticket = "";
368     *ticketLength = 0;
369     return ret;
370 }
371 
SetAttestStatusSucc(int32_t ** resultArray,char ** ticket,int32_t * ticketLength)372 static int32_t SetAttestStatusSucc(int32_t** resultArray, char** ticket, int32_t* ticketLength)
373 {
374     char* authStatusBase64 = NULL;
375     AuthStatus* authStatus = CreateAuthStatus();
376     int32_t ret = ATTEST_OK;
377     do {
378         *ticket = "";
379         *ticketLength = 0;
380         // 获取认证结果
381         if (GetAuthStatus(&authStatusBase64) != ATTEST_OK) {
382             ATTEST_LOG_ERROR("[SetAttestStatusSucc] Load Auth Status failed, auth file not exist");
383             ret = ATTEST_ERR;
384             break;
385         }
386         if (DecodeAuthStatus((const char*)authStatusBase64, authStatus) != ATTEST_OK) {
387             ATTEST_LOG_ERROR("[SetAttestStatusSucc] Decode Auth Status failed");
388             ret = ATTEST_ERR;
389             break;
390         }
391         if (authStatus->hardwareResult != 0) {
392             break;
393         }
394         // 获取token
395         char* decryptedTicket = (char *)ATTEST_MEM_MALLOC(MAX_TICKET_LEN + 1);
396         if (decryptedTicket == NULL) {
397             ATTEST_LOG_ERROR("[SetAttestStatusSucc] buff malloc memory failed");
398             ret = ATTEST_ERR;
399             break;
400         }
401         if (ReadTicketFromDevice(decryptedTicket, MAX_TICKET_LEN) != ATTEST_OK) {
402             ATTEST_LOG_ERROR("[SetAttestStatusSucc] read ticket from device failed");
403             ATTEST_MEM_FREE(decryptedTicket);
404             ret = ATTEST_ERR;
405             break;
406         }
407         *ticket = decryptedTicket;
408         *ticketLength = strlen(*ticket);
409     } while (0);
410     ATTEST_MEM_FREE(authStatusBase64);
411     if (ret != ATTEST_OK) {
412         DestroyAuthStatus(&authStatus);
413         return ret;
414     }
415     ret = CopyResultArray(authStatus, resultArray);
416     DestroyAuthStatus(&authStatus);
417     return ret;
418 }
419 
QueryAttestStatusSwitch(int32_t ** resultArray,int32_t arraySize,char ** ticket,int32_t * ticketLength)420 static int32_t QueryAttestStatusSwitch(int32_t** resultArray, int32_t arraySize, char** ticket, int32_t* ticketLength)
421 {
422     if (resultArray == NULL || arraySize != ATTEST_RESULT_MAX || ticket == NULL) {
423         ATTEST_LOG_ERROR("[QueryAttestStatusSwitch] parameter wrong");
424         return ATTEST_ERR;
425     }
426     int32_t ret = ATTEST_ERR;
427     int32_t authResultCode = GetAuthResultCode();
428     switch (authResultCode) {
429         case (AUTH_UNKNOWN):
430             ret = SetAttestStatusDefault(resultArray, ticket, ticketLength);
431             ATTEST_LOG_INFO("[QueryAttestStatusSwitch] authResultCode is 2, ret = %d", ret);
432             break;
433         case (AUTH_FAILED):
434             ret = SetAttestStatusFailed(resultArray, ticket, ticketLength);
435             ATTEST_LOG_INFO("[QueryAttestStatusSwitch] authResultCode is 1, ret = %d", ret);
436             break;
437         case (AUTH_SUCCESS):
438             ret = SetAttestStatusSucc(resultArray, ticket, ticketLength);
439             ATTEST_LOG_INFO("[QueryAttestStatusSwitch] authResultCode is 0, ret = %d", ret);
440             break;
441         default:
442             ATTEST_LOG_INFO("[QueryAttestStatusSwitch] authResultCode is invalid");
443             break;
444     }
445     return ret;
446 }
447 
QueryAttestStatus(int32_t ** resultArray,int32_t arraySize,char ** ticket,int32_t * ticketLength)448 int32_t QueryAttestStatus(int32_t** resultArray, int32_t arraySize, char** ticket, int32_t* ticketLength)
449 {
450     pthread_mutex_lock(&g_mtxAttest);
451     int32_t ret = QueryAttestStatusSwitch(resultArray, arraySize, ticket, ticketLength);
452     if (ret != ATTEST_OK) {
453         ATTEST_LOG_ERROR("[QueryAttestStatus] failed ret = %d.", ret);
454     }
455     pthread_mutex_unlock(&g_mtxAttest);
456     return ret;
457 }
458