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 "collector_func.h"
17 
18 #include "securec.h"
19 
20 #include "adaptor_log.h"
21 #include "adaptor_memory.h"
22 #include "attribute.h"
23 #include "buffer.h"
24 
25 typedef enum CollectorState {
26     COLLECTOR_STATE_INIT = 0,
27     COLLECTOR_STATE_WAIT_ACK = 1,
28     COLLECTOR_STATE_WAIT_PIN = 2,
29     COLLECTOR_STATE_FINISH = 3,
30 } CollectorState;
31 
32 typedef struct CollectorSchedule {
33     uint64_t scheduleId;
34     uint64_t timeStamp;
35     Buffer *selfUdid;
36     Buffer *peerUdid;
37     Buffer *peerPubKey;
38     Buffer *challenge;
39     Buffer *salt;
40     CollectorState state;
41 } CollectorSchedule;
42 
43 static KeyPair *g_keyPair = NULL;
44 static Buffer *g_fwkPubKey = NULL;
45 static CollectorSchedule *g_collectorSchedule = NULL;
46 
47 /* This is for example only, Should be implemented in trusted environment. */
GenerateCollectorKeyPair(void)48 int32_t GenerateCollectorKeyPair(void)
49 {
50     DestroyKeyPair(g_keyPair);
51     g_keyPair = GenerateEd25519KeyPair();
52     if (g_keyPair == NULL) {
53         LOG_ERROR("GenerateCollectorKeyPair fail");
54         return RESULT_GENERAL_ERROR;
55     }
56     LOG_INFO("GenerateCollectorKeyPair success");
57     return RESULT_SUCCESS;
58 }
59 
DestroyCollectorKeyPair(void)60 void DestroyCollectorKeyPair(void)
61 {
62     LOG_INFO("DestroyCollectorKeyPair");
63     DestroyKeyPair(g_keyPair);
64     g_keyPair = NULL;
65 }
66 
67 /* This is for example only, Should be implemented in trusted environment. */
DoGetCollectorExecutorInfo(PinExecutorInfo * pinExecutorInfo)68 int32_t DoGetCollectorExecutorInfo(PinExecutorInfo *pinExecutorInfo)
69 {
70     if (pinExecutorInfo == NULL) {
71         LOG_ERROR("check param fail!");
72         return RESULT_BAD_PARAM;
73     }
74     if (!IsEd25519KeyPairValid(g_keyPair)) {
75         LOG_ERROR("key pair not init!");
76         return RESULT_NEED_INIT;
77     }
78     uint32_t pubKeyLen = ED25519_FIX_PUBKEY_BUFFER_SIZE;
79     if (GetBufferData(g_keyPair->pubKey, pinExecutorInfo->pubKey, &pubKeyLen) != RESULT_SUCCESS) {
80         LOG_ERROR("GetBufferData fail!");
81         return RESULT_UNKNOWN;
82     }
83     pinExecutorInfo->esl = PIN_EXECUTOR_SECURITY_LEVEL;
84     pinExecutorInfo->maxTemplateAcl = PIN_CAPABILITY_LEVEL;
85     return RESULT_SUCCESS;
86 }
87 
DoSetCollectorFwkParam(const uint8_t * fwkPubKey,uint32_t fwkPubKeySize)88 int32_t DoSetCollectorFwkParam(const uint8_t *fwkPubKey, uint32_t fwkPubKeySize)
89 {
90     if ((fwkPubKey == NULL) || (fwkPubKeySize != ED25519_FIX_PUBKEY_BUFFER_SIZE)) {
91         LOG_ERROR("DoSetCollectorFwkParam check param fail!");
92         return RESULT_BAD_PARAM;
93     }
94     DestroyBuffer(g_fwkPubKey);
95     g_fwkPubKey = CreateBufferByData(fwkPubKey, fwkPubKeySize);
96     if (g_fwkPubKey == NULL) {
97         LOG_ERROR("DoSetCollectorFwkParam create fwkPubKey fail!");
98         return RESULT_NO_MEMORY;
99     }
100     return RESULT_SUCCESS;
101 }
102 
DestroyCollectorSchedule(void)103 static void DestroyCollectorSchedule(void)
104 {
105     if (g_collectorSchedule == NULL) {
106         return;
107     }
108     DestroyBuffer(g_collectorSchedule->selfUdid);
109     DestroyBuffer(g_collectorSchedule->peerUdid);
110     DestroyBuffer(g_collectorSchedule->peerPubKey);
111     DestroyBuffer(g_collectorSchedule->challenge);
112     DestroyBuffer(g_collectorSchedule->salt);
113     Free(g_collectorSchedule);
114     g_collectorSchedule= NULL;
115 }
116 
GetCollectInfoFromSchedule(uint64_t scheduleId,const uint8_t * extraInfo,uint32_t extraInfoSize)117 static int32_t GetCollectInfoFromSchedule(uint64_t scheduleId, const uint8_t *extraInfo, uint32_t extraInfoSize)
118 {
119     Attribute *attribute = NULL;
120     int32_t result = VerifyAndGetDataAttribute(scheduleId, &attribute, g_fwkPubKey, extraInfo, extraInfoSize);
121     IF_TRUE_LOGE_AND_RETURN_VAL(result != RESULT_SUCCESS, result);
122 
123     result = RESULT_GENERAL_ERROR;
124     g_collectorSchedule->selfUdid = GetBufferFromAttribute(attribute, ATTR_LOCAL_UDID, CONST_FWK_UDID_SIZE);
125     if (g_collectorSchedule->selfUdid == NULL) {
126         LOG_ERROR("get self udid fail!");
127         goto EXIT;
128     }
129     g_collectorSchedule->peerUdid = GetBufferFromAttribute(attribute, ATTR_PEER_UDID, CONST_FWK_UDID_SIZE);
130     if (g_collectorSchedule->peerUdid == NULL) {
131         LOG_ERROR("get peer udid fail!");
132         goto EXIT;
133     }
134     g_collectorSchedule->peerPubKey = GetBufferFromAttribute(
135         attribute, ATTR_PUBLIC_KEY, ED25519_FIX_PUBKEY_BUFFER_SIZE);
136     if (g_collectorSchedule->peerPubKey == NULL) {
137         LOG_ERROR("get peer public key fail!");
138         goto EXIT;
139     }
140     g_collectorSchedule->challenge = GetBufferFromAttribute(attribute, ATTR_CHALLENGE, CONST_CHALLENGE_LEN);
141     if (g_collectorSchedule->challenge == NULL) {
142         LOG_ERROR("get challenge fail!");
143         goto EXIT;
144     }
145 
146     result = RESULT_SUCCESS;
147 
148 EXIT:
149     FreeAttribute(&attribute);
150     return result;
151 }
152 
InitCollectorSchedule(uint64_t scheduleId)153 static bool InitCollectorSchedule(uint64_t scheduleId)
154 {
155     g_collectorSchedule = Malloc(sizeof(CollectorSchedule));
156     if (g_collectorSchedule == NULL) {
157         LOG_ERROR("malloc CollectorSchedule fail!");
158         return false;
159     }
160     (void)memset_s(g_collectorSchedule, sizeof(CollectorSchedule), 0, sizeof(CollectorSchedule));
161     g_collectorSchedule->scheduleId = scheduleId;
162     return true;
163 }
164 
DoCollect(uint64_t scheduleId,const uint8_t * extraInfo,uint32_t extraInfoSize,uint8_t * msg,uint32_t * msgSize)165 int32_t DoCollect(
166     uint64_t scheduleId, const uint8_t *extraInfo, uint32_t extraInfoSize, uint8_t *msg, uint32_t *msgSize)
167 {
168     LOG_INFO("DoCollect start %{public}x", (uint16_t)scheduleId);
169     if ((extraInfo == NULL) || (extraInfoSize == 0) || (extraInfoSize > MAX_EXECUTOR_MSG_LEN) ||
170         (msg == NULL) || (msgSize == NULL) || ((*msgSize) == 0)) {
171         LOG_ERROR("check param fail!");
172         return RESULT_BAD_PARAM;
173     }
174     DestroyCollectorSchedule();
175     if (!InitCollectorSchedule(scheduleId)) {
176         LOG_ERROR("InitCollectorSchedule fail!");
177         return RESULT_GENERAL_ERROR;
178     }
179 
180     int32_t result = GetCollectInfoFromSchedule(scheduleId, extraInfo, extraInfoSize);
181     if (result != RESULT_SUCCESS) {
182         LOG_ERROR("GetCollectInfoFromSchedule fail!");
183         goto ERROR;
184     }
185 
186     Attribute *attribute = GetAttributeDataBase(g_collectorSchedule->scheduleId, REMOTE_PIN_COLLECTOR_SYNC);
187     if (attribute == NULL) {
188         LOG_ERROR("GetAttributeDataBase fail!");
189         result = RESULT_GENERAL_ERROR;
190         goto ERROR;
191     }
192 
193     result = FormatTlvMsg(attribute, g_keyPair, msg, msgSize);
194     FreeAttribute(&attribute);
195     if (result != RESULT_SUCCESS) {
196         LOG_ERROR("FormatTlvMsg fail!");
197         goto ERROR;
198     }
199     g_collectorSchedule->state = COLLECTOR_STATE_WAIT_ACK;
200     return RESULT_SUCCESS;
201 
202 ERROR:
203     DestroyCollectorSchedule();
204     return result;
205 }
206 
DoCancelCollect()207 int32_t DoCancelCollect()
208 {
209     LOG_INFO("DoCancelCollect start");
210     DestroyCollectorSchedule();
211     return RESULT_SUCCESS;
212 }
213 
CheckCurrentSchedule(uint64_t scheduleId,CollectorState state)214 static bool CheckCurrentSchedule(uint64_t scheduleId, CollectorState state)
215 {
216     if (g_collectorSchedule == NULL) {
217         LOG_ERROR("schedule not exist");
218         return false;
219     }
220     if (g_collectorSchedule->scheduleId != scheduleId) {
221         LOG_ERROR("schedule:%{public}x not match current:%{public}x",
222             (uint16_t)scheduleId, (uint16_t)(g_collectorSchedule->scheduleId));
223         return false;
224     }
225     if (g_collectorSchedule->state != state) {
226         LOG_ERROR("state:%{public}d not match current:%{public}d", state, g_collectorSchedule->state);
227         return false;
228     }
229     return true;
230 }
231 
GetAlgoParam(const Attribute * data,AlgoParamOut * algoParam)232 static int32_t GetAlgoParam(const Attribute *data, AlgoParamOut *algoParam)
233 {
234     int32_t result = GetAttributeUint64(data, ATTR_PIN_SUB_TYPE, &(algoParam->subType));
235     if (result != RESULT_SUCCESS) {
236         LOG_ERROR("get sub type fail");
237         return result;
238     }
239     result = GetAttributeUint32(data, PIN_ATTR_ALGO_VERSION, &(algoParam->algoVersion));
240     if (result != RESULT_SUCCESS) {
241         LOG_ERROR("get algo version fail");
242         return result;
243     }
244     Uint8Array uint8Array = {
245         .data = algoParam->algoParameter,
246         .len = sizeof(algoParam->algoParameter),
247     };
248     result = GetAttributeUint8Array(data, PIN_ATTR_ALGO_PARAM, &uint8Array);
249     if (result != RESULT_SUCCESS) {
250         LOG_ERROR("get algo param fail");
251         return result;
252     }
253     if (uint8Array.len != sizeof(algoParam->algoParameter)) {
254         LOG_ERROR("get algo param fail");
255         return RESULT_GENERAL_ERROR;
256     }
257     if (memcpy_s(algoParam->challenge, sizeof(algoParam->challenge),
258         g_collectorSchedule->challenge->buf, g_collectorSchedule->challenge->contentSize) != EOK) {
259         LOG_ERROR("copy challenge fail");
260         return RESULT_GENERAL_ERROR;
261     }
262     return RESULT_SUCCESS;
263 }
264 
DoSendMessageToCollector(uint64_t scheduleId,const uint8_t * msg,uint32_t msgSize,AlgoParamOut * algoParam)265 int32_t DoSendMessageToCollector(uint64_t scheduleId, const uint8_t *msg, uint32_t msgSize, AlgoParamOut *algoParam)
266 {
267     LOG_INFO("SendMessageToCollector start schedule:%{public}x", (uint16_t)scheduleId);
268     if (!CheckCurrentSchedule(scheduleId, COLLECTOR_STATE_WAIT_ACK) ||
269         (msg == NULL) || (msgSize == 0) || (algoParam == NULL)) {
270         LOG_ERROR("check param fail!");
271         return RESULT_BAD_PARAM;
272     }
273     Attribute *data = NULL;
274     int32_t result = VerifyAndGetDataAttribute(scheduleId, &data, g_collectorSchedule->peerPubKey, msg, msgSize);
275     if (result != RESULT_SUCCESS) {
276         LOG_ERROR("VerifyAndGetDataAttribute fail");
277         return result;
278     }
279 
280     result = CheckAttributeDataBase(
281         data, g_collectorSchedule->scheduleId, REMOTE_PIN_VERIFIER_ACK, &(g_collectorSchedule->timeStamp));
282     if (result != RESULT_SUCCESS) {
283         LOG_ERROR("CheckAttributeDataBase fail");
284         goto EXIT;
285     }
286 
287     g_collectorSchedule->salt = GetBufferFromAttribute(data, PIN_ATTR_KEK_SALT, CONST_KEK_SALT_SIZE);
288     if (g_collectorSchedule->salt == NULL) {
289         LOG_ERROR("get kek salt fail");
290         result = RESULT_GENERAL_ERROR;
291         goto EXIT;
292     }
293 
294     result = GetAlgoParam(data, algoParam);
295     if (result != RESULT_SUCCESS) {
296         LOG_ERROR("GetAlgoParam fail");
297         goto EXIT;
298     }
299 
300     g_collectorSchedule->state = COLLECTOR_STATE_WAIT_PIN;
301 
302 EXIT:
303     FreeAttribute(&data);
304     return result;
305 }
306 
DestroyAesGcmParam(AesGcmParam * aesGcmParam)307 static void DestroyAesGcmParam(AesGcmParam *aesGcmParam)
308 {
309     DestroyBuffer(aesGcmParam->key);
310     aesGcmParam->key = NULL;
311     DestroyBuffer(aesGcmParam->iv);
312     aesGcmParam->iv = NULL;
313     DestroyBuffer(aesGcmParam->aad);
314     aesGcmParam->aad = NULL;
315 }
316 
GetAesGcmParam(AesGcmParam * aesGcmParam)317 static bool GetAesGcmParam(AesGcmParam *aesGcmParam)
318 {
319     (void)memset_s(aesGcmParam, sizeof(AesGcmParam), 0, sizeof(AesGcmParam));
320     aesGcmParam->aad = CreateBufferByData((const uint8_t *)CONST_KEK_AAD, CONST_KEK_AAD_SIZE);
321     if (aesGcmParam->aad == NULL) {
322         LOG_ERROR("create aad buffer fail");
323         goto ERROR;
324     }
325     aesGcmParam->iv = CreateBufferBySize(AES_GCM_256_IV_SIZE);
326     if (aesGcmParam->iv == NULL) {
327         LOG_ERROR("create iv buffer fail");
328         goto ERROR;
329     }
330     if (SecureRandom(aesGcmParam->iv->buf, aesGcmParam->iv->maxSize) != RESULT_SUCCESS) {
331         LOG_ERROR("SecureRandom iv fail");
332         goto ERROR;
333     }
334     aesGcmParam->iv->contentSize = aesGcmParam->iv->maxSize;
335     if (GetDistributeKey(g_collectorSchedule->peerUdid, g_collectorSchedule->salt, &(aesGcmParam->key)) !=
336         RESULT_SUCCESS) {
337         LOG_ERROR("GetDistributeKey fail");
338         goto ERROR;
339     }
340     return true;
341 
342 ERROR:
343     DestroyAesGcmParam(aesGcmParam);
344     return false;
345 }
346 
SetEncryptParam(Attribute * attribute,uint8_t * pinData,uint32_t pinDataSize)347 static int32_t SetEncryptParam(Attribute *attribute, uint8_t *pinData, uint32_t pinDataSize)
348 {
349     AesGcmParam aesGcmParam = {};
350     if (!GetAesGcmParam(&aesGcmParam)) {
351         LOG_ERROR("GetAesGcmParam fail");
352         return RESULT_GENERAL_ERROR;
353     }
354     Buffer plainText = GetTmpBuffer(pinData, pinDataSize, pinDataSize);
355     Buffer *cipherText = NULL;
356     Buffer *tag = NULL;
357     int32_t result = AesGcm256Encrypt(&plainText, &aesGcmParam, &cipherText, &tag);
358     if (result != RESULT_SUCCESS) {
359         LOG_ERROR("AesGcm256Encrypt fail");
360         goto EXIT;
361     }
362     result = SetBufferToAttribute(attribute, PIN_ATTR_KEK_IV, aesGcmParam.iv);
363     if (result != RESULT_SUCCESS) {
364         LOG_ERROR("set attribute iv fail");
365         goto EXIT;
366     }
367     result = SetBufferToAttribute(attribute, PIN_ATTR_KEK_SECRET, cipherText);
368     if (result != RESULT_SUCCESS) {
369         LOG_ERROR("set attribute secret fail");
370         goto EXIT;
371     }
372     result = SetBufferToAttribute(attribute, PIN_ATTR_KEK_TAG, tag);
373     if (result != RESULT_SUCCESS) {
374         LOG_ERROR("set attribute tag fail");
375         goto EXIT;
376     }
377 
378 EXIT:
379     DestroyAesGcmParam(&aesGcmParam);
380     DestroyBuffer(cipherText);
381     DestroyBuffer(tag);
382     return result;
383 }
384 
DoSetDataToCollector(uint64_t scheduleId,uint8_t * pinData,uint32_t pinDataSize,uint8_t * msg,uint32_t * msgSize)385 int32_t DoSetDataToCollector(
386     uint64_t scheduleId, uint8_t *pinData, uint32_t pinDataSize, uint8_t *msg, uint32_t *msgSize)
387 {
388     LOG_INFO("DoSetDataToCollector start schedule:%{public}x", (uint16_t)scheduleId);
389     int32_t result = RESULT_BAD_PARAM;
390     Attribute *attribute = NULL;
391     if (!CheckCurrentSchedule(scheduleId, COLLECTOR_STATE_WAIT_PIN) ||
392         (pinData == NULL) || (pinDataSize != CONST_PIN_DATA_LEN) || (msg == NULL) || ((*msgSize) == 0)) {
393         LOG_ERROR("check param fail!");
394         goto EXIT;
395     }
396 
397     attribute = GetAttributeDataBase(scheduleId, REMOTE_PIN_COLLECTOR_ACK);
398     if (attribute == NULL) {
399         LOG_ERROR("GetAttributeDataBase fail");
400         result = RESULT_GENERAL_ERROR;
401         goto EXIT;
402     }
403     result = SetEncryptParam(attribute, pinData, pinDataSize);
404     if (result != RESULT_SUCCESS) {
405         LOG_ERROR("SetEncryptParam fail");
406         goto EXIT;
407     }
408     result = FormatTlvMsg(attribute, g_keyPair, msg, msgSize);
409     if (result != RESULT_SUCCESS) {
410         LOG_ERROR("FormatTlvMsg fail");
411         goto EXIT;
412     }
413 
414     g_collectorSchedule->state = COLLECTOR_STATE_FINISH;
415 
416 EXIT:
417     if ((pinData != NULL) && (pinDataSize != 0)) {
418         (void)memset_s(pinData, pinDataSize, 0, pinDataSize);
419     }
420     FreeAttribute(&attribute);
421     return result;
422 }
423