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