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