• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3  * Licensed under the Mulan PSL v2.
4  * You can use this software according to the terms and conditions of the Mulan PSL v2.
5  * You may obtain a copy of Mulan PSL v2 at:
6  *     http://license.coscl.org.cn/MulanPSL2
7  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8  * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9  * PURPOSE.
10  * See the Mulan PSL v2 for more details.
11  */
12 #include "tee_defines.h"
13 #include "sfs.h"
14 #include "tee_mem_mgmt_api.h"
15 #include "tee_log.h"
16 #include "ta_framework.h"
17 #include "tee_ext_api.h"
18 #include "sfs_internal.h"
19 #include "securec.h"
20 #include "string.h"
21 #include "tee_crypto_hal.h"
22 #include "ssa_fs.h"
23 
24 #define BYTE_LEN 8
get_spec_errno(TEE_Result ret_default)25 TEE_Result get_spec_errno(TEE_Result ret_default)
26 {
27     TEE_Result ret0 = fs_get_serr();
28     if (ret0 == TEE_SUCCESS)
29         return ret_default;
30 
31     return ret0;
32 }
33 
34 struct ssa_open_info {
35     int32_t file_fd;
36     TEE_Result ret;
37     uint32_t size;
38 };
39 
40 static TEE_Result init_meta_data(struct sfd_t *sfd);
41 static void free_sfd(struct sfd_t *sfd);
42 static int32_t check_integrity_v2(struct sfd_t *sfd);
43 static TEE_Result construct_block_info(struct sfd_t *sfd);
44 static int32_t get_hmac_from_meta_data_checkfilename(struct sfd_t *sfd, meta_storage_t *sfs_meta);
45 TEE_Result do_rename(struct sfd_t *sfd, meta_data_t *new_meta_data);
46 
47 #define SHA_BUFF_HIGH_MASK    0xf0
48 #define SHA_BUFF_LOW_MASK     0x0f
49 #define HALF_BYTE_OFFSET      4U
50 #define DOUBLE(x)             ((x) * 2)
51 #define IS_SINGLE_DIGIT(x)    ((x) >= 0 && (x) <= 9)
52 #define IS_HEX_NUM(x)         ((x) >= 10 && (x) <= 15)
53 #define MIN_TWO_DIGIT         10
54 /* CAUTION: the size of "dest" MUST be larger than HASH_LEN*2 */
str_tran(const unsigned char * sha_buff,uint32_t buff_len,char * dest,uint32_t dest_len)55 void str_tran(const unsigned char *sha_buff, uint32_t buff_len, char *dest, uint32_t dest_len)
56 {
57     int32_t i;
58     bool param_check_fail = (sha_buff == NULL) || (dest == NULL) ||
59         (buff_len < HASH_LEN) || (dest_len <= HASH_VERIFY_LEN);
60 
61     if (param_check_fail)
62         return;
63 
64     for (i = 0; i < HASH_LEN; i++) {
65         int8_t hb = (sha_buff[i] & SHA_BUFF_HIGH_MASK) >> HALF_BYTE_OFFSET;
66         if (IS_SINGLE_DIGIT(hb))
67             hb += '0';
68         else if (IS_HEX_NUM(hb))
69             hb = ((hb - MIN_TWO_DIGIT) + 'A');
70 
71         int8_t lb = sha_buff[i] & SHA_BUFF_LOW_MASK;
72         if (IS_SINGLE_DIGIT(lb))
73             lb += '0';
74         else /* lb must be between 10 and 15 */
75             lb = (lb - MIN_TWO_DIGIT) + 'A';
76 
77         dest[DOUBLE(i)]     = hb;
78         dest[DOUBLE(i) + 1] = lb;
79     }
80 
81     dest[HASH_VERIFY_LEN] = '\0';
82 
83     return;
84 }
85 
get_hmac_from_meta_data(struct sfd_t * sfd,uint8_t * hmac_buff,uint32_t hmac_buff_len)86 int32_t get_hmac_from_meta_data(struct sfd_t *sfd, uint8_t *hmac_buff, uint32_t hmac_buff_len)
87 {
88     /* for fread */
89     uint32_t read_ret;
90     int32_t error = 0;
91     /* for meta_data */
92     meta_storage_t sfs_meta;
93     /* for hmac */
94     uint8_t calculated_hmac[HASH_VERIFY_LEN + 1] = { 0 };
95 
96     if (sfd == NULL || hmac_buff == NULL) {
97         tloge("check param failed!!\n");
98         return -1;
99     }
100 
101     (void)memset_s(&sfs_meta, sizeof(sfs_meta), 0, sizeof(sfs_meta));
102     /* 1. read metadata */
103     read_ret = ssa_fs_fread(&sfs_meta, sizeof(sfs_meta), sfd->nfd, &error);
104     if (read_ret != sizeof(sfs_meta) || error < 0) {
105         tloge("fread metadata failed!!\n");
106         return -1;
107     }
108 
109     /* 2. calculate hmac about metadata */
110     if (calculate_hmac((uint8_t *)&sfs_meta, sizeof(meta_storage_header_t),
111                        calculated_hmac, sizeof(calculated_hmac), sfd) != TEE_SUCCESS) {
112         tloge("get hmac of metadata failed\n");
113         return -1;
114     }
115 
116     /* 3. compare the hmac of metadata */
117     if (TEE_MemCompare(sfs_meta.meta_hmac, calculated_hmac, HASH_VERIFY_LEN) != 0) {
118         tloge("compare metadata hamc failed!!\n");
119         return -1;
120     }
121 
122     /* 4. check filename + datahmac */
123     if (get_hmac_from_meta_data_checkfilename(sfd, &sfs_meta) != 0) {
124         tloge("get hmac from meta data check filename failed!!\n");
125         return -1;
126     }
127 
128     sfd->last_block_size = sfs_meta.hdr.last_block_realsize;
129     sfd->data_encmeth  = sfs_meta.hdr.encrypto_meth;
130 
131     /* 5. read data hmac */
132     if (memmove_s(hmac_buff, hmac_buff_len, sfs_meta.data_hmac, sizeof(sfs_meta.data_hmac)) != EOK)
133         return -1;
134 
135     return 0;
136 }
137 
ssa_removefile(const uint8_t * filename,const char * file_desc,uint32_t storage_id)138 void ssa_removefile(const uint8_t *filename, const char *file_desc, uint32_t storage_id)
139 {
140     int32_t ret;
141     const char *p_filedesc = ((file_desc == NULL) ? "file" : file_desc);
142 
143     if (filename != NULL && strlen((char *)filename) != 0) {
144         ret = ssa_fs_fremove((char *)filename, storage_id);
145         if (ret != 0) {
146             tloge("remove %s failed ret %d, errno %x\n", p_filedesc, ret, fs_get_serr());
147             tlogd("remove %s %s failed ret %d, errno %x\n", p_filedesc, (char *)filename, ret, fs_get_serr());
148         } else {
149             tlogd("remove %s %s  successfully\n", p_filedesc, (char *)filename);
150         }
151     }
152 
153     return;
154 }
155 
get_key_value_by_version(struct sfd_t * sfd,uint8_t ** key_value,uint32_t * key_value_size)156 static TEE_Result get_key_value_by_version(struct sfd_t *sfd, uint8_t **key_value, uint32_t *key_value_size)
157 {
158     if (sfd->meta_data->arch_version == SFS_ARCH_VERSION_SSA) {
159         *key_value      = sfd->meta_data->hmac_key;
160         *key_value_size = sizeof(sfd->meta_data->hmac_key);
161     } else {
162         tloge("invalid arch_version: %u\n", sfd->meta_data->arch_version);
163         return TEE_ERROR_BAD_STATE;
164     }
165 
166     return TEE_SUCCESS;
167 }
168 
check_ssa_version_type(struct sfd_t * sfd)169 bool check_ssa_version_type(struct sfd_t *sfd)
170 {
171     return (sfd->meta_data->arch_version == SFS_ARCH_VERSION_SSA);
172 }
173 
174 /* CAUTION: the size of "dest" MUST be larger than HASH_LEN*2 */
calculate_hmac(const uint8_t * src,uint32_t src_len,uint8_t * dest,uint32_t dest_len,const struct sfd_t * sfd)175 TEE_Result calculate_hmac(const uint8_t *src, uint32_t src_len, uint8_t *dest, uint32_t dest_len,
176                           const struct sfd_t *sfd)
177 {
178     unsigned char temp_buff[HASH_VERIFY_LEN + 1] = { 0 };
179     uint32_t out_len = HASH_VERIFY_LEN + 1;
180     TEE_Result ret;
181     struct key_info_t key_info;
182 
183     if (src == NULL || dest == NULL || sfd == NULL || sfd->meta_data == NULL || src_len > INT32_MAX)
184         return TEE_ERROR_BAD_PARAMETERS;
185 
186     key_info.key = sfd->meta_data->hmac_key;
187     key_info.key_len = sizeof(sfd->meta_data->hmac_key);
188 
189     ret = calc_hmac256(&key_info, src, (int32_t)src_len, (uint8_t *)temp_buff, &out_len);
190     if (ret != TEE_SUCCESS) {
191         tloge("do hmac sha256 failed!\n");
192         return TEE_ERROR_GENERIC;
193     }
194 
195     str_tran(temp_buff, out_len, (char *)dest, dest_len);
196 
197     return TEE_SUCCESS;
198 }
199 
ssa_close_and_delete(struct sfd_t * sfd,bool is_delete)200 TEE_Result ssa_close_and_delete(struct sfd_t *sfd, bool is_delete)
201 {
202     if (sfd == NULL || sfd->meta_data == NULL) {
203         tloge("ssa close delete Illegal sfd\n");
204         return TEE_ERROR_BAD_PARAMETERS;
205     }
206 
207     (void)ssa_fs_fclose(sfd->nfd);
208 
209     switch (sfd->meta_data->arch_version) {
210     case SFS_ARCH_VERSION_SSA:
211         ssa_removefile(sfd->meta_data->encrypted_file_id, "file", sfd->meta_data->storage_id);
212         if (is_delete == true)
213             ssa_removefile(sfd->meta_data->backup_file_id, "bkfile", sfd->meta_data->storage_id);
214         break;
215     default:
216         tloge("invalid arch_version 0x%x\n", sfd->meta_data->arch_version);
217         return TEE_ERROR_BAD_STATE;
218     }
219 
220     free_sfd(sfd);
221 
222     return TEE_SUCCESS;
223 }
224 
get_hmac_of_data(struct sfd_t * sfd,uint8_t * hmac_buff,uint32_t hmac_buff_len)225 int32_t get_hmac_of_data(struct sfd_t *sfd, uint8_t *hmac_buff, uint32_t hmac_buff_len)
226 {
227     if (sfd == NULL || sfd->meta_data == NULL || hmac_buff == NULL)
228         return -1;
229 
230     switch (sfd->meta_data->arch_version) {
231     case SFS_ARCH_VERSION_SSA:
232         return get_hmac_from_meta_data(sfd, hmac_buff, hmac_buff_len);
233     default:
234         tloge("Invalid arch_version %u\n", sfd->meta_data->arch_version);
235         return -1;
236     }
237 }
238 
judge_valid_version(const struct sfd_t * sfd)239 static bool judge_valid_version(const struct sfd_t *sfd)
240 {
241     (void)sfd;
242     return true;
243 }
244 
switch_arch_version_rename(struct sfd_t * sfd,const uint8_t * new_obj_id,uint32_t new_obj_len,meta_data_t * new_meta_data)245 static TEE_Result switch_arch_version_rename(struct sfd_t *sfd, const uint8_t *new_obj_id, uint32_t new_obj_len,
246                                              meta_data_t *new_meta_data)
247 {
248     TEE_Result ret;
249     (void)new_obj_id;
250     (void)new_obj_len;
251 
252     switch (sfd->meta_data->arch_version) {
253     case SFS_ARCH_VERSION_SSA: {
254         ret = do_rename(sfd, new_meta_data);
255         if (ret != TEE_SUCCESS)
256             tloge("sfs arch version ssa rename failed, ret = 0x%x\n", ret);
257         break;
258     }
259     default:
260         tloge("invalid arch version %u\n", sfd->meta_data->arch_version);
261         ret = TEE_ERROR_BAD_FORMAT;
262         break;
263     }
264 
265     return ret;
266 }
267 
268 /* CAUTION: the size of "dest" MUST be larger than HASH_LEN*2 */
get_hname(const char * src,int32_t length,char * dest,uint32_t dest_len,meta_data_t * meta)269 TEE_Result get_hname(const char *src, int32_t length, char *dest, uint32_t dest_len, meta_data_t *meta)
270 {
271     unsigned char temp_buff[HASH_VERIFY_LEN + 1] = { 0 };
272     TEE_Result ret;
273     uint32_t out_len = HASH_LEN;
274 
275     if (src == NULL || dest == NULL || meta == NULL) {
276         tloge("src, dest or meta is NULL\n");
277         return (TEE_Result)TEE_ERROR_BAD_PARAMETERS;
278     }
279     struct key_info_t key_info;
280     key_info.key = meta->file_id_key;
281     key_info.key_len = sizeof(meta->file_id_key);
282     ret = calc_hmac256(&key_info, (uint8_t *)src, length, temp_buff, &out_len);
283     if (ret != TEE_SUCCESS) {
284         tloge("TEE_MAC error! %x\n", ret);
285         return ret;
286     }
287 
288     str_tran(temp_buff, (uint32_t)out_len, dest, dest_len);
289 
290     return TEE_SUCCESS;
291 }
292 
calc_filename_datahmac_hash(meta_storage_t * sfs_meta,const struct sfd_t * sfd)293 TEE_Result calc_filename_datahmac_hash(meta_storage_t *sfs_meta, const struct sfd_t *sfd)
294 {
295     uint8_t *fname_datahmac_src = NULL;
296     uint32_t fname_datahmac_len;
297     errno_t rc;
298     TEE_Result ret;
299 
300     if ((sfs_meta == NULL) || (sfd == NULL) || sfd->meta_data == NULL) {
301         tloge("sfs_meta or sfd is null\n");
302         return TEE_ERROR_BAD_PARAMETERS;
303     }
304     fname_datahmac_len = HASH_NAME_BUFF_LEN + sizeof(sfs_meta->data_hmac);
305     fname_datahmac_src = TEE_Malloc((size_t)fname_datahmac_len, 0);
306     if (fname_datahmac_src == NULL) {
307         tloge("malloc1 blockInfo failed\n");
308         return TEE_ERROR_OUT_OF_MEMORY;
309     }
310 
311     rc = memmove_s(fname_datahmac_src, HASH_NAME_BUFF_LEN, sfd->meta_data->file_id,
312                    sfd->meta_data->file_id_len);
313     if (rc != EOK) {
314         tloge("memmove failed\n");
315         TEE_Free(fname_datahmac_src);
316         return TEE_ERROR_SECURITY;
317     }
318     rc = memmove_s(fname_datahmac_src + HASH_NAME_BUFF_LEN, fname_datahmac_len - HASH_NAME_BUFF_LEN,
319                    sfs_meta->data_hmac, sizeof(sfs_meta->data_hmac));
320     if (rc != EOK) {
321         tloge("memmove failed\n");
322         TEE_Free(fname_datahmac_src);
323         return TEE_ERROR_SECURITY;
324     }
325 
326     ret = cmd_hash(fname_datahmac_src, fname_datahmac_len, (uint8_t *)sfs_meta->hdr.fname_datahmac_hash,
327                    sizeof(sfs_meta->hdr.fname_datahmac_hash));
328     if (ret != TEE_SUCCESS) {
329         tloge("cmd_hash failed\n");
330         TEE_Free(fname_datahmac_src);
331         return ret;
332     }
333 
334     TEE_Free(fname_datahmac_src);
335     return TEE_SUCCESS;
336 }
337 
338 /* fd is secure file handle */
get_last_crypt_block_padding_size(const struct sfd_t * sfd)339 static int32_t get_last_crypt_block_padding_size(const struct sfd_t *sfd)
340 {
341     if (sfd == NULL)
342         return -1;
343 
344     return sfd->last_block_size ? (sfd->crypto_block_size - sfd->last_block_size) : 0;
345 }
346 
init_meta_data(struct sfd_t * sfd)347 static TEE_Result init_meta_data(struct sfd_t *sfd)
348 {
349     uint32_t written_len, write_count;
350     meta_storage_t *buf = NULL;
351     meta_storage_t sfs_meta;
352     TEE_Result ret;
353 
354     /* init the meta_data */
355     (void)memset_s((void *)&sfs_meta, sizeof(meta_storage_t), 0, sizeof(meta_storage_t));
356 
357     buf                          = &sfs_meta;
358     buf->hdr.magic_lo            = SFS_STORAGE_MAGIC_LO;
359     buf->hdr.magic_hi            = SFS_STORAGE_MAGIC_HI;
360     buf->hdr.arch_version        = sfd->meta_data->arch_version;
361     buf->hdr.last_block_realsize = 0;
362     (void)memset_s((void *)(buf->hdr.reserved), sizeof(buf->hdr.reserved), 0x0, sizeof(buf->hdr.reserved));
363     (void)memset_s((void *)(buf->meta_hmac), sizeof(buf->meta_hmac), 0x0, sizeof(buf->meta_hmac));
364     (void)memset_s((void *)(buf->data_hmac), sizeof(buf->data_hmac), 0x0, sizeof(buf->data_hmac));
365 
366 #ifdef CONFIG_THIRD_STORAGE_SUPPORT
367     TEE_GenerateRandom(&sfd->first_iv, sizeof(sfd->first_iv));
368     buf->hdr.first_iv = sfd->first_iv;
369 #endif
370     buf->hdr.magic_version = META_STORATE_MAGIC_VERSION;
371     if (sfd->meta_data->arch_version >= SFS_ARCH_VERSION_SSA) {
372         buf->hdr.encrypto_meth = SFS_DATA_ENCRYPTO_XTS;
373         sfd->data_encmeth      = SFS_DATA_ENCRYPTO_XTS;
374     }
375 
376     int32_t fd = sfd->nfd;
377 
378     /* write to data file */
379     if (ssa_fs_fseek(fd, 0, TEE_DATA_SEEK_SET) != 0) {
380         tloge("seek file failed\n");
381         ret = get_spec_errno(TEE_ERROR_SEEK_DATA);
382         goto err_out;
383     }
384 
385     ret = TEE_SUCCESS;
386 
387     write_count = sizeof(meta_storage_t);
388     written_len = ssa_fs_fwrite(buf, write_count, fd);
389     if (written_len != write_count) {
390         tloge("a written error occurs, expected=%u, actual=%u\n", write_count, written_len);
391         ret = get_spec_errno(TEE_ERROR_WRITE_DATA);
392     }
393 
394 err_out:
395     return ret;
396 }
397 
get_hmac_from_meta_data_checkfilename(struct sfd_t * sfd,meta_storage_t * sfs_meta)398 static int32_t get_hmac_from_meta_data_checkfilename(struct sfd_t *sfd, meta_storage_t *sfs_meta)
399 {
400     errno_t rc;
401 
402     if (sfs_meta->hdr.magic_version == META_STORATE_MAGIC_VERSION) {
403         uint32_t fname_datahmac_hash[DATAHMAC_HASH_SIZE];
404         rc = memmove_s(fname_datahmac_hash, sizeof(fname_datahmac_hash), sfs_meta->hdr.fname_datahmac_hash,
405                        sizeof(sfs_meta->hdr.fname_datahmac_hash));
406         if (rc != EOK) {
407             tloge("memove failed!! %d\n", rc);
408             return -1;
409         }
410 
411         if (calc_filename_datahmac_hash(sfs_meta, sfd) != TEE_SUCCESS)
412             return -1;
413 
414         if (TEE_MemCompare(fname_datahmac_hash, sfs_meta->hdr.fname_datahmac_hash, sizeof(fname_datahmac_hash)) != 0) {
415             tloge("compare datahmac failed!!\n");
416             return -1;
417         }
418 #ifdef CONFIG_THIRD_STORAGE_SUPPORT
419         sfd->first_iv = sfs_meta->hdr.first_iv;
420     } else {
421         sfd->first_iv = 0;
422 #endif
423     }
424 
425     return 0;
426 }
427 
calculate_block_hash(uint8_t * sha_buff,uint32_t sha_size,const uint8_t * data,uint32_t data_size)428 TEE_Result calculate_block_hash(uint8_t *sha_buff, uint32_t sha_size, const uint8_t *data, uint32_t data_size)
429 {
430     if (sha_buff == NULL || data == NULL)
431         return TEE_ERROR_BAD_PARAMETERS;
432 
433     return cmd_hash(data, data_size, sha_buff, sha_size);
434 }
435 
master_hmac_params_check(const struct sfd_t * sfd,const uint8_t * hmac_buf,const uint32_t * buf_size,uint32_t * cipher_blks)436 static TEE_Result master_hmac_params_check(const struct sfd_t *sfd,
437     const uint8_t *hmac_buf, const uint32_t *buf_size, uint32_t *cipher_blks)
438 {
439     uint32_t blks = 0;
440     struct block_info_t *cur_block_pos = NULL;
441 
442     if (sfd == NULL || hmac_buf == NULL || buf_size == NULL)
443         return TEE_ERROR_BAD_PARAMETERS;
444 
445     cur_block_pos = sfd->first_block;
446     if (cur_block_pos == NULL || sfd->meta_data == NULL) {
447         tloge("cur_block_pos illegal pointer\n");
448         return TEE_ERROR_BAD_PARAMETERS;
449     }
450 
451     while (cur_block_pos != NULL) {
452         blks++;
453         cur_block_pos = cur_block_pos->next;
454     }
455 
456     if (cipher_blks == NULL)
457         return TEE_ERROR_BAD_PARAMETERS;
458 
459     *cipher_blks = blks;
460     return TEE_SUCCESS;
461 }
462 
463 #define EVEN_NUM 2
464 /* calculate master hmac base on block list in sfd */
calculate_master_hmac(struct sfd_t * sfd,uint8_t * hmac_buf,uint32_t * buf_size)465 TEE_Result calculate_master_hmac(struct sfd_t *sfd, uint8_t *hmac_buf, uint32_t *buf_size)
466 {
467     struct block_info_t *cur_block_pos = NULL;
468     uint32_t cipher_blks = 0;
469     uint8_t *all_blks_hash = NULL;
470     uint8_t *key_value = NULL;
471     uint32_t key_value_size;
472 
473     TEE_Result ret = master_hmac_params_check(sfd, hmac_buf, buf_size, &cipher_blks);
474     if (ret != TEE_SUCCESS)
475         return ret;
476 
477     /*
478      * "DataInSize" MUST be multiple of 64.
479      * so, cipher_blks SHOULD be an even number,
480      * then "DataInSize" is HASH_LEN*(even).
481      */
482     if (cipher_blks % EVEN_NUM)
483         cipher_blks++;
484 
485     all_blks_hash = TEE_Malloc(cipher_blks * HASH_LEN, 0);
486     if (all_blks_hash == NULL) {
487         tloge("malloc failed, size=%u\n", cipher_blks * HASH_LEN);
488         return TEE_ERROR_OUT_OF_MEMORY;
489     }
490 
491     cur_block_pos = sfd->first_block;
492     while (cur_block_pos != NULL) {
493         if (memmove_s(all_blks_hash + cur_block_pos->block_id * HASH_LEN,
494             cipher_blks * HASH_LEN - cur_block_pos->block_id * HASH_LEN, cur_block_pos->hash, HASH_LEN) != EOK) {
495             TEE_Free(all_blks_hash);
496             return TEE_ERROR_SECURITY;
497         }
498         cur_block_pos = cur_block_pos->next;
499     }
500 
501     ret = get_key_value_by_version(sfd, &key_value, &key_value_size);
502     if (ret != TEE_SUCCESS) {
503         TEE_Free(all_blks_hash);
504         return ret;
505     }
506 
507     struct key_info_t key_info;
508     key_info.key = key_value;
509     key_info.key_len = key_value_size;
510     ret = calc_hmac256(&key_info, all_blks_hash, cipher_blks * HASH_LEN, hmac_buf, buf_size);
511     if (ret != TEE_SUCCESS) {
512         tloge("do hmac sha256 failed!\n");
513         TEE_Free(all_blks_hash);
514         return TEE_ERROR_GENERIC;
515     }
516 
517     TEE_Free(all_blks_hash);
518     return TEE_SUCCESS;
519 }
520 
cal_construct_block(struct sfd_t * sfd,uint32_t data_size)521 static TEE_Result cal_construct_block(struct sfd_t *sfd, uint32_t data_size)
522 {
523     int32_t error = 0;
524     struct block_info_t *temp = NULL;
525     struct block_info_t *next = NULL;
526     struct block_info_t *cur_block_pos = NULL;
527     struct block_info_t *last_block_pos = NULL;
528     uint32_t block_size = CRYPT_BLOCK_SIZE_V3;
529     uint8_t *buffer = NULL;
530     buffer = malloc(CRYPT_BLOCK_SIZE_V3);
531     if (buffer == NULL)
532         return TEE_ERROR_OUT_OF_MEMORY;
533 
534     cur_block_pos = sfd->first_block;
535     last_block_pos = cur_block_pos;
536     while (data_size > 0) {
537         uint32_t read_count = ssa_fs_fread(buffer, block_size, sfd->nfd, &error);
538         if (((read_count % block_size) != 0) || (error < 0)) {
539             tloge("read encrypto buffer failed, read_count=%u, error=%d\n", read_count, error);
540             TEE_Free(buffer);
541             return get_spec_errno(TEE_ERROR_READ_DATA);
542         }
543 
544         if (cur_block_pos == NULL) {
545             last_block_pos->next = TEE_Malloc(sizeof(*last_block_pos), 0);
546             if (last_block_pos->next == NULL) {
547                 TEE_Free(buffer);
548                 return TEE_ERROR_OUT_OF_MEMORY;
549             }
550 
551             cur_block_pos = last_block_pos->next;
552             cur_block_pos->block_id = last_block_pos->block_id + 1;
553             cur_block_pos->next = NULL;
554         }
555 
556         if (calculate_block_hash(cur_block_pos->hash, sizeof(cur_block_pos->hash), buffer, block_size) != TEE_SUCCESS)
557             tlogw("cal hash fail\n");
558         last_block_pos = cur_block_pos;
559         cur_block_pos = cur_block_pos->next;
560         data_size -= read_count;
561     }
562 
563     /*
564      * The backup file and the original file share the linked list.
565      * When the two files are not the same size, the redundant linked
566      * list needs to be released.
567      */
568     temp = cur_block_pos;
569     while (temp != NULL) {
570         next = temp->next;
571         TEE_Free(temp);
572         temp = next;
573     }
574 
575     last_block_pos->next = NULL;
576     TEE_Free(buffer);
577     return TEE_SUCCESS;
578 }
579 
construct_block_info(struct sfd_t * sfd)580 static TEE_Result construct_block_info(struct sfd_t *sfd)
581 {
582     int32_t ret;
583     TEE_Result ret_c;
584     uint32_t cur_pos, data_size;
585 
586     bool param_check_null = (sfd == NULL) || (sfd->meta_data == NULL) || (sfd->first_block == NULL);
587     if (param_check_null)
588         return TEE_ERROR_BAD_PARAMETERS;
589 
590     ret = ssa_fs_finfo(sfd->nfd, &cur_pos, &data_size);
591     if (ret < 0) {
592         tloge("get info of file %s failed\n", sfd->opened_orig ? "origin" : "backup");
593         return get_spec_errno(TEE_ERROR_GENERIC);
594     }
595 
596     if (data_size < SFS_METADATA_SIZE) {
597         tloge("get info of file %s failed, datasize 0x%x\n", sfd->opened_orig ? "origin" : "backup", data_size);
598         return get_spec_errno(TEE_ERROR_GENERIC);
599     }
600 
601     data_size -= SFS_METADATA_SIZE;
602     ret = ssa_fs_fseek(sfd->nfd, SFS_METADATA_SIZE, TEE_DATA_SEEK_SET);
603     if (ret < 0) {
604         tloge("seek file %s failed\n", sfd->opened_orig ? "origin" : "backup");
605         return get_spec_errno(TEE_ERROR_SEEK_DATA);
606     }
607 
608     /* actual_size add padding_size is data_size */
609     sfd->size            = data_size;
610     bool blocksize_check = (sfd->size >= (sfd->crypto_block_size - sfd->last_block_size)) &&
611         (sfd->last_block_size != 0);
612     if (blocksize_check)
613         sfd->size -= (sfd->crypto_block_size - sfd->last_block_size);
614 
615     if (data_size == 0 || (data_size % sfd->crypto_block_size)) {
616         tloge("file %s length %u is error\n", sfd->opened_orig ? "origin" : "backup", data_size);
617         return get_spec_errno(TEE_ERROR_GENERIC);
618     }
619 
620     ret_c = cal_construct_block(sfd, data_size);
621 
622     return ret_c;
623 }
624 
625 /* This function for latest format, include PO */
check_integrity_v2(struct sfd_t * sfd)626 static int32_t check_integrity_v2(struct sfd_t *sfd)
627 {
628     uint8_t provided_hmac[HASH_VERIFY_LEN + 1]   = { 0 };
629     uint8_t calculated_hmac[HASH_VERIFY_LEN + 1] = { 0 };
630     uint8_t hmac_buf[HASH_LEN]                   = { 0 };
631     uint32_t hmac_buf_len                        = HASH_LEN;
632 
633     /* 1. get hmac from meta_data */
634     if (get_hmac_of_data(sfd, provided_hmac, HASH_VERIFY_LEN)) {
635         tloge("get hmac from meta_data failed\n");
636         return -1;
637     }
638 
639     /* 2. calculate hash of each cipher block */
640     if (construct_block_info(sfd)) {
641         tloge("construct block info failed\n");
642         return -1;
643     }
644 
645     /* 3. calculate hmac of block hash */
646     if (calculate_master_hmac(sfd, hmac_buf, &hmac_buf_len)) {
647         tloge("calculate master hmac failed\n");
648         return -1;
649     }
650     str_tran((unsigned char *)hmac_buf, hmac_buf_len, (char *)calculated_hmac, sizeof(calculated_hmac));
651 
652     /* 4. compare */
653     if (TEE_MemCompare(calculated_hmac, provided_hmac, HASH_VERIFY_LEN) != 0) {
654         tloge("checkIntegrity failed\n");
655         tloge("calculated_hmac=%s\n", calculated_hmac);
656         tloge("provided_hmac=%s\n", provided_hmac);
657         return -1;
658     }
659 
660     tlogd("checkIntegrity success \n");
661     return 0;
662 }
663 
664 /* fd is secure file handle */
fill_file_hole(struct sfd_t * sfd,uint32_t start_offset,uint32_t size)665 TEE_Result fill_file_hole(struct sfd_t *sfd, uint32_t start_offset, uint32_t size)
666 {
667     uint8_t *fill_buff = NULL;
668     uint32_t times, index;
669     const uint32_t hole_per_size = 1024;
670     TEE_Result error             = TEE_SUCCESS;
671     if (start_offset > INT32_MAX) {
672         tloge("Invalid offset, more than INT32_MAX");
673         return TEE_ERROR_BAD_PARAMETERS;
674     }
675     if (ssa_seek(sfd, (int32_t)start_offset, TEE_DATA_SEEK_SET) != 0)
676         return TEE_ERROR_GENERIC;
677 
678     fill_buff = TEE_Malloc(hole_per_size, 0);
679     if (fill_buff == NULL) {
680         tloge("alloc hole buffer failed\n");
681         return TEE_ERROR_OUT_OF_MEMORY;
682     }
683 
684     times = size / hole_per_size + ((size % hole_per_size) ? 1 : 0);
685     for (index = 0; index < times; index++) {
686         uint32_t send_count = hole_per_size * (index + 1) > size ? size % hole_per_size : hole_per_size;
687         uint32_t count      = ssa_write(fill_buff, send_count, sfd, &error);
688         if ((count != send_count) || (error != TEE_SUCCESS)) {
689             TEE_Free(fill_buff);
690             return error;
691         }
692     }
693     TEE_Free(fill_buff);
694 
695     return TEE_SUCCESS;
696 }
free_sfd(struct sfd_t * sfd)697 static void free_sfd(struct sfd_t *sfd)
698 {
699     struct block_info_t *cur_block_pos  = NULL;
700     struct block_info_t *next_block_pos = NULL;
701     if (sfd != NULL) {
702         cur_block_pos = sfd->first_block;
703         while (cur_block_pos != NULL) {
704             next_block_pos = cur_block_pos->next;
705             TEE_Free(cur_block_pos);
706             cur_block_pos = next_block_pos;
707         }
708 
709         TEE_Free(sfd);
710     }
711 }
712 
713 typedef enum {
714     /* origin file does not exist */
715     ORI_NOENT = 1,
716     /* backup file does not exist */
717     BK_NOENT = 2,
718     /* origin file intergerity checking fails */
719     ORI_CHECK_FAIL = 4,
720     /* backup file intergerity checking fails */
721     BK_CHECK_FAIL = 8,
722 } file_status;
723 
ssa_open_check(struct sfd_t * sfd,const char * file_name,uint32_t flag,int32_t * fd)724 static TEE_Result ssa_open_check(struct sfd_t *sfd, const char *file_name, uint32_t flag, int32_t *fd)
725 {
726     TEE_Result ret;
727 
728     if (sfd == NULL || file_name == NULL || fd == NULL)
729         return TEE_ERROR_BAD_PARAMETERS;
730 
731     *fd = ssa_fs_fopen(file_name, flag, sfd->meta_data->storage_id);
732     if (*fd < 0) {
733         ret = TEE_ERROR_ITEM_NOT_FOUND;
734         goto out;
735     }
736 
737     sfd->nfd = *fd;
738 
739     /* check integrity */
740     ret = (TEE_Result)check_integrity_v2(sfd);
741     if (ret != TEE_SUCCESS) {
742         if (ssa_fs_fclose(sfd->nfd) != 0)
743             tloge("close error %x\n", fs_get_serr());
744 
745         ret = TEE_ERROR_CORRUPT_OBJECT;
746         goto out;
747     }
748 
749     tlogd("intergerity check success in %s file\n", file_name);
750 
751 out:
752     return ret;
753 }
754 
ssa_open_init(struct sfd_t * sfd,meta_data_t * meta,uint32_t flag)755 static TEE_Result ssa_open_init(struct sfd_t *sfd, meta_data_t *meta, uint32_t flag)
756 {
757     tlogd("arch_version = %u\n", meta->arch_version);
758 
759     sfd->meta_data         = meta;
760     sfd->flags             = flag;
761     sfd->update_backup     = false;
762     sfd->seek_position     = 0;
763     sfd->size              = 0; /* we will update in 'checkIntegrity' */
764     sfd->crypto_block_size = meta->crypto_block_size;
765     sfd->attr_size         = 0;
766 
767     /* init block list */
768     sfd->first_block = TEE_Malloc(sizeof(struct block_info_t), 0);
769     if (sfd->first_block == NULL) {
770         tloge("malloc blockInfo failed\n");
771         return TEE_ERROR_OUT_OF_MEMORY;
772     }
773     sfd->first_block->block_id = SFS_START_BLOCKID;
774     sfd->first_block->next = NULL;
775 
776     return TEE_SUCCESS;
777 }
778 
ssa_open_handle_init(struct sfd_t * sfd,const meta_data_t * meta,uint32_t flag,struct ssa_open_info * orig,struct ssa_open_info * back)779 static void ssa_open_handle_init(struct sfd_t *sfd, const meta_data_t *meta, uint32_t flag,
780     struct ssa_open_info *orig, struct ssa_open_info *back)
781 {
782     back->ret = ssa_open_check(sfd, (char *)meta->cur_backup_file_id, flag, &(back->file_fd));
783     back->size = sfd->size;
784 
785     orig->ret = ssa_open_check(sfd, (char *)meta->cur_encrypted_file_id, flag, &(orig->file_fd));
786     orig->size = sfd->size;
787 }
788 
ssa_open_handle_orig(const meta_data_t * meta)789 static TEE_Result ssa_open_handle_orig(const meta_data_t *meta)
790 {
791     TEE_Result ret;
792 
793     /* orig is ok , and back is corrupt. */
794     if (ssa_fs_fcopy((char *)meta->cur_encrypted_file_id, (char *)meta->cur_backup_file_id, meta->storage_id)) {
795         ret = fs_get_serr();
796         tloge("Oops, copy origin file to backup file failed, 0x%x\n", ret);
797         return ret;
798     }
799 
800     return TEE_SUCCESS;
801 }
802 
ssa_open_handle_back(struct sfd_t * sfd,const meta_data_t * meta,uint32_t flag,struct ssa_open_info * orig,struct ssa_open_info * back)803 static TEE_Result ssa_open_handle_back(struct sfd_t *sfd, const meta_data_t *meta, uint32_t flag,
804     struct ssa_open_info *orig, struct ssa_open_info *back)
805 {
806     TEE_Result ret;
807 
808     if (ssa_fs_fcopy((char *)meta->cur_backup_file_id, (char *)meta->cur_encrypted_file_id, meta->storage_id)) {
809         ret = fs_get_serr();
810         tloge("Oops, copy backup file to origin file failed, 0x%x\n", ret);
811         return ret;
812     }
813 
814     if (ssa_fs_fclose(back->file_fd)) {
815         tloge("close error 0x%x\n", fs_get_serr());
816         ret = TEE_ERROR_GENERIC;
817         back->file_fd = 0;
818         return ret;
819     }
820     back->file_fd = 0;
821 
822     orig->ret = ssa_open_check(sfd, (char *)meta->cur_encrypted_file_id, flag, &(orig->file_fd));
823     if (orig->ret != TEE_SUCCESS) {
824         ret = fs_get_serr();
825         tloge("reopen the origin file failed, 0x%x\n", ret);
826         return ret;
827     }
828 
829     return TEE_SUCCESS;
830 }
831 
handle_orig_back(struct sfd_t * sfd,const meta_data_t * meta,uint32_t flag,struct ssa_open_info * orig,struct ssa_open_info * back)832 static TEE_Result handle_orig_back(struct sfd_t *sfd, const meta_data_t *meta, uint32_t flag,
833     struct ssa_open_info *orig, struct ssa_open_info *back)
834 {
835     TEE_Result ret;
836 
837     if (ssa_fs_fclose(back->file_fd)) {
838         tloge("close error 0x%x\n", fs_get_serr());
839         ret = TEE_ERROR_GENERIC;
840         back->file_fd = 0;
841         return ret;
842     }
843     back->file_fd = 0;
844 
845     if (back->size != orig->size) {
846         /* the backup file is right, copy back to orig. */
847         if (ssa_fs_fclose(orig->file_fd)) {
848             tloge("close error 0x%x\n", fs_get_serr());
849             ret = TEE_ERROR_GENERIC;
850             orig->file_fd = 0;
851             return ret;
852         }
853         orig->file_fd = 0;
854 
855         /* orig is ok , and back is corrupt. */
856         if (ssa_fs_fcopy((char *)meta->cur_backup_file_id, (char *)meta->cur_encrypted_file_id, meta->storage_id)) {
857             ret = fs_get_serr();
858             tloge("Oops, copy backup file to origin file failed, 0x%x\n", ret);
859             return ret;
860         }
861 
862         orig->ret = ssa_open_check(sfd, (char *)meta->cur_encrypted_file_id, flag, &(orig->file_fd));
863         if (orig->ret != TEE_SUCCESS) {
864             ret = fs_get_serr();
865             tloge("reopen the origin file failed, 0x%x\n", ret);
866             return ret;
867         }
868     }
869 
870     return TEE_SUCCESS;
871 }
872 
ssa_open_handle_clean_fd(struct ssa_open_info * orig,struct ssa_open_info * back)873 static void ssa_open_handle_clean_fd(struct ssa_open_info *orig, struct ssa_open_info *back)
874 {
875     if (back->file_fd > 0) {
876         if (ssa_fs_fclose(back->file_fd) != 0)
877             tloge("close error 0x%x\n", fs_get_serr());
878 
879         back->file_fd = 0;
880     }
881 
882     if (orig->file_fd > 0) {
883         if (ssa_fs_fclose(orig->file_fd) != 0)
884             tloge("close error 0x%x\n", fs_get_serr());
885 
886         orig->file_fd = 0;
887     }
888 }
889 
ssa_open_handle_retry(struct sfd_t * sfd,const meta_data_t * meta,uint32_t flag,struct ssa_open_info * back)890 static TEE_Result ssa_open_handle_retry(struct sfd_t *sfd, const meta_data_t *meta,
891     uint32_t flag, struct ssa_open_info *back)
892 {
893     TEE_Result ret;
894     tlogi("we will try to reopen the file when open file without write\n");
895     if (back->ret == TEE_SUCCESS)
896         ret = ssa_open_check(sfd, (char *)meta->cur_backup_file_id, flag, &(back->file_fd));
897     else
898         ret = ssa_open_check(sfd, (char *)meta->cur_encrypted_file_id, flag, &(back->file_fd));
899     if (ret != TEE_SUCCESS)
900         return fs_get_serr();
901 
902     if (ssa_fs_fseek(sfd->nfd, (int32_t)SFS_METADATA_SIZE, TEE_DATA_SEEK_SET)) {
903         tloge("seek error 0x%x\n", fs_get_serr());
904         if (back->file_fd > 0 && ssa_fs_fclose(back->file_fd) != 0) {
905             tloge("close error 0x%x\n", fs_get_serr());
906             back->file_fd = 0;
907         }
908         return fs_get_serr();
909     }
910 
911     return TEE_SUCCESS;
912 }
913 
ssa_open_handle(struct sfd_t * sfd,const meta_data_t * meta,uint32_t flag)914 static TEE_Result ssa_open_handle(struct sfd_t *sfd, const meta_data_t *meta, uint32_t flag)
915 {
916     TEE_Result ret;
917     struct ssa_open_info orig = {0};
918     struct ssa_open_info back = {0};
919 
920     ssa_open_handle_init(sfd, meta, flag, &orig, &back);
921     if (back.ret != TEE_SUCCESS && orig.ret != TEE_SUCCESS) {
922         /* all are corrupt */
923         if (back.ret == TEE_ERROR_ITEM_NOT_FOUND && orig.ret == TEE_ERROR_ITEM_NOT_FOUND) {
924             ret = TEE_ERROR_ITEM_NOT_FOUND;
925         } else {
926             ret = TEE_ERROR_GENERIC;
927         }
928 
929         goto out;
930     }
931 
932     if (back.ret != TEE_SUCCESS) {
933         tloge("backup file open error 0x%x\n", back.ret);
934         ret = ssa_open_handle_orig(meta);
935         if (ret != TEE_SUCCESS) {
936             tloge("ssa open handle orig failed, 0x%x\n", ret);
937             goto out;
938         }
939     } else if (orig.ret != TEE_SUCCESS) {
940         tloge("origin file open error 0x%x\n", orig.ret);
941         ret = ssa_open_handle_back(sfd, meta, flag, &orig, &back);
942         if (ret != TEE_SUCCESS) {
943             tloge("ssa open handle back failed, 0x%x\n", ret);
944             goto out;
945         }
946     } else {
947         /* orig and back all are correct . */
948         tlogd("orig and back file are all check ok %s\n", (char *)meta->cur_encrypted_file_id);
949         ret = handle_orig_back(sfd, meta, flag, &orig, &back);
950         if (ret != TEE_SUCCESS) {
951             tloge("ssa open handle orig back failed, 0x%x\n", ret);
952             goto out;
953         }
954     }
955 
956     /* we should skip the metadata */
957     if (ssa_fs_fseek(sfd->nfd, (int32_t)SFS_METADATA_SIZE, TEE_DATA_SEEK_SET)) {
958         tloge("seek error 0x%x\n", fs_get_serr());
959         ret = TEE_ERROR_GENERIC;
960         goto out;
961     }
962 
963     return TEE_SUCCESS;
964 
965 out:
966     ssa_open_handle_clean_fd(&orig, &back);
967     if ((back.ret == TEE_SUCCESS || orig.ret == TEE_SUCCESS) &&
968         !((TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_ACCESS_WRITE_META | TEE_DATA_FLAG_SHARE_WRITE |
969            TEE_DATA_FLAG_CREATE | TEE_DATA_FLAG_OVERWRITE) & flag))
970         return ssa_open_handle_retry(sfd, meta, flag, &back);
971 
972     return ret;
973 }
974 
ssa_open(meta_data_t * meta,uint32_t flag,TEE_Result * error)975 struct sfd_t *ssa_open(meta_data_t *meta, uint32_t flag, TEE_Result *error)
976 {
977     struct sfd_t *sfd = NULL;
978 
979     if (meta == NULL || error == NULL) {
980         if (error)
981             *error = TEE_ERROR_BAD_PARAMETERS;
982         return NULL;
983     }
984 
985     /* init file handle */
986     sfd = TEE_Malloc(sizeof(struct sfd_t), 0);
987     if (sfd == NULL) {
988         tloge("malloc sfd failed\n");
989         *error = TEE_ERROR_OUT_OF_MEMORY;
990         return NULL;
991     }
992 
993     *error = ssa_open_init(sfd, meta, flag);
994     if (*error != TEE_SUCCESS) {
995         tloge("ssa open init failed");
996         goto out_final;
997     }
998 
999     *error = ssa_open_handle(sfd, meta, flag);
1000     if (*error != TEE_SUCCESS) {
1001         tloge("ssa open handle failed, ret = 0x%x\n", *error);
1002         goto out_final;
1003     }
1004 
1005     return sfd;
1006 
1007 out_final:
1008     free_sfd(sfd);
1009 
1010     return NULL;
1011 }
1012 
ssa_close(struct sfd_t * sfd)1013 TEE_Result ssa_close(struct sfd_t *sfd)
1014 {
1015     if (sfd == NULL) {
1016         tloge("ssa close Illegal sfd\n");
1017         return TEE_ERROR_BAD_PARAMETERS;
1018     }
1019     (void)ssa_fs_fclose(sfd->nfd);
1020 
1021     bool copy_flag = sfd->update_backup && (sfd->meta_data != NULL) &&
1022         (sfd->meta_data->cur_encrypted_file_id != NULL) && (sfd->meta_data->cur_backup_file_id != NULL);
1023     if (copy_flag) { /* Update the backup file */
1024         tlogd("file has been written successfully, need to update the backup file\n");
1025         if (ssa_fs_fcopy((char *)sfd->meta_data->cur_encrypted_file_id,
1026             (char *)sfd->meta_data->cur_backup_file_id, sfd->meta_data->storage_id) != 0)
1027             tloge("copy file failed, %x\n", fs_get_serr());
1028     }
1029 
1030     free_sfd(sfd);
1031     return TEE_SUCCESS;
1032 }
1033 
ssa_sync(const struct sfd_t * sfd)1034 TEE_Result ssa_sync(const struct sfd_t *sfd)
1035 {
1036     if (sfd == NULL) {
1037         tloge("ssa sync Illegal sfd\n");
1038         return TEE_ERROR_BAD_PARAMETERS;
1039     }
1040     if (ssa_fs_fsync(sfd->nfd))
1041         return fs_get_serr();
1042 
1043     return TEE_SUCCESS;
1044 }
1045 
handle_truncation(struct sfd_t * sfd,uint8_t * buffer,uint32_t end_offset,uint32_t head_blocks)1046 static TEE_Result handle_truncation(struct sfd_t *sfd, uint8_t *buffer,
1047     uint32_t end_offset, uint32_t head_blocks)
1048 {
1049     TEE_Result ret;
1050     errno_t rc;
1051     uint32_t read_ret;
1052 
1053     if (sfd->crypto_block_size * head_blocks > INT32_MAX) {
1054         tloge("Invalid size, more than INT32_MAX");
1055         return TEE_ERROR_BAD_PARAMETERS;
1056     }
1057     ret = ssa_seek(sfd, (int32_t)(sfd->crypto_block_size * head_blocks), TEE_DATA_SEEK_SET);
1058     if (ret != TEE_SUCCESS) {
1059         tloge("seek to %u failed 0x%x\n", sfd->crypto_block_size * head_blocks, ret);
1060         return ret;
1061     }
1062 
1063     rc = memset_s(buffer, BLOCK_SIZE, 0, BLOCK_SIZE);
1064     if (rc != EOK)
1065         tloge("memset failed, 0x%x\n", rc);
1066 
1067     ret = TEE_SUCCESS;
1068     read_ret = ssa_read(buffer, end_offset, sfd, &ret);
1069     if ((read_ret < end_offset) || (ret != TEE_SUCCESS)) {
1070         tloge("read failed %u 0x%x\n", read_ret, ret);
1071         return ret;
1072     }
1073 
1074     if (check_ssa_version_type(sfd)) {
1075         if (ssa_fs_ftruncate((char *)sfd->meta_data->cur_encrypted_file_id,
1076                              sfd->crypto_block_size * head_blocks + SFS_METADATA_SIZE,
1077                              sfd->meta_data->storage_id)) {
1078             tloge("truncate file failed\n");
1079             return get_spec_errno(TEE_ERROR_TRUNCATE_OBJECT);
1080         }
1081         sfd->last_block_size = 0;
1082     } else {
1083         tloge("invalid file format, version=%u\n", sfd->meta_data->arch_version);
1084         return TEE_ERROR_BAD_FORMAT;
1085     }
1086 
1087     return TEE_SUCCESS;
1088 }
1089 
handle_supplement(struct sfd_t * sfd,uint8_t * buffer,uint32_t head_blocks,uint32_t append_size)1090 static TEE_Result handle_supplement(struct sfd_t *sfd, uint8_t *buffer,
1091     uint32_t head_blocks, uint32_t append_size)
1092 {
1093     TEE_Result ret;
1094     errno_t rc;
1095     uint32_t write_count;
1096 
1097     if (sfd->crypto_block_size * head_blocks > INT32_MAX) {
1098         tloge("Invalid size, more than INT32_MAX");
1099         return TEE_ERROR_BAD_PARAMETERS;
1100     }
1101     ret = ssa_seek(sfd, (int32_t)(sfd->crypto_block_size * head_blocks), TEE_DATA_SEEK_SET);
1102     if (ret != TEE_SUCCESS) {
1103         tloge("seek to %u failed\n", sfd->crypto_block_size * head_blocks);
1104         return ret;
1105     }
1106 
1107     if (append_size == 0) {
1108         sfd->need_update_hmac = true;
1109         return TEE_SUCCESS;
1110     }
1111 
1112     if (append_size > BLOCK_SIZE) {
1113         ret = TEE_SUCCESS;
1114         write_count = ssa_write(buffer, BLOCK_SIZE, sfd, &ret);
1115         if ((write_count != BLOCK_SIZE) || (ret != TEE_SUCCESS))
1116             return ret;
1117         append_size -= BLOCK_SIZE;
1118         rc = memset_s(buffer, BLOCK_SIZE, 0, BLOCK_SIZE);
1119         if (rc != EOK)
1120             tlogw("memset failed, 0x%x\n", rc);
1121 
1122         while (append_size > BLOCK_SIZE) {
1123             ret = TEE_SUCCESS;
1124             write_count = ssa_write(buffer, BLOCK_SIZE, sfd, &ret);
1125             if ((write_count != BLOCK_SIZE) || (ret != TEE_SUCCESS))
1126                 return ret;
1127             append_size -= BLOCK_SIZE;
1128         }
1129     }
1130 
1131     if (append_size > 0) {
1132         ret = TEE_SUCCESS;
1133         write_count = ssa_write(buffer, append_size, sfd, &ret);
1134         if ((write_count != append_size) || (ret != TEE_SUCCESS))
1135             return ret;
1136     }
1137 
1138     return TEE_SUCCESS;
1139 }
handle_truncation_supplement(struct sfd_t * sfd,uint32_t end_offset,uint32_t head_blocks,uint32_t append_size)1140 static TEE_Result handle_truncation_supplement(struct sfd_t *sfd,
1141     uint32_t end_offset, uint32_t head_blocks, uint32_t append_size)
1142 {
1143     uint8_t *buffer = NULL;
1144     TEE_Result ret;
1145 
1146     /* malloc for s_fread */
1147     buffer = TEE_Malloc(BLOCK_SIZE, 0);
1148     if (buffer == NULL) {
1149         tloge("malloc buffer failed\n");
1150         return TEE_ERROR_OUT_OF_MEMORY;
1151     }
1152 
1153     ret = handle_truncation(sfd, buffer, end_offset, head_blocks);
1154     if (ret != TEE_SUCCESS) {
1155         tloge("ssa truncate handle truncation failed, ret = 0x%x\n", ret);
1156         goto error_handle;
1157     }
1158 
1159     ret = handle_supplement(sfd, buffer, head_blocks, append_size);
1160     if (ret != TEE_SUCCESS) {
1161         tloge("ssa truncate handle supplement failed, ret = 0x%x\n", ret);
1162         goto error_handle;
1163     }
1164 
1165 error_handle:
1166     if (buffer != NULL)
1167         TEE_Free(buffer);
1168     return ret;
1169 }
1170 
ssa_truncate_handle(struct sfd_t * sfd,uint32_t len,uint32_t file_len)1171 static TEE_Result ssa_truncate_handle(struct sfd_t *sfd, uint32_t len, uint32_t file_len)
1172 {
1173     uint32_t end_offset, head_blocks, append_size;
1174 
1175     if (len > file_len) {
1176         end_offset  = file_len % sfd->crypto_block_size;
1177         head_blocks = file_len / sfd->crypto_block_size;
1178         append_size = len - file_len + end_offset;
1179         return handle_truncation_supplement(sfd, end_offset, head_blocks, append_size);
1180     }
1181 
1182     end_offset  = len % sfd->crypto_block_size;
1183     head_blocks = len / sfd->crypto_block_size;
1184     append_size = end_offset;
1185     if (judge_valid_version(sfd)) {
1186         struct block_info_t *head = sfd->first_block;
1187         struct block_info_t *p = NULL;
1188         struct block_info_t *pre = NULL;
1189         bool found = false;
1190 
1191         while (head->next) {
1192             if (head->block_id == head_blocks) {
1193                 found = true;
1194                 break;
1195             }
1196             pre = head;
1197             head = head->next;
1198         }
1199         if (found) {
1200             while (head->next) {
1201                 p          = head->next;
1202                 head->next = p->next;
1203                 TEE_Free(p);
1204             }
1205         }
1206         if (append_size == 0 && pre != NULL) { /* It means the last block is useless */
1207             TEE_Free(head);
1208             pre->next = NULL;
1209         }
1210     }
1211 
1212     return handle_truncation_supplement(sfd, end_offset, head_blocks, append_size);
1213 }
1214 
ssa_truncate(struct sfd_t * sfd,uint32_t len)1215 TEE_Result ssa_truncate(struct sfd_t *sfd, uint32_t len)
1216 {
1217     uint32_t cur_pos = 0;
1218     uint32_t file_len = 0;
1219     TEE_Result ret;
1220 
1221     if (sfd == NULL || sfd->meta_data == NULL) {
1222         tloge("ssa truncate Illegal sfd\n");
1223         return TEE_ERROR_BAD_PARAMETERS;
1224     }
1225 
1226     ret = ssa_info(sfd, &cur_pos, &file_len);
1227     if (ret != TEE_SUCCESS) {
1228         tloge("get file info error 0x%x\n", ret);
1229         return ret;
1230     }
1231     tlogd("file size=%u, new_size=%u, pos=%u\n", file_len, len, cur_pos);
1232 
1233     if (len == file_len)
1234         return TEE_SUCCESS;
1235 
1236     ret = ssa_truncate_handle(sfd, len, file_len);
1237     if (ret != TEE_SUCCESS) {
1238         tloge("ssa truncate handle failed, ret = 0x%x\n", ret);
1239         return ret;
1240     }
1241     if (cur_pos > INT32_MAX) {
1242         tloge("Invalid position, more than INT32_MAX");
1243         return TEE_ERROR_BAD_PARAMETERS;
1244     }
1245     ret = ssa_seek(sfd, (int32_t)cur_pos, TEE_DATA_SEEK_SET);
1246     if (ret != TEE_SUCCESS)
1247         return ret;
1248 
1249     sfd->seek_position = cur_pos;
1250     sfd->size          = len;
1251 
1252     return TEE_SUCCESS;
1253 }
1254 
do_rename(struct sfd_t * sfd,meta_data_t * new_meta_data)1255 TEE_Result do_rename(struct sfd_t *sfd, meta_data_t *new_meta_data)
1256 {
1257     TEE_Result ret;
1258 
1259     if (ssa_fs_faccess((char *)new_meta_data->encrypted_file_id, F_OK, sfd->meta_data->storage_id) == 0) {
1260         tloge("file already exist\n");
1261         return TEE_ERROR_ACCESS_CONFLICT;
1262     }
1263     if (ssa_fs_faccess((char *)new_meta_data->backup_file_id, F_OK, sfd->meta_data->storage_id) == 0) {
1264         tloge("backup file already exist\n");
1265         return TEE_ERROR_ACCESS_CONFLICT;
1266     }
1267 
1268     if (ssa_fs_faccess((char *)sfd->meta_data->backup_file_id, F_OK, sfd->meta_data->storage_id) == 0) {
1269         if (ssa_fs_frename((char *)sfd->meta_data->backup_file_id, (char *)new_meta_data->backup_file_id,
1270                            sfd->meta_data->storage_id) != 0) {
1271             tloge("rename backup file fail\n");
1272             return get_spec_errno(TEE_ERROR_GENERIC);
1273         }
1274     }
1275 
1276     if (ssa_fs_frename((char *)sfd->meta_data->encrypted_file_id, (char *)new_meta_data->encrypted_file_id,
1277                        sfd->meta_data->storage_id) != 0) {
1278         tloge("rename file fail\n");
1279         ret = get_spec_errno(TEE_ERROR_GENERIC);
1280         (void)ssa_fs_frename((char *)new_meta_data->backup_file_id, (char *)sfd->meta_data->backup_file_id,
1281             sfd->meta_data->storage_id); /* no need to verify return value here */
1282         return ret;
1283     }
1284 
1285     return TEE_SUCCESS;
1286 }
1287 
ssa_rename(struct sfd_t * sfd,const uint8_t * new_obj_id,uint32_t new_obj_len)1288 TEE_Result ssa_rename(struct sfd_t *sfd, const uint8_t *new_obj_id, uint32_t new_obj_len)
1289 {
1290     meta_data_t *new_meta_data = NULL;
1291     TEE_Result ret             = TEE_SUCCESS;
1292 
1293     if (sfd == NULL || new_obj_id == NULL || sfd->meta_data == NULL) {
1294         tloge("ssa rename Bad parameters!\n");
1295         return TEE_ERROR_BAD_PARAMETERS;
1296     }
1297 
1298     new_meta_data = create_meta_data(new_obj_id, new_obj_len, sfd->meta_data->storage_id, sfd->flags,
1299                                      &sfd->meta_data->uuid, &ret, sfd->meta_data->arch_version);
1300     if ((new_meta_data == NULL) || (ret != TEE_SUCCESS)) {
1301         tloge("meta create fail %x\n", ret);
1302         goto clean;
1303     }
1304 
1305     ret = switch_arch_version_rename(sfd, new_obj_id, new_obj_len, new_meta_data);
1306     if (ret != TEE_SUCCESS)
1307         goto clean;
1308 
1309     tlogd("rename file success\n");
1310     free_meta_data(&sfd->meta_data);
1311     sfd->meta_data = new_meta_data;
1312     return TEE_SUCCESS;
1313 
1314 clean:
1315     if (new_meta_data != NULL)
1316         free_meta_data(&new_meta_data);
1317     return ret;
1318 }
1319 
ssa_file_sfd_params(uint32_t flag,int32_t nfd,meta_data_t * meta,struct sfd_t * sfd)1320 static TEE_Result ssa_file_sfd_params(uint32_t flag, int32_t nfd, meta_data_t *meta, struct sfd_t *sfd)
1321 {
1322     TEE_Result ret;
1323     uint8_t empty_buff[1] = { 0 };
1324 
1325     sfd->seek_position     = 0;
1326     sfd->size              = 0;
1327     sfd->attr_size         = 0;
1328     sfd->nfd               = nfd;
1329     sfd->flags             = flag;
1330     sfd->update_backup     = true;
1331     sfd->opened_orig       = true;
1332     sfd->meta_data         = meta;
1333     sfd->crypto_block_size = meta->crypto_block_size;
1334 
1335     /* init the block list */
1336     sfd->first_block = TEE_Malloc(sizeof(struct block_info_t), 0);
1337     if (sfd->first_block == NULL) {
1338         tloge("malloc blockInfo failed\n");
1339         return TEE_ERROR_OUT_OF_MEMORY;
1340     }
1341 
1342     sfd->first_block->next    = NULL;
1343     sfd->first_block->block_id = SFS_START_BLOCKID;
1344     ret = calculate_block_hash(sfd->first_block->hash, sizeof(sfd->first_block->hash), empty_buff,
1345                                sizeof(empty_buff) / sizeof(uint8_t));
1346     if (ret != TEE_SUCCESS) {
1347         tloge("calculate first block hash failed 0x%x\n", ret);
1348         TEE_Free(sfd->first_block);
1349         sfd->first_block = NULL;
1350         return ret;
1351     }
1352 
1353     /* write metadata */
1354     ret = init_meta_data(sfd);
1355     if (ret != TEE_SUCCESS) {
1356         tloge("write metadata failed, 0x%x\n", ret);
1357         TEE_Free(sfd->first_block);
1358         sfd->first_block = NULL;
1359         return ret;
1360     }
1361 
1362     tlogd("write metadata success\n");
1363     return TEE_SUCCESS;
1364 }
1365 
ssa_create(meta_data_t * meta,uint32_t flag,TEE_Result * error)1366 struct sfd_t *ssa_create(meta_data_t *meta, uint32_t flag, TEE_Result *error)
1367 {
1368     TEE_Result ret;
1369     struct sfd_t *sfd = NULL;
1370 
1371     if (error == NULL) {
1372         tloge("Bad parameters!\n");
1373         return NULL;
1374     }
1375     if (meta == NULL || meta->file_id == NULL) {
1376         *error = get_spec_errno(TEE_ERROR_BAD_PARAMETERS);
1377         return NULL;
1378     }
1379 
1380     /* create data file */
1381     int32_t nfd = ssa_fs_fcreate((char *)meta->cur_encrypted_file_id, flag, meta->storage_id);
1382     if (nfd < 0) {
1383         tloge("create data file failed %x\n", nfd);
1384         *error = get_spec_errno(TEE_ERROR_GENERIC);
1385         goto fail;
1386     }
1387 
1388     /* init file handle */
1389     sfd = TEE_Malloc(sizeof(struct sfd_t), 0);
1390     if (sfd == NULL) {
1391         tloge("malloc sfd failed\n");
1392         *error = TEE_ERROR_OUT_OF_MEMORY;
1393         goto alloc_sfd_fail;
1394     }
1395 
1396     ret = ssa_file_sfd_params(flag, nfd, meta, sfd);
1397     if (ret != TEE_SUCCESS) {
1398         *error = ret;
1399         goto init_fail;
1400     }
1401 
1402     return sfd;
1403 
1404 init_fail:
1405     free_sfd(sfd);
1406     sfd = NULL;
1407 alloc_sfd_fail:
1408     (void)ssa_fs_fclose(nfd);
1409     (void)ssa_fs_fremove((char *)meta->cur_encrypted_file_id, meta->storage_id);
1410 fail:
1411     return NULL;
1412 }
1413 
1414 typedef struct {
1415     int32_t offset;
1416     uint32_t cur_pos;
1417     uint32_t cur_file_len;
1418 } ssa_seek_param;
proc_seek_set(const struct sfd_t * sfd,ssa_seek_param * seek_param)1419 static TEE_Result proc_seek_set(const struct sfd_t *sfd, ssa_seek_param *seek_param)
1420 {
1421     if (seek_param->offset < 0) {
1422         tloge("Illegal offset %d, file_len %u attrsize %u \n", seek_param->offset, seek_param->cur_file_len,
1423               sfd->attr_size);
1424         return TEE_ERROR_BAD_PARAMETERS;
1425     }
1426     if (judge_valid_version(sfd))
1427         seek_param->offset += (int32_t)SFS_METADATA_SIZE;
1428 
1429     return TEE_SUCCESS;
1430 }
proc_seek_cur(const struct sfd_t * sfd,ssa_seek_param * seek_param)1431 static TEE_Result proc_seek_cur(const struct sfd_t *sfd, ssa_seek_param *seek_param)
1432 {
1433     if (seek_param->offset < 0) {
1434         if ((seek_param->offset + (int32_t)(seek_param->cur_pos)) < (int32_t)(sfd->attr_size))
1435             seek_param->offset = sfd->attr_size - seek_param->cur_pos;
1436         return TEE_SUCCESS;
1437     }
1438 
1439     if ((seek_param->cur_pos + seek_param->offset) > (MAX_FILE_SIZE + sfd->attr_size)) {
1440         tloge("The data position has overflowed, cur_pos=%u, offset=%d\n", seek_param->cur_pos, seek_param->offset);
1441         return TEE_ERROR_OVERFLOW;
1442     }
1443 
1444     return TEE_SUCCESS;
1445 }
1446 
proc_seek_end(const struct sfd_t * sfd,ssa_seek_param * seek_param)1447 static TEE_Result proc_seek_end(const struct sfd_t *sfd, ssa_seek_param *seek_param)
1448 {
1449     if ((seek_param->offset > 0) &&
1450         ((seek_param->cur_file_len + (uint32_t)seek_param->offset) > (MAX_FILE_SIZE + sfd->attr_size))) {
1451         tloge("The data position has overflowed, file_real_len=%u, offset=%d\n", seek_param->cur_file_len,
1452               seek_param->offset);
1453         return TEE_ERROR_OVERFLOW;
1454     }
1455 
1456     if ((seek_param->offset + (int32_t)(seek_param->cur_file_len)) < (int32_t)(sfd->attr_size))
1457         seek_param->offset = sfd->attr_size - seek_param->cur_file_len;
1458 
1459     int32_t last_block_padding_size = get_last_crypt_block_padding_size(sfd);
1460     if (last_block_padding_size < 0) {
1461         tloge("get last block padding size failed 0x%x\n", last_block_padding_size);
1462         return TEE_ERROR_GENERIC;
1463     }
1464     seek_param->offset -= last_block_padding_size;
1465 
1466     return TEE_SUCCESS;
1467 }
1468 
1469 typedef TEE_Result (*seek_proc_call_back)(const struct sfd_t *sfd, ssa_seek_param *seek_param);
1470 typedef struct {
1471     uint32_t whence;
1472     seek_proc_call_back seek_proc_func;
1473 } seek_proc;
1474 
1475 static seek_proc g_ssa_seek_proc[] = { { TEE_DATA_SEEK_SET, proc_seek_set },
1476                                        { TEE_DATA_SEEK_CUR, proc_seek_cur },
1477                                        { TEE_DATA_SEEK_END, proc_seek_end } };
1478 
ssa_seek(struct sfd_t * sfd,int32_t offset,uint32_t whence)1479 TEE_Result ssa_seek(struct sfd_t *sfd, int32_t offset, uint32_t whence)
1480 {
1481     TEE_Result ret;
1482     uint32_t cur_pos          = 0;
1483     uint32_t file_len         = 0;
1484     uint32_t file_real_len    = 0;
1485     ssa_seek_param seek_param = { 0 };
1486 
1487     if ((sfd == NULL) || (sfd->meta_data == NULL)) {
1488         tloge("ssa seek Illegal sfd\n");
1489         return TEE_ERROR_BAD_PARAMETERS;
1490     }
1491 
1492     ret = ssa_info(sfd, &cur_pos, &file_real_len);
1493     if (ret != TEE_SUCCESS) {
1494         tloge("get file info error, 0x%x\n", ret);
1495         return ret;
1496     }
1497 
1498     tlogd("before seek, pos=%u, size=%u\n", cur_pos, file_real_len);
1499 
1500     if (whence > TEE_DATA_SEEK_END)
1501         return TEE_ERROR_BAD_STATE;
1502 
1503     seek_param.offset       = offset;
1504     seek_param.cur_pos      = cur_pos;
1505     seek_param.cur_file_len = file_real_len;
1506     ret                     = g_ssa_seek_proc[whence].seek_proc_func((const struct sfd_t *)sfd, &seek_param);
1507     if (ret != TEE_SUCCESS) {
1508         tloge("ssa seek proc error, 0x%x\n", ret);
1509         return ret;
1510     }
1511 
1512     tlogd("offset=%d, whence=%u\n", seek_param.offset, whence);
1513 
1514     int32_t rc = ssa_fs_fseek(sfd->nfd, seek_param.offset, whence);
1515     if (rc != 0) {
1516         tloge("fseek failed: offset=%d, whence=%u\n", seek_param.offset, whence);
1517         return get_spec_errno(TEE_ERROR_SEEK_DATA);
1518     }
1519 
1520     ret = ssa_info(sfd, &cur_pos, &file_len);
1521     if (ret != TEE_SUCCESS) {
1522         tloge("get file info error 0x%x\n", ret);
1523         return ret;
1524     }
1525     tlogd("after seek, pos=%u, size=%u\n", cur_pos, file_len);
1526     sfd->seek_position = cur_pos;
1527     sfd->size          = file_len;
1528 
1529     if (cur_pos > file_real_len)
1530         return fill_file_hole(sfd, file_real_len, cur_pos - file_real_len);
1531 
1532     return TEE_SUCCESS;
1533 }
1534 
ssa_info(struct sfd_t * sfd,uint32_t * pos,uint32_t * len)1535 TEE_Result ssa_info(struct sfd_t *sfd, uint32_t *pos, uint32_t *len)
1536 {
1537     int32_t last_block_padding_size;
1538 
1539     if (sfd == NULL || sfd->meta_data == NULL || pos == NULL || len == NULL) {
1540         tloge("ssa info Illegal sfd\n");
1541         return TEE_ERROR_BAD_PARAMETERS;
1542     }
1543 
1544     /* get cur_pos and file_len */
1545     if (ssa_fs_finfo(sfd->nfd, pos, len)) {
1546         tloge("get file info error\n");
1547         return get_spec_errno(TEE_ERROR_GENERIC);
1548     }
1549     tlogd("file info : pos/len = %u/%u\n", *pos, *len);
1550 
1551     /* remove the meta_data size */
1552 
1553     if (judge_valid_version(sfd)) {
1554         (*pos) = (*pos) > SFS_METADATA_SIZE ? ((*pos) - SFS_METADATA_SIZE) : 0;
1555         (*len) = (*len) > SFS_METADATA_SIZE ? ((*len) - SFS_METADATA_SIZE) : 0;
1556     }
1557 
1558     last_block_padding_size = get_last_crypt_block_padding_size((const struct sfd_t *)sfd);
1559     if (last_block_padding_size < 0) {
1560         tloge("get last block padding size failed %x\n", last_block_padding_size);
1561         return get_spec_errno(TEE_ERROR_GENERIC);
1562     }
1563     tlogd("last_block_padding_size=%d\n", last_block_padding_size);
1564 
1565     if ((int32_t)*len < last_block_padding_size) {
1566         tlogw("last write operation may be interrupted %u\n", *len);
1567         *len = 0;
1568     } else {
1569         *len -= (uint32_t)last_block_padding_size;
1570     }
1571     sfd->seek_position = *pos;
1572     sfd->size          = *len;
1573 
1574     return TEE_SUCCESS;
1575 }
1576