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