• 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 <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 }