• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-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 #ifndef _CUT_AUTHENTICATE_
17 
18 #ifdef _STORAGE_LITE_
19 
20 #include "hks_storage.h"
21 
22 #include "hks_file_operator.h"
23 #include "hks_log.h"
24 #include "hks_mem.h"
25 #include "hks_param.h"
26 #include "hks_storage_adapter.h"
27 #include "hks_template.h"
28 
29 #include "huks_access.h"
30 
31 #include <securec.h>
32 
33 #define HKS_FILE_OFFSET_BASE 0
34 #define MAX_STORAGE_SIZE 5120
35 #define MAX_BUF_SIZE 65536
36 #define BUF_SIZE_ADDEND_PER_TIME 1024
37 #define HKS_STORAGE_VERSION 1
38 #define HKS_STORAGE_RESERVED_SEALING_ALG 0xFEDCBA98
39 
40 struct HksBlob g_storageImageBuffer = { 0, NULL };
41 
HksGetStoreFileOffset(void)42 static uint32_t HksGetStoreFileOffset(void)
43 {
44     return HKS_FILE_OFFSET_BASE;
45 }
46 
ConstructCalcMacParamSet(struct HksParamSet ** paramSet)47 static int32_t ConstructCalcMacParamSet(struct HksParamSet **paramSet)
48 {
49     struct HksParamSet *outputParamSet = NULL;
50     int32_t ret = HksInitParamSet(&outputParamSet);
51     HKS_IF_NOT_SUCC_RETURN(ret, ret)
52 
53     do {
54         struct HksParam digestParam = {
55             .tag = HKS_TAG_DIGEST,
56             .uint32Param = HKS_DIGEST_SHA512
57         };
58 
59         ret = HksAddParams(outputParamSet, &digestParam, 1); /* 1: param count */
60         HKS_IF_NOT_SUCC_BREAK(ret)
61 
62         ret = HksBuildParamSet(&outputParamSet);
63     } while (0);
64 
65     if (ret != HKS_SUCCESS) {
66         HksFreeParamSet(&outputParamSet);
67         return ret;
68     }
69 
70     *paramSet = outputParamSet;
71     return ret;
72 }
73 
CalcHeaderMac(const struct HksBlob * salt,const uint8_t * buf,const uint32_t srcSize,struct HksBlob * mac)74 static int32_t CalcHeaderMac(const struct HksBlob *salt, const uint8_t *buf,
75     const uint32_t srcSize, struct HksBlob *mac)
76 {
77     if (srcSize == 0) {
78         return HKS_ERROR_INVALID_ARGUMENT;
79     }
80 
81     struct HksBlob srcData = { srcSize, NULL };
82     srcData.data = (uint8_t *)HksMalloc(srcData.size);
83     HKS_IF_NULL_RETURN(srcData.data, HKS_ERROR_MALLOC_FAIL)
84 
85     int32_t ret;
86     struct HksParamSet *paramSet = NULL;
87     do {
88         if (memcpy_s(srcData.data, srcData.size, buf, srcSize) != EOK) {
89             ret = HKS_ERROR_INSUFFICIENT_MEMORY;
90             break;
91         }
92 
93         ret = ConstructCalcMacParamSet(&paramSet);
94         HKS_IF_NOT_SUCC_BREAK(ret)
95 
96         ret = HuksAccessCalcHeaderMac(paramSet, salt, &srcData, mac);
97         HKS_IF_NOT_SUCC_LOGE(ret, "access calc header mac failed, ret = %" LOG_PUBLIC "d.", ret)
98     } while (0);
99 
100     HKS_FREE_BLOB(srcData);
101     HksFreeParamSet(&paramSet);
102     return ret;
103 }
104 
InitImageBuffer(void)105 static int32_t InitImageBuffer(void)
106 {
107     /* caller func ensure g_storageImageBuffer.size is larger than sizeof(*keyInfoHead) */
108     struct HksStoreHeaderInfo *keyInfoHead = (struct HksStoreHeaderInfo *)g_storageImageBuffer.data;
109     keyInfoHead->version = HKS_STORAGE_VERSION;
110     keyInfoHead->keyCount = 0;
111     keyInfoHead->totalLen = sizeof(*keyInfoHead);
112     keyInfoHead->sealingAlg = HKS_STORAGE_RESERVED_SEALING_ALG;
113 
114     struct HksBlob salt = { HKS_DERIVE_DEFAULT_SALT_LEN, keyInfoHead->salt };
115     int32_t ret = HuksAccessGenerateRandom(NULL, &salt);
116     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "generate random failed, ret = %" LOG_PUBLIC "d", ret)
117 
118     struct HksBlob mac = { HKS_HMAC_DIGEST_SHA512_LEN, keyInfoHead->hmac };
119     uint16_t size = sizeof(*keyInfoHead) - HKS_HMAC_DIGEST_SHA512_LEN;
120 
121     return CalcHeaderMac(&salt, g_storageImageBuffer.data, size, &mac);
122 }
123 
CleanImageBuffer(void)124 static void CleanImageBuffer(void)
125 {
126     if (g_storageImageBuffer.data == NULL) {
127         return;
128     }
129     (void)memset_s(g_storageImageBuffer.data, g_storageImageBuffer.size, 0, g_storageImageBuffer.size);
130 }
131 
ApplyImageBuffer(uint32_t size)132 static int32_t ApplyImageBuffer(uint32_t size)
133 {
134     if (g_storageImageBuffer.data != NULL) {
135         return HKS_SUCCESS;
136     }
137 
138     if ((size == 0) || (size > MAX_BUF_SIZE)) {
139         HKS_LOG_E("invalid size = %" LOG_PUBLIC "u", size);
140         return HKS_ERROR_INVALID_ARGUMENT;
141     }
142 
143     g_storageImageBuffer.data = (uint8_t *)HksMalloc(size);
144     HKS_IF_NULL_RETURN(g_storageImageBuffer.data, HKS_ERROR_MALLOC_FAIL)
145 
146     g_storageImageBuffer.size = size;
147 
148     return HKS_SUCCESS;
149 }
150 
FreeImageBuffer(void)151 static void FreeImageBuffer(void)
152 {
153     CleanImageBuffer();
154     HKS_FREE_BLOB(g_storageImageBuffer);
155 }
156 
FreshImageBuffer(const char * fileName)157 static int32_t FreshImageBuffer(const char *fileName)
158 {
159     /* caller func ensure g_storageImageBuffer.size is larger than sizeof(*keyInfoHead) */
160     struct HksStoreHeaderInfo *keyInfoHead = (struct HksStoreHeaderInfo *)g_storageImageBuffer.data;
161     uint32_t totalLen = keyInfoHead->totalLen;
162 
163     /* check totalLen */
164     if ((totalLen < sizeof(*keyInfoHead)) || (totalLen > MAX_STORAGE_SIZE)) {
165         return HKS_ERROR_INVALID_KEY_FILE;
166     }
167 
168     if (totalLen == sizeof(*keyInfoHead)) {
169         return HKS_SUCCESS;
170     }
171 
172     uint32_t offset = HksGetStoreFileOffset();
173     uint32_t fileLen = HksFileSize(HKS_KEY_STORE_PATH, fileName);
174     if (fileLen < (totalLen + offset)) { /* keyfile len at least totalLen + offset */
175         HKS_LOG_E("total Len: %" LOG_PUBLIC "u, invalid file size: %" LOG_PUBLIC "u", totalLen, fileLen);
176         return HKS_ERROR_INVALID_KEY_FILE;
177     }
178 
179     uint8_t *buf = (uint8_t *)HksMalloc(totalLen);
180     HKS_IF_NULL_RETURN(buf, HKS_ERROR_MALLOC_FAIL)
181 
182     struct HksBlob blob = { .size = totalLen, .data = buf };
183 
184     int32_t ret = HksFileRead(HKS_KEY_STORE_PATH, fileName, offset, &blob, &fileLen);
185     if (ret != HKS_SUCCESS) {
186         HKS_FREE(buf);
187         return HKS_ERROR_READ_FILE_FAIL;
188     }
189 
190     FreeImageBuffer();
191     g_storageImageBuffer.data = buf;
192     g_storageImageBuffer.size = totalLen;
193 
194     return HKS_SUCCESS;
195 }
196 
CheckKeyInfoHeaderValid(void)197 static int32_t CheckKeyInfoHeaderValid(void)
198 {
199     /* caller func ensure g_storageImageBuffer.size is larger than sizeof(*keyInfoHead) */
200     struct HksStoreHeaderInfo *keyInfoHead = (struct HksStoreHeaderInfo *)g_storageImageBuffer.data;
201 
202     uint8_t mac512[HKS_HMAC_DIGEST_SHA512_LEN] = {0};
203     struct HksBlob mac = { HKS_HMAC_DIGEST_SHA512_LEN, mac512 };
204     struct HksBlob salt = { HKS_DERIVE_DEFAULT_SALT_LEN, keyInfoHead->salt };
205     uint16_t size = sizeof(*keyInfoHead) - HKS_HMAC_DIGEST_SHA512_LEN;
206 
207     int32_t ret = CalcHeaderMac(&salt, g_storageImageBuffer.data, size, &mac);
208     HKS_IF_NOT_SUCC_RETURN(ret, ret)
209 
210     if (HksMemCmp(mac.data, keyInfoHead->hmac, HKS_HMAC_DIGEST_SHA512_LEN) != 0) {
211         HKS_LOG_E("hmac value not match");
212         return HKS_ERROR_INVALID_KEY_FILE;
213     }
214 
215     return HKS_SUCCESS;
216 }
217 
RefreshKeyInfoHeaderHmac(struct HksStoreHeaderInfo * keyInfoHead)218 static int32_t RefreshKeyInfoHeaderHmac(struct HksStoreHeaderInfo *keyInfoHead)
219 {
220     struct HksBlob mac = { HKS_HMAC_DIGEST_SHA512_LEN, keyInfoHead->hmac };
221     struct HksBlob salt = { HKS_DERIVE_DEFAULT_SALT_LEN, keyInfoHead->salt };
222     uint16_t size = sizeof(*keyInfoHead) - HKS_HMAC_DIGEST_SHA512_LEN;
223 
224     uint8_t *buffer = (uint8_t *)HksMalloc(sizeof(*keyInfoHead));
225     HKS_IF_NULL_RETURN(buffer, HKS_ERROR_MALLOC_FAIL)
226 
227     (void)memcpy_s(buffer, sizeof(*keyInfoHead), keyInfoHead, sizeof(*keyInfoHead));
228 
229     int32_t ret = CalcHeaderMac(&salt, buffer, size, &mac);
230     HKS_FREE(buffer);
231     return ret;
232 }
233 
HksGetImageBuffer(void)234 static struct HksBlob HksGetImageBuffer(void)
235 {
236     return g_storageImageBuffer;
237 }
238 
LoadFileToBuffer(const char * fileName)239 static int32_t LoadFileToBuffer(const char *fileName)
240 {
241     /* 1. read key info header */
242     uint32_t offset = HksGetStoreFileOffset();
243     uint32_t len = 0;
244     int32_t ret = HksFileRead(HKS_KEY_STORE_PATH, fileName, offset,
245         &g_storageImageBuffer, &len);
246 
247     do {
248         /* 2. file not exist or read nothing, init image */
249         if (ret != HKS_SUCCESS) {
250             HKS_LOG_I("file not exist, init buffer.");
251             ret = InitImageBuffer();
252             HKS_IF_NOT_SUCC_BREAK(ret) /* init fail, need free global buf */
253             return ret;
254         }
255 
256         /* 3. read header success, check keyinfo header */
257         HKS_LOG_I("file exist, check buffer.");
258         ret = CheckKeyInfoHeaderValid();
259         HKS_IF_NOT_SUCC_BREAK(ret)
260 
261         /* 4. check success, load full buffer */
262         ret = FreshImageBuffer(fileName);
263     } while (0);
264 
265     if (ret != HKS_SUCCESS) {
266         FreeImageBuffer();
267     }
268 
269     return ret;
270 }
271 
HksLoadFileToBuffer(void)272 int32_t HksLoadFileToBuffer(void)
273 {
274     if (g_storageImageBuffer.data != NULL) {
275         return HKS_SUCCESS;
276     }
277 
278     /* 1. malloc keyinfo header size buffer */
279     int32_t ret = ApplyImageBuffer(sizeof(struct HksStoreHeaderInfo));
280     HKS_IF_NOT_SUCC_RETURN(ret, ret)
281 
282     CleanImageBuffer();
283 
284     /* 2. read file to buffer */
285     return LoadFileToBuffer(HKS_KEY_STORE_FILE_NAME);
286 }
287 
CleanStorageKeyInfo(const char * fileName)288 static int32_t CleanStorageKeyInfo(const char *fileName)
289 {
290     int32_t ret = InitImageBuffer();
291     if (ret != HKS_SUCCESS) {
292         FreeImageBuffer();
293         return ret;
294     }
295 
296     /* write to file */
297     uint32_t totalLen = sizeof(struct HksStoreHeaderInfo);
298     uint32_t fileOffset = HksGetStoreFileOffset();
299     ret = HksFileWrite(HKS_KEY_STORE_PATH, fileName, fileOffset, g_storageImageBuffer.data, totalLen);
300     if (ret != HKS_SUCCESS) {
301         HKS_LOG_E("write file failed when hks refresh file buffer");
302         FreeImageBuffer();
303     }
304     return ret;
305 }
306 
HksFileBufferRefresh(void)307 int32_t HksFileBufferRefresh(void)
308 {
309     /* malloc keyinfo header size buffer */
310     int32_t ret = ApplyImageBuffer(sizeof(struct HksStoreHeaderInfo));
311     HKS_IF_NOT_SUCC_RETURN(ret, ret)
312 
313     CleanImageBuffer();
314 
315     return CleanStorageKeyInfo(HKS_KEY_STORE_FILE_NAME);
316 }
317 
318 /*
319  * Storage format:
320  * keyInfoHeader + keyInfo1 + keyInfo2 + ... + keyInfoN
321  *
322  *                +--------------------------------------------------------------+
323  * KeyInfoHeader: | version | keyCount | totalLen | sealingAlg |  salt  |  hmac  |
324  *                | 2bytes  |  2bytes  |  4bytes  |   4bytes   |16bytes |64bytes |
325  *                +--------------------------------------------------------------+
326  *
327  *          +---------------------------------------------------------------------+
328  * KeyInfo: | keyInfoLen | keySize |  nonce  |  flag  | keyAlg | keyMode | digest |
329  *          |   2bytes   | 2bytes  | 16bytes | 1bytes | 1bytes | 1bytes  | 1bytes |
330  *          +---------------------------------------------------------------------+
331  *          | padding |  rsv   | keyLen | purpose |  role  | domain  | aliasSize |
332  *          | 1bytes  | 1bytes | 2bytes | 4bytes  | 4bytes | 21bytes |  1bytes   |
333  *          +--------------------------------------------------------------------+
334  *          | AuthIdSize |  keyAlias   |  keyAuthId  |         key          |
335  *          |   1bytes   | max 64bytes | max 64bytes | max keyMaterial size |
336  *          +---------------------------------------------------------------+
337  */
GetKeyOffsetByKeyAlias(const struct HksBlob * keyAlias,uint32_t * keyOffset)338 static int32_t GetKeyOffsetByKeyAlias(const struct HksBlob *keyAlias, uint32_t *keyOffset)
339 {
340     struct HksBlob storageBuf = HksGetImageBuffer();
341     if (storageBuf.size < sizeof(struct HksStoreHeaderInfo)) {
342         HKS_LOG_E("invalid keyinfo buffer size %" LOG_PUBLIC "u.", storageBuf.size);
343         return HKS_ERROR_INVALID_KEY_FILE;
344     }
345 
346     /* 1. get imageBuffer total Len */
347     struct HksStoreHeaderInfo *keyInfoHead = (struct HksStoreHeaderInfo *)storageBuf.data;
348     uint32_t keyCount = keyInfoHead->keyCount;
349     uint32_t totalLen = keyInfoHead->totalLen;
350     if (keyCount == 0) {
351         return HKS_ERROR_NOT_EXIST;
352     }
353     if (totalLen > storageBuf.size) {
354         HKS_LOG_E("storageBuf size invalid");
355         return HKS_ERROR_INVALID_KEY_FILE;
356     }
357 
358     /* 2. traverse imageBuffer to search for keyAlias */
359     uint32_t offset = sizeof(*keyInfoHead);
360     for (uint32_t i = 0; i < keyCount; ++i) {
361         if ((totalLen < offset) || ((totalLen - offset) < sizeof(struct HksStoreKeyInfo))) {
362             HKS_LOG_E("invalid keyinfo size.");
363             return HKS_ERROR_INVALID_KEY_FILE;
364         }
365 
366         uint8_t *tmpBuf = storageBuf.data + offset;
367         struct HksStoreKeyInfo *keyInfo = (struct HksStoreKeyInfo *)tmpBuf;
368         if (HksIsKeyInfoLenInvalid(keyInfo) || (keyInfo->keyInfoLen > (totalLen - offset))) {
369             HKS_LOG_E("invalid keyinfo len");
370             return HKS_ERROR_INVALID_KEY_FILE;
371         }
372 
373         if (keyInfo->aliasSize == keyAlias->size) {
374             if (HksMemCmp(keyAlias->data, tmpBuf + sizeof(*keyInfo), keyAlias->size) == 0) {
375                 *keyOffset = offset;
376                 return HKS_SUCCESS;
377             }
378         }
379 
380         offset += keyInfo->keyInfoLen;
381     }
382 
383     return HKS_ERROR_NOT_EXIST;
384 }
385 
AdjustImageBuffer(uint32_t totalLenAdded,const struct HksBlob * keyBlob)386 static int32_t AdjustImageBuffer(uint32_t totalLenAdded, const struct HksBlob *keyBlob)
387 {
388     struct HksStoreHeaderInfo *keyInfoHead = (struct HksStoreHeaderInfo *)g_storageImageBuffer.data;
389 
390     /* buffer has been checked will not overflow */
391     uint32_t newBufLen = g_storageImageBuffer.size +
392         ((keyBlob->size > BUF_SIZE_ADDEND_PER_TIME) ? keyBlob->size : BUF_SIZE_ADDEND_PER_TIME);
393     uint8_t *buf = (uint8_t *)HksMalloc(newBufLen);
394     HKS_IF_NULL_RETURN(buf, HKS_ERROR_MALLOC_FAIL)
395 
396     (void)memset_s(buf, newBufLen, 0, newBufLen);
397 
398     /* copy old imagebuf to new malloc buf */
399     if (memcpy_s(buf, newBufLen, g_storageImageBuffer.data, keyInfoHead->totalLen) != EOK) {
400         HKS_FREE(buf);
401         return HKS_ERROR_INSUFFICIENT_MEMORY;
402     }
403 
404     /* append new add key buffer to the end */
405     if (memcpy_s(buf + keyInfoHead->totalLen, newBufLen - keyInfoHead->totalLen,
406         keyBlob->data, keyBlob->size) != EOK) {
407         HKS_FREE(buf);
408         return HKS_ERROR_INSUFFICIENT_MEMORY;
409     }
410 
411     struct HksStoreHeaderInfo *newHead = (struct HksStoreHeaderInfo *)buf;
412     newHead->totalLen = totalLenAdded;
413     newHead->keyCount += 1;
414 
415     FreeImageBuffer();
416     g_storageImageBuffer.data = buf;
417     g_storageImageBuffer.size = newBufLen;
418 
419     return HKS_SUCCESS;
420 }
421 
AppendNewKey(const struct HksBlob * keyBlob)422 static int32_t AppendNewKey(const struct HksBlob *keyBlob)
423 {
424     struct HksBlob storageBuf = HksGetImageBuffer();
425     if (storageBuf.size < sizeof(struct HksStoreHeaderInfo)) {
426         HKS_LOG_E("invalid keyinfo buffer size %" LOG_PUBLIC "u.", storageBuf.size);
427         return HKS_ERROR_INVALID_KEY_FILE;
428     }
429 
430     /* 1. get imagebuf total Len */
431     struct HksStoreHeaderInfo *keyInfoHead = (struct HksStoreHeaderInfo *)storageBuf.data;
432 
433     if (IsAdditionOverflow(keyInfoHead->totalLen, keyBlob->size)) {
434         return HKS_ERROR_INSUFFICIENT_MEMORY;
435     }
436 
437     uint32_t totalLenAdded = keyInfoHead->totalLen + keyBlob->size;
438     if (totalLenAdded > MAX_STORAGE_SIZE) {
439         HKS_LOG_E("after add, buffer too big to store");
440         return HKS_ERROR_STORAGE_FAILURE;
441     }
442 
443     /* imagebuf is enough to append new keyinfo */
444     if (storageBuf.size >= totalLenAdded) {
445         if (memcpy_s(storageBuf.data + keyInfoHead->totalLen, storageBuf.size - keyInfoHead->totalLen,
446             keyBlob->data, keyBlob->size) != EOK) {
447             return HKS_ERROR_INSUFFICIENT_MEMORY;
448         }
449         keyInfoHead->totalLen = totalLenAdded;
450         keyInfoHead->keyCount += 1;
451         return HKS_SUCCESS;
452     }
453 
454     /* need malloc new buffer */
455     return AdjustImageBuffer(totalLenAdded, keyBlob);
456 }
457 
GetLenAfterAddKey(const struct HksBlob * keyBlob,uint32_t totalLen,uint32_t * totalLenAdded)458 static int32_t GetLenAfterAddKey(const struct HksBlob *keyBlob, uint32_t totalLen, uint32_t *totalLenAdded)
459 {
460     if (IsAdditionOverflow(totalLen, keyBlob->size)) {
461         return HKS_ERROR_INSUFFICIENT_MEMORY;
462     }
463 
464     uint32_t newTotalLen = totalLen + keyBlob->size;
465     if (newTotalLen > MAX_STORAGE_SIZE) {
466         HKS_LOG_E("after add, buffer too big to store");
467         return HKS_ERROR_STORAGE_FAILURE;
468     }
469 
470     *totalLenAdded = newTotalLen;
471     return HKS_SUCCESS;
472 }
473 
DeleteKey(uint32_t keyOffset)474 static int32_t DeleteKey(uint32_t keyOffset)
475 {
476     struct HksStoreHeaderInfo *keyInfoHead = (struct HksStoreHeaderInfo *)g_storageImageBuffer.data;
477     struct HksStoreKeyInfo *keyInfo = (struct HksStoreKeyInfo *)(g_storageImageBuffer.data + keyOffset);
478 
479     uint32_t keyInfoLen = keyInfo->keyInfoLen;
480     uint32_t nextKeyOffset = keyOffset + keyInfoLen;
481     if (nextKeyOffset > keyInfoHead->totalLen) {
482         return HKS_ERROR_INVALID_KEY_FILE;
483     }
484 
485     (void)memset_s(keyInfo, keyInfoLen, 0, keyInfoLen);
486 
487     /* If key to delete is not the last key, need to be move image buffer */
488     if (nextKeyOffset < keyInfoHead->totalLen) {
489         if (memmove_s(keyInfo, keyInfoHead->totalLen - keyOffset, g_storageImageBuffer.data + nextKeyOffset,
490             keyInfoHead->totalLen - nextKeyOffset) != EOK) {
491             HKS_LOG_E("memmove image buffer failed");
492             return HKS_ERROR_INSUFFICIENT_MEMORY;
493         }
494         /* clear the last buffer */
495         if (memset_s(g_storageImageBuffer.data + keyInfoHead->totalLen - keyInfoLen, keyInfoLen, 0,
496             keyInfoLen) != EOK) {
497             HKS_LOG_E("memset storageImageBuffer data failed!");
498             return HKS_ERROR_INSUFFICIENT_MEMORY;
499         }
500     }
501     keyInfoHead->keyCount -= 1;
502     keyInfoHead->totalLen -= keyInfoLen;
503 
504     return HKS_SUCCESS;
505 }
506 
StoreKeyBlob(bool needDeleteKey,uint32_t offset,const struct HksBlob * keyBlob)507 static int32_t StoreKeyBlob(bool needDeleteKey, uint32_t offset, const struct HksBlob *keyBlob)
508 {
509     struct HksStoreHeaderInfo *keyInfoHead = (struct HksStoreHeaderInfo *)g_storageImageBuffer.data;
510     struct HksStoreKeyInfo *keyInfo = (struct HksStoreKeyInfo *)(g_storageImageBuffer.data + offset);
511 
512     struct HksStoreHeaderInfo newkeyInfoHead;
513     if (memcpy_s(&newkeyInfoHead, sizeof(newkeyInfoHead), keyInfoHead, sizeof(*keyInfoHead)) != EOK) {
514         return HKS_ERROR_INSUFFICIENT_MEMORY;
515     }
516 
517     uint32_t totalLenAdded = 0;
518     int32_t ret;
519 
520     /* 1. check storage buffer enough for store new key */
521     if (needDeleteKey) {
522         ret = GetLenAfterAddKey(keyBlob, keyInfoHead->totalLen - keyInfo->keyInfoLen, &totalLenAdded);
523     } else {
524         newkeyInfoHead.keyCount += 1,
525         ret = GetLenAfterAddKey(keyBlob, keyInfoHead->totalLen, &totalLenAdded);
526     }
527     HKS_IF_NOT_SUCC_RETURN(ret, ret)
528 
529     /* 2. calc temp hmac */
530     newkeyInfoHead.totalLen = totalLenAdded;
531     ret = RefreshKeyInfoHeaderHmac(&newkeyInfoHead);
532     HKS_IF_NOT_SUCC_RETURN(ret, ret)
533 
534     /* 3. delete key if keyExist */
535     if (needDeleteKey) {
536         ret = DeleteKey(offset);
537         HKS_IF_NOT_SUCC_RETURN(ret, ret)
538     }
539 
540     /* 4. append key */
541     ret = AppendNewKey(keyBlob);
542     HKS_IF_NOT_SUCC_RETURN(ret, ret)
543 
544     /* 5. replace header */
545     if (memcpy_s(g_storageImageBuffer.data, sizeof(newkeyInfoHead), &newkeyInfoHead, sizeof(newkeyInfoHead)) != EOK) {
546         HKS_LOG_E("replace header memcpy failed");
547         return HKS_ERROR_INSUFFICIENT_MEMORY;
548     }
549     return HKS_SUCCESS;
550 }
551 
GetFileName(const struct HksBlob * name,char ** fileName)552 static int32_t GetFileName(const struct HksBlob *name, char **fileName)
553 {
554     char *tmpName = (char *)HksMalloc(name->size + 1); /* \0 at the end */
555     HKS_IF_NULL_RETURN(tmpName, HKS_ERROR_MALLOC_FAIL)
556 
557     (void)memcpy_s(tmpName, name->size, name->data, name->size);
558     tmpName[name->size] = '\0';
559     *fileName = tmpName;
560     return HKS_SUCCESS;
561 }
562 
StoreRootMaterial(const struct HksBlob * name,const struct HksBlob * buffer)563 static int32_t StoreRootMaterial(const struct HksBlob *name, const struct HksBlob *buffer)
564 {
565     char *fileName = NULL;
566     int32_t ret = GetFileName(name, &fileName);
567     HKS_IF_NOT_SUCC_RETURN(ret, ret)
568 
569     ret = HksFileWrite(HKS_KEY_STORE_PATH, fileName, 0, buffer->data, buffer->size);
570     HKS_FREE(fileName);
571     return ret;
572 }
573 
IsRootMaterialExist(const struct HksBlob * name)574 static int32_t IsRootMaterialExist(const struct HksBlob *name)
575 {
576     char *fileName = NULL;
577     int32_t ret = GetFileName(name, &fileName);
578     HKS_IF_NOT_SUCC_RETURN(ret, ret)
579 
580     ret = HksIsFileExist(HKS_KEY_STORE_PATH, fileName);
581     HKS_FREE(fileName);
582     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, HKS_ERROR_NOT_EXIST, "file not exist")
583 
584     return ret;
585 }
586 
GetRootMaterial(const struct HksBlob * name,struct HksBlob * buffer)587 static int32_t GetRootMaterial(const struct HksBlob *name, struct HksBlob *buffer)
588 {
589     char *fileName = NULL;
590     int32_t ret = GetFileName(name, &fileName);
591     HKS_IF_NOT_SUCC_RETURN(ret, ret)
592 
593     uint32_t len = 0;
594     ret = HksFileRead(HKS_KEY_STORE_PATH, fileName, 0, buffer, &len);
595     HKS_FREE(fileName);
596     if (ret != HKS_SUCCESS) {
597         return HKS_ERROR_READ_FILE_FAIL;
598     }
599     return HKS_SUCCESS;
600 }
601 
HksStoreKeyBlob(const struct HksStoreFileInfo * fileInfo,const struct HksBlob * keyAlias,uint32_t storageType,const struct HksBlob * keyBlob)602 int32_t HksStoreKeyBlob(const struct HksStoreFileInfo *fileInfo, const struct HksBlob *keyAlias,
603     uint32_t storageType, const struct HksBlob *keyBlob)
604 {
605     (void)fileInfo;
606     if (storageType == HKS_STORAGE_TYPE_ROOT_KEY) {
607         return StoreRootMaterial(keyAlias, keyBlob);
608     }
609 
610     /* 1. check key exist or not */
611     uint32_t offset = 0;
612     int32_t ret = GetKeyOffsetByKeyAlias(keyAlias, &offset);
613     if ((ret != HKS_SUCCESS) && (ret != HKS_ERROR_NOT_EXIST)) {
614         return ret;
615     }
616 
617     /* 2. store key blob */
618     bool needDeleteKey = (ret == HKS_SUCCESS);
619     ret = StoreKeyBlob(needDeleteKey, offset, keyBlob);
620     HKS_IF_NOT_SUCC_RETURN(ret, ret)
621 
622     /* 3. write to file */
623     uint32_t totalLen = 0;
624     ret = HksStoreGetToatalSize(&totalLen);
625     HKS_IF_NOT_SUCC_RETURN(ret, ret)
626 
627     uint32_t fileOffset = HksGetStoreFileOffset();
628     return HksFileWrite(HKS_KEY_STORE_PATH, HKS_KEY_STORE_FILE_NAME, fileOffset, g_storageImageBuffer.data, totalLen);
629 }
630 
HksStoreDeleteKeyBlob(const struct HksStoreFileInfo * fileInfo,const struct HksBlob * keyAlias,uint32_t storageType)631 int32_t HksStoreDeleteKeyBlob(const struct HksStoreFileInfo *fileInfo,
632     const struct HksBlob *keyAlias, uint32_t storageType)
633 {
634     (void)fileInfo;
635     (void)storageType;
636 
637     /* 1. check key exist or not */
638     uint32_t offset = 0;
639     int32_t ret = GetKeyOffsetByKeyAlias(keyAlias, &offset);
640     HKS_IF_NOT_SUCC_RETURN(ret, ret)
641 
642     /* 2. calc tmp header hmac */
643     struct HksStoreHeaderInfo *keyInfoHead = (struct HksStoreHeaderInfo *)g_storageImageBuffer.data;
644     struct HksStoreKeyInfo *keyInfo = (struct HksStoreKeyInfo *)(g_storageImageBuffer.data + offset);
645     struct HksStoreHeaderInfo newkeyInfoHead;
646     if (memcpy_s(&newkeyInfoHead, sizeof(newkeyInfoHead), keyInfoHead, sizeof(*keyInfoHead)) != EOK) {
647         return HKS_ERROR_INSUFFICIENT_MEMORY;
648     }
649     newkeyInfoHead.totalLen -= keyInfo->keyInfoLen;
650     newkeyInfoHead.keyCount -= 1;
651 
652     ret = RefreshKeyInfoHeaderHmac(&newkeyInfoHead);
653     HKS_IF_NOT_SUCC_RETURN(ret, ret)
654 
655     /* 3. delete key */
656     ret = DeleteKey(offset);
657     HKS_IF_NOT_SUCC_RETURN(ret, ret)
658 
659     /* 4. replace header */
660     if (memcpy_s(keyInfoHead, sizeof(*keyInfoHead), &newkeyInfoHead, sizeof(newkeyInfoHead)) != EOK) {
661         return HKS_ERROR_INSUFFICIENT_MEMORY;
662     }
663 
664     uint32_t fileOffset = HksGetStoreFileOffset();
665     return HksFileWrite(HKS_KEY_STORE_PATH, HKS_KEY_STORE_FILE_NAME, fileOffset,
666         g_storageImageBuffer.data, keyInfoHead->totalLen);
667 }
668 
HksStoreIsKeyBlobExist(const struct HksStoreFileInfo * fileInfo,const struct HksBlob * keyAlias,uint32_t storageType)669 int32_t HksStoreIsKeyBlobExist(const struct HksStoreFileInfo *fileInfo,
670     const struct HksBlob *keyAlias, uint32_t storageType)
671 {
672     (void)fileInfo;
673     if (storageType == HKS_STORAGE_TYPE_ROOT_KEY) {
674         return IsRootMaterialExist(keyAlias);
675     }
676 
677     uint32_t offset = 0;
678     return GetKeyOffsetByKeyAlias(keyAlias, &offset);
679 }
680 
HksStoreGetKeyBlob(const struct HksStoreInfo * fileInfoPath,const struct HksBlob * keyAlias,uint32_t storageType,struct HksBlob * keyBlob)681 int32_t HksStoreGetKeyBlob(const struct HksStoreInfo *fileInfoPath,
682     const struct HksBlob *keyAlias, uint32_t storageType, struct HksBlob *keyBlob)
683 {
684     (void)fileInfoPath;
685     if (storageType == HKS_STORAGE_TYPE_ROOT_KEY) {
686         return GetRootMaterial(keyAlias, keyBlob);
687     }
688 
689     uint32_t offset = 0;
690     int32_t ret = GetKeyOffsetByKeyAlias(keyAlias, &offset);
691     HKS_IF_NOT_SUCC_RETURN(ret, ret)
692 
693     /* get offset success, len has been check valid */
694     uint8_t *tmpBuf = g_storageImageBuffer.data + offset;
695     struct HksStoreKeyInfo *keyInfo = (struct HksStoreKeyInfo *)tmpBuf;
696 
697     keyBlob->data = (uint8_t *)HksMalloc(keyInfo->keyInfoLen); /* need be freed by caller functions */
698     HKS_IF_NULL_RETURN(keyBlob->data, HKS_ERROR_MALLOC_FAIL)
699 
700     keyBlob->size = keyInfo->keyInfoLen;
701 
702     if (memcpy_s(keyBlob->data, keyBlob->size, tmpBuf, keyInfo->keyInfoLen) != EOK) {
703         HKS_LOG_E("memcpy to key blob failed.");
704         HKS_FREE(keyBlob->data);
705         return HKS_ERROR_INSUFFICIENT_MEMORY;
706     }
707 
708     return HKS_SUCCESS;
709 }
710 
HksStoreGetKeyBlobSize(const struct HksBlob * processName,const struct HksBlob * keyAlias,uint32_t storageType,uint32_t * keyBlobSize)711 int32_t HksStoreGetKeyBlobSize(const struct HksBlob *processName,
712     const struct HksBlob *keyAlias, uint32_t storageType, uint32_t *keyBlobSize)
713 {
714     (void)processName;
715     (void)storageType;
716 
717     uint32_t offset = 0;
718     int32_t ret = GetKeyOffsetByKeyAlias(keyAlias, &offset);
719     HKS_IF_NOT_SUCC_RETURN(ret, ret)
720 
721     /* get offset success, len has been check valid */
722     struct HksStoreKeyInfo *keyInfo = (struct HksStoreKeyInfo *)(g_storageImageBuffer.data + offset);
723     *keyBlobSize = keyInfo->keyInfoLen;
724     return HKS_SUCCESS;
725 }
726 
HksGetKeyCountByProcessName(const struct HksBlob * processName,uint32_t * keyCount)727 int32_t HksGetKeyCountByProcessName(const struct HksBlob *processName, uint32_t *keyCount)
728 {
729     (void)processName;
730     if (g_storageImageBuffer.size < sizeof(struct HksStoreHeaderInfo)) {
731         HKS_LOG_E("invalid keyinfo buffer size %" LOG_PUBLIC "u.", g_storageImageBuffer.size);
732         return HKS_ERROR_INVALID_KEY_FILE;
733     }
734 
735     struct HksStoreHeaderInfo *keyInfoHead = (struct HksStoreHeaderInfo *)g_storageImageBuffer.data;
736     *keyCount = keyInfoHead->keyCount;
737     return HKS_SUCCESS;
738 }
739 
HksStoreGetToatalSize(uint32_t * size)740 int32_t HksStoreGetToatalSize(uint32_t *size)
741 {
742     if (g_storageImageBuffer.size < sizeof(struct HksStoreHeaderInfo)) {
743         HKS_LOG_E("invalid keyinfo buffer size %" LOG_PUBLIC "u.", g_storageImageBuffer.size);
744         return HKS_ERROR_INVALID_KEY_FILE;
745     }
746 
747     struct HksStoreHeaderInfo *keyInfoHead = (struct HksStoreHeaderInfo *)g_storageImageBuffer.data;
748     *size = keyInfoHead->totalLen;
749     return HKS_SUCCESS;
750 }
751 
GetKeyInfoList(struct HksKeyInfo * keyInfoList,const struct HksBlob * keyInfoBlob)752 static int32_t GetKeyInfoList(struct HksKeyInfo *keyInfoList, const struct HksBlob *keyInfoBlob)
753 {
754     struct HksStoreKeyInfo *keyInfo = (struct HksStoreKeyInfo *)keyInfoBlob->data;
755 
756     if (keyInfoList->alias.size < keyInfo->aliasSize) {
757         return HKS_ERROR_BUFFER_TOO_SMALL;
758     }
759 
760     if (memcpy_s(keyInfoList->alias.data, keyInfoList->alias.size,
761         keyInfoBlob->data + sizeof(*keyInfo), keyInfo->aliasSize) != EOK) {
762         HKS_LOG_E("memcpy keyAlias failed");
763         return HKS_ERROR_INSUFFICIENT_MEMORY;
764     }
765     keyInfoList->alias.size = keyInfo->aliasSize;
766 
767     struct HksParamSet *paramSet = NULL;
768     int32_t ret = TranslateKeyInfoBlobToParamSet(NULL, keyInfoBlob, &paramSet);
769     HKS_IF_NOT_SUCC_RETURN(ret, ret)
770 
771     if (keyInfoList->paramSet->paramSetSize < paramSet->paramSetSize) {
772         HksFreeParamSet(&paramSet);
773         return HKS_ERROR_BUFFER_TOO_SMALL;
774     }
775     if (memcpy_s(keyInfoList->paramSet, keyInfoList->paramSet->paramSetSize,
776         paramSet, paramSet->paramSetSize) != EOK) {
777         HKS_LOG_E("memcpy paramSet failed.");
778         HksFreeParamSet(&paramSet);
779         return HKS_ERROR_INSUFFICIENT_MEMORY;
780     }
781 
782     HksFreeParamSet(&paramSet);
783     return HKS_SUCCESS;
784 }
785 
GetAndCheckKeyCount(uint32_t * inputCount,uint32_t * keyCount)786 static int32_t GetAndCheckKeyCount(uint32_t *inputCount, uint32_t *keyCount)
787 {
788     struct HksBlob storageBuf = HksGetImageBuffer();
789     if (storageBuf.size < sizeof(struct HksStoreHeaderInfo)) {
790         HKS_LOG_E("invalid keyinfo buffer size %" LOG_PUBLIC "u.", storageBuf.size);
791         return HKS_ERROR_INVALID_KEY_FILE;
792     }
793 
794     struct HksStoreHeaderInfo *keyInfoHead = (struct HksStoreHeaderInfo *)storageBuf.data;
795     *keyCount = keyInfoHead->keyCount;
796     if (*keyCount == 0) {
797         *inputCount = 0;
798         return HKS_SUCCESS;
799     }
800 
801     if (storageBuf.size < keyInfoHead->totalLen) {
802         HKS_LOG_E("storageBuf size invalid");
803         return HKS_ERROR_INVALID_KEY_FILE;
804     }
805 
806     if (*inputCount < *keyCount) {
807         HKS_LOG_E("listCount space not enough");
808         return HKS_ERROR_BUFFER_TOO_SMALL;
809     }
810     return HKS_SUCCESS;
811 }
812 
HksStoreGetKeyInfoList(struct HksKeyInfo * keyInfoList,uint32_t * listCount)813 int32_t HksStoreGetKeyInfoList(struct HksKeyInfo *keyInfoList, uint32_t *listCount)
814 {
815     uint32_t keyCount;
816     int32_t ret = GetAndCheckKeyCount(listCount, &keyCount);
817     HKS_IF_NOT_SUCC_RETURN(ret, ret)
818 
819     /* 2. traverse ImageBuffer to search for keyAlias */
820     struct HksBlob storageBuf = HksGetImageBuffer();
821     struct HksStoreHeaderInfo *keyInfoHead = (struct HksStoreHeaderInfo *)storageBuf.data;
822     uint32_t totalLen = keyInfoHead->totalLen;
823     uint32_t num = 0;
824     uint32_t offset = sizeof(*keyInfoHead);
825     for (uint32_t i = 0; i < keyCount; ++i) {
826         if ((totalLen < offset) || ((totalLen - offset) < sizeof(struct HksStoreKeyInfo))) {
827             HKS_LOG_E("invalid keyinfo size.");
828             return HKS_ERROR_INVALID_KEY_FILE;
829         }
830 
831         uint8_t *tmpBuf = storageBuf.data + offset; /* storageBuf.size has been checked */
832         struct HksStoreKeyInfo *keyInfo = (struct HksStoreKeyInfo *)tmpBuf;
833 
834         if (HksIsKeyInfoLenInvalid(keyInfo) || ((totalLen - offset) < keyInfo->keyInfoLen)) {
835             HKS_LOG_E("invalid keyinfo len");
836             return HKS_ERROR_INVALID_KEY_FILE;
837         }
838 
839         struct HksBlob keyInfoBlob = { keyInfo->keyInfoLen, tmpBuf };
840         ret = GetKeyInfoList(&keyInfoList[i], &keyInfoBlob);
841         HKS_IF_NOT_SUCC_RETURN(ret, ret)
842 
843         num++;
844         offset += keyInfo->keyInfoLen;
845     }
846 
847     *listCount = num;
848     return HKS_SUCCESS;
849 }
850 
851 #ifdef HKS_ENABLE_CLEAN_FILE
CleanFile(const char * path,const char * fileName)852 static int32_t CleanFile(const char *path, const char *fileName)
853 {
854     uint32_t size = HksFileSize(path, fileName);
855     if (size == 0 || size > HKS_MAX_FILE_SIZE) {
856         HKS_LOG_E("storage lite get file size failed, ret = %" LOG_PUBLIC "u.", size);
857         return HKS_ERROR_FILE_SIZE_FAIL;
858     }
859 
860     int32_t ret = HKS_SUCCESS;
861     uint8_t *buf;
862     do {
863         buf = (uint8_t *)HksMalloc(size);
864         if (buf == NULL) {
865             HKS_LOG_E("storage lite malloc buf failed!");
866             ret = HKS_ERROR_MALLOC_FAIL;
867             break;
868         }
869 
870         (void)memset_s(buf, size, 0, size);
871         ret = HksFileWrite(path, fileName, 0, buf, size);
872         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "write file 0 failed!")
873 
874         (void)memset_s(buf, size, 1, size);
875         ret = HksFileWrite(path, fileName, 0, buf, size);
876         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "write file 1 failed!")
877 
878         struct HksBlob bufBlob = { .size = size, .data = buf };
879         ret = HuksAccessGenerateRandom(NULL, &bufBlob);
880         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "fill buf random failed!")
881 
882         ret = HksFileWrite(path, fileName, 0, buf, size);
883         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "write file random failed!")
884     } while (0);
885     HKS_FREE(buf);
886     return ret;
887 }
888 #endif
889 
RemoveFile(const char * path,const char * fileName)890 static int32_t RemoveFile(const char *path, const char *fileName)
891 {
892 #ifdef HKS_ENABLE_CLEAN_FILE
893     if (CleanFile(path, fileName) != HKS_SUCCESS) {
894         HKS_LOG_E("clean file failed");
895     }
896 #endif
897 
898     if (HksFileRemove(path, fileName) != HKS_SUCCESS) {
899         HKS_LOG_E("remove file failed");
900     }
901     return HKS_SUCCESS;
902 }
903 
HksStoreDestroy(const struct HksBlob * processName)904 int32_t HksStoreDestroy(const struct HksBlob *processName)
905 {
906     (void)processName;
907     /* only record log, continue delete */
908 
909     if (RemoveFile(HKS_KEY_STORE_PATH, HKS_KEY_STORE_FILE_NAME) != HKS_SUCCESS) {
910         HKS_LOG_E("remove key store file failed");
911     }
912 
913     if (RemoveFile(HKS_KEY_STORE_PATH, "info1.data") != HKS_SUCCESS) {
914         HKS_LOG_E("remove info1 file failed");
915     }
916 
917     if (RemoveFile(HKS_KEY_STORE_PATH, "info2.data") != HKS_SUCCESS) {
918         HKS_LOG_E("remove info2 file failed");
919     }
920     return HKS_SUCCESS;
921 }
922 #endif /* _STORAGE_LITE_ */
923 
924 #endif /* _CUT_AUTHENTICATE_ */
925