1  /*
2   * Copyright (c) 2024 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 "verifier_func.h"
17  
18  #include "securec.h"
19  
20  #include "adaptor_algorithm.h"
21  #include "adaptor_log.h"
22  #include "adaptor_memory.h"
23  #include "attribute.h"
24  #include "buffer.h"
25  #include "pin_db.h"
26  
27  typedef enum VerifierState {
28      VERIFIER_STATE_INIT = 0,
29      VERIFIER_STATE_WAIT_SYNC = 1,
30      VERIFIER_STATE_WAIT_ACK = 2,
31      VERIFIER_STATE_FINISH = 3,
32  } VerifierState;
33  
34  typedef struct VerifierSchedule {
35      uint64_t scheduleId;
36      uint64_t templateId;
37      uint64_t timeStamp;
38      Buffer *selfUdid;
39      Buffer *peerUdid;
40      Buffer *peerPubKey;
41      Buffer *salt;
42      VerifierState state;
43  } VerifierSchedule;
44  
45  static KeyPair *g_keyPair = NULL;
46  static Buffer *g_fwkPubKey = NULL;
47  static VerifierSchedule *g_verifierSchedule = NULL;
48  
49  /* This is for example only, Should be implemented in trusted environment. */
GenerateVerifierKeyPair(void)50  ResultCode GenerateVerifierKeyPair(void)
51  {
52      DestroyKeyPair(g_keyPair);
53      g_keyPair = GenerateEd25519KeyPair();
54      if (g_keyPair == NULL) {
55          LOG_ERROR("GenerateVerifierKeyPair fail!");
56          return RESULT_GENERAL_ERROR;
57      }
58      LOG_INFO("GenerateVerifierKeyPair success");
59      return RESULT_SUCCESS;
60  }
61  
DestroyVerifierKeyPair(void)62  void DestroyVerifierKeyPair(void)
63  {
64      LOG_INFO("DestroyVerifierKeyPair");
65      DestroyKeyPair(g_keyPair);
66      g_keyPair = NULL;
67  }
68  
69  /* This is for example only, Should be implemented in trusted environment. */
DoGetVerifierExecutorInfo(PinExecutorInfo * pinExecutorInfo)70  ResultCode DoGetVerifierExecutorInfo(PinExecutorInfo *pinExecutorInfo)
71  {
72      if (pinExecutorInfo == NULL) {
73          LOG_ERROR("check param fail!");
74          return RESULT_BAD_PARAM;
75      }
76      if (!IsEd25519KeyPairValid(g_keyPair)) {
77          LOG_ERROR("key pair not init!");
78          return RESULT_NEED_INIT;
79      }
80      uint32_t pubKeyLen = ED25519_FIX_PUBKEY_BUFFER_SIZE;
81      if (GetBufferData(g_keyPair->pubKey, pinExecutorInfo->pubKey, &pubKeyLen) != RESULT_SUCCESS) {
82          LOG_ERROR("GetBufferData fail!");
83          return RESULT_UNKNOWN;
84      }
85      pinExecutorInfo->esl = PIN_EXECUTOR_SECURITY_LEVEL;
86      pinExecutorInfo->maxTemplateAcl = PIN_CAPABILITY_LEVEL;
87      return RESULT_SUCCESS;
88  }
89  
DoSetVerifierFwkParam(const uint8_t * fwkPubKey,uint32_t fwkPubKeySize)90  int32_t DoSetVerifierFwkParam(const uint8_t *fwkPubKey, uint32_t fwkPubKeySize)
91  {
92      if ((fwkPubKey == NULL) || (fwkPubKeySize != ED25519_FIX_PUBKEY_BUFFER_SIZE)) {
93          LOG_ERROR("DoSetVerifierFwkParam check param fail!");
94          return RESULT_BAD_PARAM;
95      }
96      DestroyBuffer(g_fwkPubKey);
97      g_fwkPubKey = CreateBufferByData(fwkPubKey, fwkPubKeySize);
98      if (g_fwkPubKey == NULL) {
99          LOG_ERROR("DoSetVerifierFwkParam create fwkPubKey fail!");
100          return RESULT_NO_MEMORY;
101      }
102      return RESULT_SUCCESS;
103  }
104  
DestroyVerifierSchedule(void)105  static void DestroyVerifierSchedule(void)
106  {
107      if (g_verifierSchedule == NULL) {
108          return;
109      }
110      DestroyBuffer(g_verifierSchedule->selfUdid);
111      DestroyBuffer(g_verifierSchedule->peerUdid);
112      DestroyBuffer(g_verifierSchedule->peerPubKey);
113      DestroyBuffer(g_verifierSchedule->salt);
114      Free(g_verifierSchedule);
115      g_verifierSchedule= NULL;
116  }
117  
InitVerifierSchedule(uint64_t scheduleId)118  static bool InitVerifierSchedule(uint64_t scheduleId)
119  {
120      g_verifierSchedule = Malloc(sizeof(VerifierSchedule));
121      if (g_verifierSchedule == NULL) {
122          LOG_ERROR("malloc VerifierSchedule fail!");
123          return false;
124      }
125      (void)memset_s(g_verifierSchedule, sizeof(VerifierSchedule), 0, sizeof(VerifierSchedule));
126      g_verifierSchedule->scheduleId = scheduleId;
127      return true;
128  }
129  
GetAuthInfoFromSchedule(uint64_t scheduleId,const uint8_t * extraInfo,uint32_t extraInfoSize)130  static int32_t GetAuthInfoFromSchedule(uint64_t scheduleId, const uint8_t *extraInfo, uint32_t extraInfoSize)
131  {
132      Attribute *attribute = NULL;
133      int32_t result = VerifyAndGetDataAttribute(scheduleId, &attribute, g_fwkPubKey, extraInfo, extraInfoSize);
134      IF_TRUE_LOGE_AND_RETURN_VAL(result != RESULT_SUCCESS, result);
135  
136      result = RESULT_GENERAL_ERROR;
137      g_verifierSchedule->selfUdid = GetBufferFromAttribute(attribute, ATTR_LOCAL_UDID, CONST_FWK_UDID_SIZE);
138      if (g_verifierSchedule->selfUdid == NULL) {
139          LOG_ERROR("get self udid fail!");
140          goto EXIT;
141      }
142      g_verifierSchedule->peerUdid = GetBufferFromAttribute(attribute, ATTR_PEER_UDID, CONST_FWK_UDID_SIZE);
143      if (g_verifierSchedule->peerUdid == NULL) {
144          LOG_ERROR("get peer udid fail!");
145          goto EXIT;
146      }
147      g_verifierSchedule->peerPubKey = GetBufferFromAttribute(
148          attribute, ATTR_PUBLIC_KEY, ED25519_FIX_PUBKEY_BUFFER_SIZE);
149      if (g_verifierSchedule->peerPubKey == NULL) {
150          LOG_ERROR("get peer public key fail!");
151          goto EXIT;
152      }
153      result = RESULT_SUCCESS;
154  
155  EXIT:
156      FreeAttribute(&attribute);
157      return result;
158  }
159  
SetVerifyAckDataSalt(Attribute * attribute)160  static bool SetVerifyAckDataSalt(Attribute *attribute)
161  {
162      if (g_verifierSchedule->salt != NULL) {
163          LOG_ERROR("get non null salt!");
164          return false;
165      }
166      g_verifierSchedule->salt = CreateBufferBySize(CONST_KEK_SALT_SIZE);
167      if (g_verifierSchedule->salt == NULL) {
168          LOG_ERROR("create salt fail!");
169          return false;
170      }
171      int32_t result = SecureRandom(g_verifierSchedule->salt->buf, g_verifierSchedule->salt->maxSize);
172      if (result != RESULT_SUCCESS) {
173          LOG_ERROR("random salt fail!");
174          return false;
175      }
176      g_verifierSchedule->salt->contentSize = g_verifierSchedule->salt->maxSize;
177      if (SetBufferToAttribute(attribute, PIN_ATTR_KEK_SALT, g_verifierSchedule->salt) != RESULT_SUCCESS) {
178          LOG_ERROR("set salt fail!");
179          return false;
180      }
181      return true;
182  }
183  
SetVerifyAckDataPinParam(Attribute * attribute)184  static bool SetVerifyAckDataPinParam(Attribute *attribute)
185  {
186      uint64_t subType = 0;
187      if (GetSubType(g_verifierSchedule->templateId, &subType) != RESULT_SUCCESS) {
188          LOG_ERROR("GetSubType fail!");
189          return false;
190      }
191      if (SetAttributeUint64(attribute, ATTR_PIN_SUB_TYPE, subType) != RESULT_SUCCESS) {
192          LOG_ERROR("set sub type fail!");
193          return false;
194      }
195  
196      Buffer *algoParam = CreateBufferBySize(CONST_SALT_LEN);
197      if (algoParam == NULL) {
198          LOG_ERROR("create algoParam fail!");
199          return false;
200      }
201      algoParam->contentSize = algoParam->maxSize;
202      uint32_t algoVersion = 0;
203      int32_t result = DoGetAlgoParameter(
204          g_verifierSchedule->templateId, algoParam->buf, &(algoParam->contentSize), &algoVersion);
205      if (result != RESULT_SUCCESS) {
206          LOG_ERROR("DoGetAlgoParameter fail!");
207          DestroyBuffer(algoParam);
208          return false;
209      }
210      if (SetBufferToAttribute(attribute, PIN_ATTR_ALGO_PARAM, algoParam) != RESULT_SUCCESS) {
211          LOG_ERROR("set algo param fail!");
212          DestroyBuffer(algoParam);
213          return false;
214      }
215      DestroyBuffer(algoParam);
216      if (SetAttributeUint32(attribute, PIN_ATTR_ALGO_VERSION, algoVersion) != RESULT_SUCCESS) {
217          LOG_ERROR("set algo version fail!");
218          return false;
219      }
220      return true;
221  }
222  
GetVerifyAckData()223  static Attribute *GetVerifyAckData()
224  {
225      Attribute *attribute = GetAttributeDataBase(g_verifierSchedule->scheduleId, REMOTE_PIN_VERIFIER_ACK);
226      IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, NULL);
227  
228      if (!SetVerifyAckDataSalt(attribute)) {
229          LOG_ERROR("SetVerifyAckDataSalt fail!");
230          goto ERROR;
231      }
232  
233      if (!SetVerifyAckDataPinParam(attribute)) {
234          LOG_ERROR("SetVerifyAckDataPinParam fail!");
235          goto ERROR;
236      }
237  
238      return attribute;
239  
240  ERROR:
241      FreeAttribute(&attribute);
242      return NULL;
243  }
244  
GetResultTlv(VerifierMsg * verifierMsg)245  static int32_t GetResultTlv(VerifierMsg *verifierMsg)
246  {
247      Attribute *attribute = GetAttributeDataBase(g_verifierSchedule->scheduleId, REMOTE_PIN_MSG_NONE);
248      IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, RESULT_GENERAL_ERROR);
249  
250      int32_t result = RESULT_GENERAL_ERROR;
251      if (!SetResultDataInfo(
252          attribute, PinResultToFwkResult(verifierMsg->authResult), g_verifierSchedule->templateId, NULL)) {
253          LOG_ERROR("SetResultDataInfo fail");
254          goto EXIT;
255      }
256  
257      result = FormatTlvMsg(attribute, g_keyPair, verifierMsg->msgOut, &(verifierMsg->msgOutSize));
258      if (result != RESULT_SUCCESS) {
259          LOG_ERROR("FormatTlvMsg fail");
260          goto EXIT;
261      }
262  
263  EXIT:
264      FreeAttribute(&attribute);
265      return result;
266  }
267  
IsVeriferMsgValid(VerifierMsg * verifierMsg)268  static bool IsVeriferMsgValid(VerifierMsg *verifierMsg)
269  {
270      if (verifierMsg == NULL) {
271          LOG_ERROR("verifierMsg is null");
272          return false;
273      }
274      if ((verifierMsg->msgIn == NULL) || (verifierMsg->msgInSize == 0)) {
275          LOG_ERROR("verifierMsg msgIn is invalid");
276          return false;
277      }
278      if ((verifierMsg->msgOut == NULL) || (verifierMsg->msgOutSize == 0)) {
279          LOG_ERROR("verifierMsg msgOut is invalid");
280          return false;
281      }
282      return true;
283  }
284  
DoVerifierAuth(uint64_t scheduleId,uint64_t templateId,VerifierMsg * verifierMsg)285  int32_t DoVerifierAuth(uint64_t scheduleId, uint64_t templateId, VerifierMsg *verifierMsg)
286  {
287      LOG_INFO("DoVerifierAuth start %{public}x", (uint16_t)scheduleId);
288      if (!IsVeriferMsgValid(verifierMsg)) {
289          LOG_ERROR("check param fail!");
290          return RESULT_BAD_PARAM;
291      }
292      DestroyVerifierSchedule();
293      if (!InitVerifierSchedule(scheduleId)) {
294          LOG_ERROR("InitVerifierSchedule fail!");
295          return RESULT_GENERAL_ERROR;
296      }
297      int32_t result = GetAuthInfoFromSchedule(scheduleId, verifierMsg->msgIn, verifierMsg->msgInSize);
298      if (result != RESULT_SUCCESS) {
299          LOG_ERROR("GetAuthInfoFromSchedule fail!");
300          goto ERROR;
301      }
302      g_verifierSchedule->templateId = templateId;
303      g_verifierSchedule->state = VERIFIER_STATE_WAIT_SYNC;
304  
305      PinCredentialInfos pinCredentialInfo;
306      result = DoQueryPinInfo(templateId, &pinCredentialInfo);
307      if (result != RESULT_SUCCESS) {
308          LOG_ERROR("DoQueryPinInfo fail!");
309          goto ERROR;
310      }
311      if (pinCredentialInfo.freezeTime == 0) {
312          LOG_INFO("DoVerifierAuth success");
313          verifierMsg->authResult = RESULT_SUCCESS;
314          verifierMsg->msgOutSize = 0;
315          return RESULT_SUCCESS;
316      }
317  
318      LOG_ERROR("DoVerifierAuth locked");
319      verifierMsg->authResult = RESULT_PIN_FREEZE;
320      result = GetResultTlv(verifierMsg);
321      if (result != RESULT_SUCCESS) {
322          LOG_ERROR("GetResultTlv fail!");
323          goto ERROR;
324      }
325      return RESULT_SUCCESS;
326  
327  ERROR:
328      DestroyVerifierSchedule();
329      return result;
330  }
331  
DoCancelVerifierAuth()332  int32_t DoCancelVerifierAuth()
333  {
334      LOG_INFO("DoCancelVerifierAuth start");
335      DestroyVerifierSchedule();
336      return RESULT_SUCCESS;
337  }
338  
CheckCurrentSchedule(uint64_t scheduleId)339  static bool CheckCurrentSchedule(uint64_t scheduleId)
340  {
341      if (g_verifierSchedule == NULL) {
342          LOG_ERROR("schedule not exist");
343          return false;
344      }
345      if (g_verifierSchedule->scheduleId != scheduleId) {
346          LOG_ERROR("schedule:%{public}x not match current:%{public}x",
347              (uint16_t)scheduleId, (uint16_t)(g_verifierSchedule->scheduleId));
348          return false;
349      }
350      return true;
351  }
352  
DoHandleCollectorSync(VerifierMsg * verifierMsg)353  static int32_t DoHandleCollectorSync(VerifierMsg *verifierMsg)
354  {
355      verifierMsg->isAuthEnd = false;
356      Attribute *dataIn = NULL;
357      int32_t result = VerifyAndGetDataAttribute(g_verifierSchedule->scheduleId,
358          &dataIn, g_verifierSchedule->peerPubKey, verifierMsg->msgIn, verifierMsg->msgInSize);
359      if (result != RESULT_SUCCESS) {
360          LOG_ERROR("VerifyAndGetDataAttribute fail");
361          return result;
362      }
363  
364      result = CheckAttributeDataBase(
365          dataIn, g_verifierSchedule->scheduleId, REMOTE_PIN_COLLECTOR_SYNC, &(g_verifierSchedule->timeStamp));
366      FreeAttribute(&dataIn);
367      if (result != RESULT_SUCCESS) {
368          LOG_ERROR("CheckAttributeDataBase fail");
369          return result;
370      }
371  
372      Attribute *dataOut = GetVerifyAckData();
373      if (dataOut == NULL) {
374          LOG_ERROR("GetVerifyAckData fail!");
375          return RESULT_GENERAL_ERROR;
376      }
377      result = FormatTlvMsg(dataOut, g_keyPair, verifierMsg->msgOut, &(verifierMsg->msgOutSize));
378      FreeAttribute(&dataOut);
379      if (result != RESULT_SUCCESS) {
380          LOG_ERROR("FormatTlvMsg fail!");
381          return result;
382      }
383      g_verifierSchedule->state = VERIFIER_STATE_WAIT_ACK;
384      return result;
385  }
386  
DestroyAesGcmParam(AesGcmParam * aesGcmParam)387  static void DestroyAesGcmParam(AesGcmParam *aesGcmParam)
388  {
389      DestroyBuffer(aesGcmParam->key);
390      aesGcmParam->key = NULL;
391      DestroyBuffer(aesGcmParam->iv);
392      aesGcmParam->iv = NULL;
393      DestroyBuffer(aesGcmParam->aad);
394      aesGcmParam->aad = NULL;
395  }
396  
GetAesGcmParam(AesGcmParam * aesGcmParam,const Attribute * attribute)397  static bool GetAesGcmParam(AesGcmParam *aesGcmParam, const Attribute *attribute)
398  {
399      (void)memset_s(aesGcmParam, sizeof(AesGcmParam), 0, sizeof(AesGcmParam));
400      aesGcmParam->aad = CreateBufferByData((const uint8_t *)CONST_KEK_AAD, CONST_KEK_AAD_SIZE);
401      if (aesGcmParam->aad == NULL) {
402          LOG_ERROR("create aad buffer fail");
403          goto ERROR;
404      }
405      aesGcmParam->iv = GetBufferFromAttribute(attribute, PIN_ATTR_KEK_IV, AES_GCM_256_IV_SIZE);
406      if (aesGcmParam->iv == NULL) {
407          LOG_ERROR("create iv buffer fail");
408          goto ERROR;
409      }
410      if (GetDistributeKey(g_verifierSchedule->peerUdid, g_verifierSchedule->salt, &(aesGcmParam->key)) !=
411          RESULT_SUCCESS) {
412          LOG_ERROR("GetDistributeKey fail");
413          goto ERROR;
414      }
415      return true;
416  
417  ERROR:
418      DestroyAesGcmParam(aesGcmParam);
419      return false;
420  }
421  
GetPinData(const Attribute * attribute)422  static Buffer *GetPinData(const Attribute *attribute)
423  {
424      AesGcmParam aesGcmParam = {};
425      if (!GetAesGcmParam(&aesGcmParam, attribute)) {
426          LOG_ERROR("GetAesGcmParam fail");
427          return NULL;
428      }
429      int32_t result = RESULT_GENERAL_ERROR;
430      Buffer *plainText = NULL;
431      Buffer *tag = NULL;
432      Buffer *cipherText = GetBufferFromAttribute(attribute, PIN_ATTR_KEK_SECRET, CONST_PIN_DATA_LEN);
433      if (cipherText == NULL) {
434          LOG_ERROR("GetBufferFromAttribute secret fail");
435          goto EXIT;
436      }
437      tag = GetBufferFromAttribute(attribute, PIN_ATTR_KEK_TAG, AES_GCM_256_TAG_SIZE);
438      if (tag == NULL) {
439          LOG_ERROR("GetBufferFromAttribute tag fail");
440          goto EXIT;
441      }
442      result = AesGcm256Decrypt(cipherText, &aesGcmParam, tag, &plainText);
443      if (result != RESULT_SUCCESS) {
444          LOG_ERROR("AesGcm256Decrypt fail");
445          goto EXIT;
446      }
447  
448  EXIT:
449      DestroyAesGcmParam(&aesGcmParam);
450      DestroyBuffer(cipherText);
451      DestroyBuffer(tag);
452      return plainText;
453  }
454  
AuthPin(VerifierMsg * verifierMsg,Buffer * pinDataBuf)455  static int32_t AuthPin(VerifierMsg *verifierMsg, Buffer *pinDataBuf)
456  {
457      LOG_INFO("start");
458      verifierMsg->isAuthEnd = true;
459      verifierMsg->authResult = RESULT_GENERAL_ERROR;
460  
461      PinCredentialInfos pinCredentialInfo = {};
462      ResultCode ret = DoQueryPinInfo(g_verifierSchedule->templateId, &pinCredentialInfo);
463      if (ret != RESULT_SUCCESS) {
464          LOG_ERROR("DoQueryPinInfo fail.");
465          verifierMsg->msgOutSize = 0;
466          return RESULT_SUCCESS;
467      }
468  
469      if (pinCredentialInfo.freezeTime == 0) {
470          ResultCode compareRet = RESULT_COMPARE_FAIL;
471          ResultCode result = AuthPinById(pinDataBuf, g_verifierSchedule->templateId, NULL, &compareRet);
472          if (result != RESULT_SUCCESS) {
473              LOG_ERROR("AuthPinById fail!");
474          }
475          verifierMsg->authResult = result != RESULT_SUCCESS ? result : compareRet;
476      } else {
477          LOG_ERROR("Pin is freezing.");
478          verifierMsg->authResult = RESULT_PIN_FREEZE;
479      }
480  
481      ret = GetResultTlv(verifierMsg);
482      if (ret != RESULT_SUCCESS) {
483          LOG_ERROR("GetResultTlv fail!");
484          verifierMsg->msgOutSize = 0;
485      }
486      return RESULT_SUCCESS;
487  }
488  
DoHandleCollectorAck(VerifierMsg * verifierMsg)489  static int32_t DoHandleCollectorAck(VerifierMsg *verifierMsg)
490  {
491      Attribute *dataIn = NULL;
492      int32_t result = VerifyAndGetDataAttribute(g_verifierSchedule->scheduleId,
493          &dataIn, g_verifierSchedule->peerPubKey, verifierMsg->msgIn, verifierMsg->msgInSize);
494      if (result != RESULT_SUCCESS) {
495          LOG_ERROR("VerifyAndGetDataAttribute fail");
496          return result;
497      }
498  
499      result = CheckAttributeDataBase(
500          dataIn, g_verifierSchedule->scheduleId, REMOTE_PIN_COLLECTOR_ACK, &(g_verifierSchedule->timeStamp));
501      if (result != RESULT_SUCCESS) {
502          LOG_ERROR("CheckAttributeDataBase fail");
503          FreeAttribute(&dataIn);
504          return result;
505      }
506  
507      Buffer *pinData = GetPinData(dataIn);
508      FreeAttribute(&dataIn);
509      if (pinData == NULL) {
510          LOG_ERROR("GetPinData fail");
511          return RESULT_GENERAL_ERROR;
512      }
513  
514      result = AuthPin(verifierMsg, pinData);
515      DestroyBuffer(pinData);
516      if (result != RESULT_SUCCESS) {
517          LOG_ERROR("AuthPin fail");
518      }
519      DestroyVerifierSchedule();
520      return result;
521  }
522  
DoSendMessageToVerifier(uint64_t scheduleId,VerifierMsg * verifierMsg)523  int32_t DoSendMessageToVerifier(uint64_t scheduleId, VerifierMsg *verifierMsg)
524  {
525      LOG_INFO("DoSendMessageToVerifier start schedule:%{public}x", (uint16_t)scheduleId);
526      if (!CheckCurrentSchedule(scheduleId) || !IsVeriferMsgValid(verifierMsg)) {
527          LOG_ERROR("check param fail!");
528          return RESULT_BAD_PARAM;
529      }
530      LOG_INFO("DoSendMessageToVerifier current state:%{public}d", g_verifierSchedule->state);
531      if (g_verifierSchedule->state == VERIFIER_STATE_WAIT_SYNC) {
532          return DoHandleCollectorSync(verifierMsg);
533      }
534      if (g_verifierSchedule->state == VERIFIER_STATE_WAIT_ACK) {
535          return DoHandleCollectorAck(verifierMsg);
536      }
537      return RESULT_GENERAL_ERROR;
538  }
539