• 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_crypto_api.h"
15 #include "tee_mem_mgmt_api.h"
16 #include "tee_log.h"
17 #include "ta_framework.h"
18 #include "tee_ext_api.h"
19 #include "sfs_internal.h"
20 #include "securec.h"
21 #include "string.h"
22 #include "ssa_fs.h"
23 #include "ssa_fs.h"
24 struct crypto_key {
25     bool flag;
26     uint8_t key[CRYPT_KEY_SIZE];
27 };
28 
29 static struct crypto_key g_gs_key_hash = { false, { 0 } };
30 
check_invalid_version(const struct sfd_t * sfd)31 static bool check_invalid_version(const struct sfd_t *sfd)
32 {
33     return (sfd->meta_data->arch_version != SFS_ARCH_VERSION_SSA);
34 }
35 
judge_valid_version(const struct sfd_t * sfd)36 static bool judge_valid_version(const struct sfd_t *sfd)
37 {
38     (void)sfd;
39     return true;
40 }
41 
get_encrypted_file_name(uint8_t ** encrypted_file_name,const struct sfd_t * sfd)42 static int32_t get_encrypted_file_name(uint8_t **encrypted_file_name, const struct sfd_t *sfd)
43 {
44     switch (sfd->meta_data->arch_version) {
45     case SFS_ARCH_VERSION_SSA:
46         *encrypted_file_name = sfd->meta_data->cur_encrypted_file_id;
47         break;
48     default:
49         tloge("Invalid arch_version, %x\n", sfd->meta_data->arch_version);
50         return -1;
51     }
52     return 0;
53 }
54 
ssa_fs_fseek_blk_start(const struct sfd_t * sfd,uint32_t start_pos)55 static TEE_Result ssa_fs_fseek_blk_start(const struct sfd_t *sfd, uint32_t start_pos)
56 {
57     TEE_Result ret;
58 
59     ret = (TEE_Result)ssa_fs_fseek(sfd->nfd, start_pos + SFS_METADATA_SIZE, TEE_DATA_SEEK_SET);
60     if (ret != TEE_SUCCESS) { /* if error, no need to update hash file */
61         tloge("seek file to start offset failed\n");
62         return get_spec_errno(TEE_ERROR_SEEK_DATA);
63     }
64 
65     return TEE_SUCCESS;
66 }
67 
ssa_fs_fseek_blk_end(const struct sfd_t * sfd,uint32_t end_pos,uint32_t end_offset)68 static TEE_Result ssa_fs_fseek_blk_end(const struct sfd_t *sfd, uint32_t end_pos, uint32_t end_offset)
69 {
70     TEE_Result ret;
71 
72     ret = (TEE_Result)ssa_fs_fseek(sfd->nfd, end_pos - end_offset + SFS_METADATA_SIZE, TEE_DATA_SEEK_SET);
73     if (ret != TEE_SUCCESS) {
74         tloge("seek file to end offset failed\n");
75         return get_spec_errno(TEE_ERROR_SEEK_DATA);
76     }
77 
78     return TEE_SUCCESS;
79 }
80 
81 // encrypt or decrypt many blocks
encrypt_blocks(const uint8_t * src,uint32_t len,uint8_t * dst,const struct sfd_t * sfd,uint32_t mode)82 static TEE_Result encrypt_blocks(const uint8_t *src, uint32_t len, uint8_t *dst, const struct sfd_t *sfd, uint32_t mode)
83 {
84     TEE_Result ret;
85     if (src == NULL || dst == NULL || sfd == NULL || sfd->meta_data == NULL)
86         return TEE_ERROR_BAD_PARAMETERS;
87 
88     tlogd("ready to %s, dataLen=%u, version=%u, bs=%u, block_id=%u\n", mode == TEE_MODE_ENCRYPT ? "encrypt" : "decrypt",
89           len, sfd->meta_data->arch_version, sfd->crypto_block_size, sfd->start_block_id);
90 
91     switch (sfd->meta_data->arch_version) {
92     case SFS_ARCH_VERSION_SSA:
93         ret = encrypt_blocks_with_xts(src, len, dst, sfd, mode);
94         break;
95     default:
96         ret = TEE_ERROR_BAD_STATE;
97         break; // never
98     }
99 
100     return ret;
101 }
102 
write_hmac_to_meta_data(const struct sfd_t * sfd,const uint8_t * hmac_buf,uint32_t buf_len)103 static int32_t write_hmac_to_meta_data(const struct sfd_t *sfd, const uint8_t *hmac_buf, uint32_t buf_len)
104 {
105     uint32_t write_ret;
106     int32_t ret;
107 
108     if (sfd == NULL || hmac_buf == NULL || sfd->meta_data == NULL)
109         return -1;
110 
111     /* we canot use nfd in sfd directly, otherwise file offset has changed */
112     if (check_invalid_version(sfd)) {
113         tloge("invalid arch version to write hmac 0x%x\n", sfd->meta_data->arch_version);
114         return -1;
115     }
116 
117     int32_t nfd = ssa_fs_fopen((char *)sfd->meta_data->cur_encrypted_file_id, TEE_DATA_FLAG_ACCESS_WRITE,
118                                sfd->meta_data->storage_id);
119     if (nfd < 0) {
120         tloge("open file %s failed\n", sfd->meta_data->cur_encrypted_file_id);
121         return -1;
122     }
123 
124     ret = ssa_fs_fseek(nfd, SFS_DATAHMAC_OFFSET, TEE_DATA_SEEK_SET);
125     if (ret < 0) {
126         tloge("seek file %s failed\n", sfd->meta_data->cur_encrypted_file_id);
127         (void)ssa_fs_fclose(nfd);
128         return -1;
129     }
130 
131     write_ret = ssa_fs_fwrite(hmac_buf, buf_len, nfd);
132     if (write_ret != buf_len) {
133         tloge("write data hmac to metadata failed, ret=%u\n", write_ret);
134         (void)ssa_fs_fclose(nfd);
135         return -1;
136     }
137 
138     (void)ssa_fs_fclose(nfd);
139     return 0;
140 }
141 
update_master_hmac(struct sfd_t * sfd)142 static TEE_Result update_master_hmac(struct sfd_t *sfd)
143 {
144     uint8_t hmac_buf[HASH_LEN]            = { 0 };
145     uint8_t hmac_hex[HASH_VERIFY_LEN + 1] = { 0 };
146     uint32_t hmac_buf_len = HASH_LEN;
147     TEE_Result ret;
148 
149     ret = calculate_master_hmac(sfd, hmac_buf, &hmac_buf_len);
150     if (ret != TEE_SUCCESS) {
151         tloge("calculate master hmac failed %x\n", ret);
152         return ret;
153     }
154     str_tran((unsigned char *)hmac_buf, hmac_buf_len, (char *)hmac_hex, sizeof(hmac_hex));
155 
156     ret = (TEE_Result)write_hmac_to_meta_data(sfd, hmac_hex, HASH_VERIFY_LEN);
157     if (ret != 0) {
158         tloge("write data hmac to meta failed %x\n", ret);
159         return ret;
160     }
161 
162     return TEE_SUCCESS;
163 }
164 
set_last_blocksize_to_meta_hdr(int nfd,uint32_t last_block_realsize,const struct sfd_t * sfd)165 static int32_t set_last_blocksize_to_meta_hdr(int nfd, uint32_t last_block_realsize, const struct sfd_t *sfd)
166 {
167     /* for read metadata */
168     uint32_t read_count;
169     int32_t error = 0;
170     errno_t rc;
171     /* for write metadata */
172     uint32_t write_count;
173     /* for meta_data Header */
174     meta_storage_t sfs_meta;
175     /* for hmac of data */
176     uint8_t calculated_hmac[HASH_VERIFY_LEN + 1] = { 0 };
177 
178     /* read origal metadata */
179     read_count = ssa_fs_fread(&sfs_meta, sizeof(sfs_meta), nfd, &error);
180     if (read_count != sizeof(sfs_meta) || error < 0) {
181         tloge("read metadata failed! count %x\n", read_count);
182         return -1;
183     }
184 
185     /* update metadata */
186     sfs_meta.hdr.last_block_realsize = last_block_realsize;
187 
188     sfs_meta.hdr.magic_version = META_STORATE_MAGIC_VERSION;
189 
190     if (calc_filename_datahmac_hash(&sfs_meta, sfd) != TEE_SUCCESS)
191         return -1;
192 
193 #ifdef CONFIG_THIRD_STORAGE_SUPPORT
194     sfs_meta.hdr.first_iv = sfd->first_iv;
195 #endif
196     /* calculate hmac of metadata */
197     if (calculate_hmac((uint8_t *)&sfs_meta.hdr, sizeof(sfs_meta.hdr), calculated_hmac, sizeof(calculated_hmac), sfd)) {
198         tloge("get hmac of metadata failed\n");
199         return -1;
200     }
201 
202     rc = memmove_s(sfs_meta.meta_hmac, sizeof(sfs_meta.meta_hmac), calculated_hmac, sizeof(sfs_meta.meta_hmac));
203     if (rc != EOK)
204         return -1;
205 
206     /* seek to start of file */
207     if (ssa_fs_fseek(nfd, 0, TEE_DATA_SEEK_SET)) {
208         tloge("seek start of file failed\n");
209         return -1;
210     }
211 
212     /* write metadata */
213     tlogd("enc_method is %u\n", sfs_meta.hdr.encrypto_meth);
214     write_count = ssa_fs_fwrite(&sfs_meta, sizeof(sfs_meta), nfd);
215     if (write_count != sizeof(sfs_meta)) {
216         tloge("write metadata failed! count %u\n", write_count);
217         return -1;
218     }
219 
220     return 0;
221 }
222 
223 /* fd is secure file handle */
set_last_crypt_block_realsize(const struct sfd_t * sfd,uint32_t len)224 static int32_t set_last_crypt_block_realsize(const struct sfd_t *sfd, uint32_t len)
225 {
226     int32_t ret;
227     uint8_t *encrypted_file_name = NULL;
228 
229     if (sfd == NULL || sfd->meta_data == NULL)
230         return -1;
231 
232     if (get_encrypted_file_name(&encrypted_file_name, sfd) != 0)
233         return -1;
234 
235     if (encrypted_file_name == NULL)
236         return -1;
237 
238     int32_t fd = ssa_fs_fopen((char *)encrypted_file_name,
239                               (uint32_t)(TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE),
240                               sfd->meta_data->storage_id);
241     if (fd < 0) {
242         tloge("open file error fd:%d!\n", fd);
243         return -1;
244     }
245 
246     ret = set_last_blocksize_to_meta_hdr(fd, len, sfd);
247 
248     (void)ssa_fs_fclose(fd);
249 
250     return ret;
251 }
252 
ssa_write_mac(struct sfd_t * sfd)253 TEE_Result ssa_write_mac(struct sfd_t *sfd)
254 {
255     TEE_Result ret = TEE_SUCCESS;
256 
257     if (sfd == NULL || sfd->meta_data == NULL)
258         return TEE_ERROR_BAD_PARAMETERS;
259 
260     if (judge_valid_version(sfd)) {
261         ret = update_master_hmac(sfd);
262         if (ret != TEE_SUCCESS) {
263             tloge("update master hmac failed\n");
264         } else {
265             sfd->update_backup = true;
266         }
267     }
268 
269     if (set_last_crypt_block_realsize(sfd, sfd->last_block_size)) {
270         tloge("set last crypto blocksize failed\n");
271         return TEE_ERROR_GENERIC;
272     }
273 
274     return ret;
275 }
276 
ssa_reset_mac(const struct sfd_t * sfd)277 static TEE_Result ssa_reset_mac(const struct sfd_t *sfd)
278 {
279     uint8_t hmac_hex[HASH_VERIFY_LEN + 1] = { 0 };
280 
281     if (sfd == NULL || sfd->meta_data == NULL)
282         return TEE_ERROR_BAD_PARAMETERS;
283 
284     if (judge_valid_version(sfd)) {
285         int32_t nfd = ssa_fs_fopen((char *)sfd->meta_data->cur_encrypted_file_id, TEE_DATA_FLAG_ACCESS_WRITE,
286                                    sfd->meta_data->storage_id);
287         if (nfd < 0) {
288             tloge("open file %s failed\n", sfd->meta_data->cur_encrypted_file_id);
289             return TEE_ERROR_GENERIC;
290         }
291 
292         int32_t ret = ssa_fs_fseek(nfd, SFS_DATAHMAC_OFFSET, TEE_DATA_SEEK_SET);
293         if (ret < 0) {
294             tloge("seek file %s failed\n", sfd->meta_data->cur_encrypted_file_id);
295             (void)ssa_fs_fclose(nfd);
296             return TEE_ERROR_GENERIC;
297         }
298 
299         uint32_t write_ret = ssa_fs_fwrite(hmac_hex, HASH_VERIFY_LEN, nfd);
300         if (write_ret != HASH_VERIFY_LEN) {
301             tloge("write data hmac to metadata failed, ret=%u\n", write_ret);
302             (void)ssa_fs_fclose(nfd);
303             return TEE_ERROR_GENERIC;
304         }
305 
306         (void)ssa_fs_fclose(nfd);
307     }
308 
309     return TEE_SUCCESS;
310 }
311 
calculate_hash_for_block(const struct sfd_t * sfd,const uint8_t * crypto_buf,uint32_t buf_size,struct block_info_t * cur_block_pos,struct block_info_t * last_block_pos)312 static TEE_Result calculate_hash_for_block(const struct sfd_t *sfd, const uint8_t *crypto_buf,
313     uint32_t buf_size, struct block_info_t *cur_block_pos, struct block_info_t *last_block_pos)
314 {
315     uint32_t idx;
316     uint32_t block_size;
317     uint32_t crypto_blks;
318 
319     block_size = sfd->crypto_block_size;
320     if (block_size == 0)
321         return TEE_ERROR_BAD_PARAMETERS;
322 
323     crypto_blks = buf_size / block_size;
324 
325     for (idx = 0; idx < crypto_blks && cur_block_pos != NULL; idx++) {
326         (void)calculate_block_hash(cur_block_pos->hash, sizeof(cur_block_pos->hash),
327                                    crypto_buf + idx * block_size, block_size);
328 
329         if (cur_block_pos->next == NULL && (idx + 1) < crypto_blks) {
330             cur_block_pos->next = TEE_Malloc(sizeof(struct block_info_t), 0);
331             if (cur_block_pos->next == NULL) {
332                 tloge("malloc2 blockInfo failed\n");
333                 return TEE_ERROR_OUT_OF_MEMORY;
334             }
335 
336             last_block_pos          = cur_block_pos->next;
337             last_block_pos->block_id = last_block_pos->block_id + 1;
338             last_block_pos->next    = NULL;
339         }
340 
341         cur_block_pos = cur_block_pos->next;
342     }
343 
344     return TEE_SUCCESS;
345 }
346 
update_block_hash(struct sfd_t * sfd,const uint8_t * crypto_buf,uint32_t buf_size,uint32_t start_block_id)347 static TEE_Result update_block_hash(struct sfd_t *sfd, const uint8_t *crypto_buf,
348     uint32_t buf_size, uint32_t start_block_id)
349 {
350     TEE_Result ret;
351     struct block_info_t *cur_block_pos  = NULL;
352     struct block_info_t *last_block_pos = NULL;
353     bool found_start_block              = false;
354 
355     tlogd("start block_id=%u, buffer size=%u\n", start_block_id, buf_size);
356 
357     cur_block_pos = sfd->first_block;
358     if (cur_block_pos == NULL) {
359         tloge("illegal pointer\n");
360         return TEE_ERROR_BAD_PARAMETERS;
361     }
362 
363     /* find start_block_id entry in list */
364     while (cur_block_pos != NULL) {
365         if (cur_block_pos->block_id == start_block_id) {
366             found_start_block = true;
367             break;
368         }
369         last_block_pos = cur_block_pos;
370         cur_block_pos  = cur_block_pos->next;
371     }
372 
373     /* create a whole list from zero to start_block_id */
374     if (!found_start_block) {
375         cur_block_pos = last_block_pos;
376         while (cur_block_pos->block_id < start_block_id) {
377             cur_block_pos->next = TEE_Malloc(sizeof(struct block_info_t), 0);
378             if (cur_block_pos->next == NULL) {
379                 tloge("malloc1 blockInfo failed\n");
380                 return TEE_ERROR_OUT_OF_MEMORY;
381             }
382 
383             last_block_pos          = cur_block_pos;
384             cur_block_pos           = cur_block_pos->next;
385             cur_block_pos->block_id = last_block_pos->block_id + 1;
386             cur_block_pos->next     = NULL;
387         }
388     }
389 
390     /* calculate hash one by one */
391     ret = calculate_hash_for_block(sfd, crypto_buf, buf_size, cur_block_pos, last_block_pos);
392     return ret;
393 }
394 
395 #define HUANGLONG_PLATFORM 2
derive_ivcounter(const uint8_t * data_in,uint32_t data_in_size,uint8_t * data_out,uint32_t data_out_size,const uint8_t * key_value,uint32_t key_value_size)396 static int32_t derive_ivcounter(const uint8_t *data_in, uint32_t data_in_size, uint8_t *data_out,
397                                 uint32_t data_out_size, const uint8_t *key_value, uint32_t key_value_size)
398 {
399     if (data_in == NULL || data_out == NULL || key_value == NULL || data_in_size > INT32_MAX)
400         return -1;
401 
402     /* do hash sha256 */
403     TEE_Result ret = cmd_hash(key_value, key_value_size, g_gs_key_hash.key, (size_t)data_out_size);
404     if (ret != TEE_SUCCESS) {
405         tloge("do hash sha256 failed, ret = 0x%x\n", ret);
406         return -1;
407     }
408     g_gs_key_hash.flag = true;
409 
410     /* do hmac sha256 */
411     struct key_info_t key_info = {
412         .key = g_gs_key_hash.key,
413         .key_len = CRYPT_KEY_SIZE,
414     };
415     ret = calc_hmac256(&key_info, data_in, (int32_t)data_in_size, data_out, &data_out_size);
416     if (ret != TEE_SUCCESS) {
417         tloge("do hmac sha256 failed, ret = 0x%x\n", ret);
418         return -1;
419     }
420     return 0;
421 }
422 
423 #define BLOCK_ID_SIZE 4
encrypt_blocks_with_cbc(const uint8_t * src,uint32_t len,uint8_t * dst,const struct sfd_t * sfd,uint32_t mode)424 TEE_Result encrypt_blocks_with_cbc(const uint8_t *src, uint32_t len, uint8_t *dst, const struct sfd_t *sfd,
425                                    uint32_t mode)
426 {
427     uint32_t encrypt_times, encrypt_index;
428     size_t crypto_blocksize;
429     /* for CBC IV */
430     uint8_t iv[CRYPT_KEY_SIZE];
431     uint8_t block_id_buffer[BLOCK_ID_SIZE];
432     uint32_t block_id;
433     errno_t rc;
434 
435     if (src == NULL || dst == NULL || sfd == NULL || sfd->meta_data == NULL)
436         return TEE_ERROR_BAD_PARAMETERS;
437 #ifdef CONFIG_THIRD_STORAGE_SUPPORT
438     block_id = sfd->start_block_id + sfd->first_iv;
439 #else
440     block_id = sfd->start_block_id;
441 #endif
442     crypto_blocksize = sfd->crypto_block_size;
443     if (crypto_blocksize == 0)
444         return TEE_ERROR_BAD_PARAMETERS;
445 
446     encrypt_times = len / crypto_blocksize;
447 
448     for (encrypt_index = 0; encrypt_index < encrypt_times; encrypt_index++) {
449         tlogd("---encrypt %u/%u---\n", encrypt_index, encrypt_times);
450 
451         /* generate iv from block id */
452         rc = memset_s((void *)iv, sizeof(iv), 0, sizeof(iv));
453         if (rc != EOK)
454             tloge("memset iv failed, %x\n", rc);
455 
456         rc = memset_s((void *)block_id_buffer, sizeof(block_id_buffer), 0, sizeof(block_id_buffer));
457         if (rc != EOK)
458             tloge("memset block_id failed, %x\n", rc);
459 
460         rc = memmove_s(block_id_buffer, sizeof(block_id_buffer), &block_id, sizeof(block_id_buffer));
461         if (rc != EOK)
462             return TEE_ERROR_SECURITY;
463 
464         if (derive_ivcounter(block_id_buffer, sizeof(block_id_buffer), iv, sizeof(iv), sfd->meta_data->ta_root_key,
465             sizeof(sfd->meta_data->ta_root_key))) {
466             tloge("generate iv from block id failed\n");
467             return TEE_ERROR_GENERIC;
468         }
469 
470         uint32_t encrypt_offset = crypto_blocksize * encrypt_index;
471 
472         TEE_Result ret = aes_cbc_crypto(mode, sfd->meta_data->ta_root_key, sizeof(sfd->meta_data->ta_root_key),
473             iv, sizeof(iv), (uint8_t *)(src + encrypt_offset), crypto_blocksize, (uint8_t *)(dst + encrypt_offset));
474         if (ret != TEE_SUCCESS)
475             return ret;
476 
477         /* update block id */
478         block_id++;
479     }
480     return TEE_SUCCESS;
481 }
482 
encrypt_blocks_with_xts(const uint8_t * src,uint32_t len,uint8_t * dst,const struct sfd_t * sfd,uint32_t mode)483 TEE_Result encrypt_blocks_with_xts(const uint8_t *src, uint32_t len, uint8_t *dst, const struct sfd_t *sfd,
484                                    uint32_t mode)
485 {
486     uint32_t encrypt_index;
487     uint8_t block_id_buffer[sizeof(uint32_t)];
488     uint32_t block_id;
489 
490     if (src == NULL || dst == NULL || sfd == NULL)
491         return TEE_ERROR_BAD_PARAMETERS;
492 
493     block_id = sfd->start_block_id;
494 
495     for (encrypt_index = 0; encrypt_index < len / sfd->crypto_block_size; encrypt_index++) {
496         tlogd("---encrypt %u/%u---\n", encrypt_index, len / sfd->crypto_block_size);
497 
498         /* generate iv from block id and random */
499         (void)memset_s((void *)block_id_buffer, sizeof(block_id_buffer), 0, sizeof(block_id_buffer));
500         if (memmove_s(block_id_buffer, sizeof(block_id_buffer), &block_id, sizeof(block_id_buffer)) != EOK)
501             return TEE_ERROR_SECURITY;
502 
503         struct memref_t tweak = {(uintptr_t)block_id_buffer, sizeof(block_id_buffer)};
504         uint32_t crypto_offset = sfd->crypto_block_size * encrypt_index;
505         struct memref_t data_in = {(uintptr_t)(src + crypto_offset), sfd->crypto_block_size};
506         struct memref_t data_out = {(uintptr_t)(dst + crypto_offset), sfd->crypto_block_size};
507         if (aes_xts_crypto(mode, sfd, &tweak, &data_in, &data_out) != TEE_SUCCESS) {
508             tloge("encrypt failed\n");
509             return TEE_ERROR_GENERIC;
510         }
511 
512         /* update block id */
513         block_id++;
514     }
515     return TEE_SUCCESS;
516 }
517 
check_block_integrity(const struct sfd_t * sfd,const uint8_t * buff,uint32_t buff_size,uint32_t block_id)518 static TEE_Result check_block_integrity(const struct sfd_t *sfd, const uint8_t *buff,
519     uint32_t buff_size, uint32_t block_id)
520 {
521     TEE_Result ret;
522     struct block_info_t *cur_block_pos = NULL;
523     uint8_t calculated_hash[HASH_LEN];
524     uint32_t i;
525     errno_t rc;
526 
527     if (sfd == NULL || buff == NULL)
528         return TEE_ERROR_BAD_PARAMETERS;
529 
530     for (i = 0; i < buff_size / sfd->crypto_block_size; i++) {
531         rc = memset_s((void *)calculated_hash, sizeof(calculated_hash), 0, sizeof(calculated_hash));
532         if (rc != EOK)
533             tlogw("memset failed\n");
534 
535         ret = calculate_block_hash(calculated_hash, sizeof(calculated_hash), buff + i * sfd->crypto_block_size,
536                                    sfd->crypto_block_size);
537         if (ret != TEE_SUCCESS)
538             return ret;
539 
540         cur_block_pos = sfd->first_block;
541         while (cur_block_pos != NULL) {
542             if (cur_block_pos->block_id == (block_id + i))
543                 break;
544             cur_block_pos = cur_block_pos->next;
545         }
546         if (cur_block_pos == NULL) {
547             tloge("block_id is not found in the block list %u\n", block_id + i);
548             return TEE_ERROR_BAD_STATE;
549         }
550 
551         if (TEE_MemCompare(calculated_hash, cur_block_pos->hash, sizeof(cur_block_pos->hash))) {
552             tloge("compare hash of block fail, block_id=%u\n", block_id + i);
553             return TEE_ERROR_CORRUPT_OBJECT;
554         }
555     }
556 
557     return TEE_SUCCESS;
558 }
559 
check_read_params(const uint8_t * out_buf,struct sfd_t * sfd,TEE_Result * error)560 static TEE_Result check_read_params(const uint8_t *out_buf, struct sfd_t *sfd, TEE_Result *error)
561 {
562     if (error == NULL)
563         return TEE_ERROR_BAD_PARAMETERS;
564 
565     if (out_buf == NULL || sfd == NULL || sfd->meta_data == NULL ||
566         sfd->meta_data->cur_encrypted_file_id == NULL) {
567         tloge("ssa read Illegal sfd\n");
568         *error = TEE_ERROR_BAD_PARAMETERS;
569         return TEE_ERROR_BAD_PARAMETERS;
570     }
571 
572     if (sfd->crypto_block_size == 0) {
573         tloge("Illegal sfd crypto_block_size\n");
574         *error = TEE_ERROR_BAD_STATE;
575         return TEE_ERROR_BAD_STATE;
576     }
577 
578     return TEE_SUCCESS;
579 }
580 
ssa_read_init_data(struct ssa_rw_info * r_info,uint32_t * count,struct sfd_t * sfd)581 static TEE_Result ssa_read_init_data(struct ssa_rw_info *r_info, uint32_t *count, struct sfd_t *sfd)
582 {
583     TEE_Result ret;
584     uint32_t file_len;
585     r_info->start_flag = 0;
586     r_info->end_flag = 0;
587     r_info->crypto_blocksize = sfd->crypto_block_size;  /* crypto_block_size = 3k */
588 
589     /* get cur_pos and file_len */
590     ret = ssa_info(sfd, &(r_info->cur_pos), &file_len);
591     if (ret != TEE_SUCCESS) {
592         tloge("get file info error\n");
593         return ret;
594     }
595 
596     if (r_info->cur_pos + *count > file_len)
597         *count = file_len - r_info->cur_pos;
598 
599     /* start pos should be CRYPT_BLOCK_SIZE align */
600     r_info->start_pos    = GET_ALIGNED_SIZE_DOWN(r_info->cur_pos, r_info->crypto_blocksize);
601     r_info->start_offset = r_info->cur_pos - r_info->start_pos;
602     r_info->end_pos      = r_info->cur_pos + *count;
603     r_info->end_offset   = r_info->end_pos % r_info->crypto_blocksize;
604 
605     /* go to start pos */
606     if (r_info->start_offset != 0) {
607         ret = ssa_seek(sfd, r_info->start_pos, TEE_DATA_SEEK_SET);
608         if (ret != TEE_SUCCESS) {
609             tloge("seek to start pos failed \n");
610             return ret;
611         }
612     }
613 
614     return TEE_SUCCESS;
615 }
616 
decrypt_data_block(struct sfd_t * sfd,uint32_t read_count,uint32_t start_block_id,uint8_t * buff)617 static TEE_Result decrypt_data_block(struct sfd_t *sfd,
618     uint32_t read_count, uint32_t start_block_id, uint8_t *buff)
619 {
620     TEE_Result ret;
621     sfd->start_block_id = start_block_id;
622 
623     ret = check_block_integrity(sfd, buff, read_count, sfd->start_block_id);
624     if (ret != TEE_SUCCESS) {
625         tloge("block has been corrupted while read\n");
626         return ret;
627     }
628     ret = encrypt_blocks(buff, read_count, buff, sfd, TEE_MODE_DECRYPT);
629     if (ret != TEE_SUCCESS) {
630         tloge("decrypt file failed\n");
631         return ret;
632     }
633 
634     return TEE_SUCCESS;
635 }
636 
read_data_out(struct ssa_rw_info * r_info,uint8_t * out_buf,uint32_t count,struct sfd_t * sfd,uint32_t * total_read_count)637 static TEE_Result read_data_out(struct ssa_rw_info *r_info, uint8_t *out_buf,
638     uint32_t count, struct sfd_t *sfd, uint32_t *total_read_count)
639 {
640     TEE_Result ret;
641     int8_t end_of_file = 0;
642     uint32_t recv_times, recv_index;
643     struct ssa_rw_count_process cnt_proc;
644     uint32_t total_actual_count = 0; /* actual total read count */
645 
646     cnt_proc.actual_count = count + r_info->start_offset;
647     if (r_info->end_offset != 0)
648         cnt_proc.actual_count += (r_info->crypto_blocksize - r_info->end_offset);
649     recv_times = cnt_proc.actual_count / r_info->trans_size + ((cnt_proc.actual_count % r_info->trans_size) ? 1 : 0);
650 
651     for (recv_index = 0; recv_index < recv_times; recv_index++) {
652         uint32_t recv_count = (total_actual_count + r_info->trans_size) <= cnt_proc.actual_count ?
653             r_info->trans_size : (cnt_proc.actual_count % r_info->trans_size);
654 
655         (void)memset_s((void *)(r_info->trans_buff), r_info->trans_size, 0, r_info->trans_size);
656 
657         cnt_proc.read_count = ssa_fs_fread(r_info->trans_buff, recv_count, sfd->nfd, (int32_t *)&ret);
658         if (cnt_proc.read_count < recv_count) {
659             if (ret != TEE_SUCCESS) {
660                 tloge("a read error occurs, expected=%u, actual=%u, ret=%d\n", recv_count, cnt_proc.read_count, ret);
661                 return get_spec_errno(TEE_ERROR_READ_DATA);
662             }
663             end_of_file = 1;
664         }
665 
666         ret = decrypt_data_block(sfd, cnt_proc.read_count,
667             (r_info->start_pos + total_actual_count) / r_info->crypto_blocksize, r_info->trans_buff);
668         if (ret != TEE_SUCCESS)
669             return ret;
670 
671         total_actual_count += cnt_proc.read_count;
672         cnt_proc.copy_count = cnt_proc.read_count;
673 
674         if (recv_index == 0 && r_info->start_offset != 0)
675             cnt_proc.copy_count -= r_info->start_offset;
676 
677         if ((recv_index == (recv_times - 1)) && r_info->end_offset != 0) {
678             cnt_proc.copy_count -= (r_info->crypto_blocksize - r_info->end_offset);
679             r_info->end_flag = 1;
680         }
681 
682         if (memmove_s(out_buf + *total_read_count, count - *total_read_count,
683             recv_index ? r_info->trans_buff : (r_info->trans_buff + r_info->start_offset), cnt_proc.copy_count) != EOK)
684             return TEE_ERROR_SECURITY;
685 
686         *total_read_count += cnt_proc.copy_count;
687         if (end_of_file != 0)
688             return TEE_SUCCESS;
689     }
690     return TEE_SUCCESS;
691 }
692 
693 /*
694  * Function    : safe file read
695  * Description : null
696  * Input       : count - read size
697  *               sfd   - file handler
698  * Output      : out_buf - buffer to store read file content
699  * Return      : number of element successfully read
700  */
ssa_read(uint8_t * out_buf,uint32_t count,struct sfd_t * sfd,TEE_Result * error)701 uint32_t ssa_read(uint8_t *out_buf, uint32_t count, struct sfd_t *sfd, TEE_Result *error)
702 {
703     TEE_Result ret;
704     uint32_t total_read_count = 0; /* total read useful count */
705     struct ssa_rw_info read_info;
706 
707     if (check_read_params(out_buf, sfd, error) != TEE_SUCCESS)
708         return 0;
709 
710     *error = ssa_read_init_data(&read_info, &count, sfd);
711     if (*error != TEE_SUCCESS)
712         return 0;
713 
714     if (read_info.cur_pos >= sfd->size) {
715         *error = TEE_SUCCESS;
716         return 0;
717     }
718 
719     /* alloc trans_buff, CRYPT_BLOCK_SIZE align */
720     read_info.trans_size = GET_ALIGNED_SIZE_DOWN(TRANS_BUFF_SIZE - get_fs_meta_size(), read_info.crypto_blocksize);
721     read_info.trans_buff = TEE_Malloc(read_info.trans_size, 0);
722     if (read_info.trans_buff == NULL) {
723         tloge("can't alloc trans_buff\n");
724         *error = TEE_ERROR_OUT_OF_MEMORY;
725         return 0;
726     }
727 
728     ret = read_data_out(&read_info, out_buf, count, sfd, &total_read_count);
729     if (ret != TEE_SUCCESS) {
730         tloge("read data fail!\n");
731         *error = ret;
732     }
733 
734     if (read_info.end_flag != 0) {
735         ret = ssa_seek(sfd, read_info.end_pos, TEE_DATA_SEEK_SET);
736         if (ret != TEE_SUCCESS) {
737             tloge("seek to end position fail\n");
738             *error = ret;
739         }
740     }
741 
742     TEE_Free(read_info.trans_buff);
743 
744     /* *error equal the initial value of invoking function */
745     return total_read_count;
746 }
747 
check_write_params(const uint8_t * content,struct sfd_t * sfd,TEE_Result * error)748 static TEE_Result check_write_params(const uint8_t *content,
749                                      struct sfd_t *sfd, TEE_Result *error)
750 {
751     if ((sfd == NULL) || (content == NULL) || (error == NULL) || (sfd->meta_data == NULL) ||
752         (sfd->meta_data->file_id == NULL)) {
753         tloge("ssa write Illegal sfd\n");
754         *error = TEE_ERROR_BAD_PARAMETERS;
755         return TEE_ERROR_BAD_PARAMETERS;
756     }
757 
758     if (sfd->crypto_block_size == 0) {
759         tloge("ssa write crypto block size invalid\n");
760         *error = TEE_ERROR_BAD_STATE;
761         return TEE_ERROR_BAD_STATE;
762     }
763 
764     return TEE_SUCCESS;
765 }
766 
get_file_info_fill_hole(struct sfd_t * sfd,uint32_t count,uint32_t * cur_pos)767 static TEE_Result get_file_info_fill_hole(struct sfd_t *sfd, uint32_t count, uint32_t *cur_pos)
768 {
769     TEE_Result ret;
770     uint32_t file_len;
771 
772     /*
773      * get cur_pos and file_len
774      * if we update seek_position and size real-time, we don't need to call ssa_info here.
775      */
776     ret = ssa_info(sfd, cur_pos, &file_len);
777     if (ret != TEE_SUCCESS) {
778         tloge("get file info error\n");
779         return ret;
780     }
781 
782     tlogd("file info : pos/len = %u/%u count=%u\n", *cur_pos, file_len, count);
783 
784     /* count max size is 4M */
785     if (*(cur_pos) + count > MAX_FILE_SIZE + sfd->attr_size) {
786         tloge("file size is exceed maximum");
787         return TEE_ERROR_OVERFLOW;
788     }
789 
790     /* here is a file hole!! encrypt the file hole first */
791     if (*cur_pos > file_len) {
792         ret = fill_file_hole(sfd, file_len, *cur_pos - file_len);
793         if (ret != TEE_SUCCESS) {
794             tloge("fill hole failed\n");
795             return ret;
796         }
797     }
798 
799     return TEE_SUCCESS;
800 }
801 
init_write_pos_info(struct ssa_rw_info * w_info,struct sfd_t * sfd,uint32_t count)802 static void init_write_pos_info(struct ssa_rw_info *w_info, struct sfd_t *sfd, uint32_t count)
803 {
804     /* start pos should be CRYPT_BLOCK_SIZE align */
805     w_info->crypto_blocksize = sfd->crypto_block_size;
806     w_info->start_pos        = GET_ALIGNED_SIZE_DOWN(w_info->cur_pos, w_info->crypto_blocksize);
807     w_info->start_offset     = w_info->cur_pos - w_info->start_pos;
808     w_info->end_pos          = w_info->cur_pos + count;
809     w_info->end_offset       = w_info->end_pos % w_info->crypto_blocksize;
810 
811     tlogd("start_pos = %u, start_offset=%u, end_pos=%u, end_offset=%u\n", pos->start_pos,
812         pos->start_offset, pos->end_pos, pos->end_offset);
813 }
814 
malloc_write_buffer(uint8_t ** trans_buff,uint32_t * trans_size,uint8_t ** crypto_buff,uint32_t crypto_blocksize)815 static TEE_Result malloc_write_buffer(uint8_t **trans_buff, uint32_t *trans_size,
816     uint8_t **crypto_buff, uint32_t crypto_blocksize)
817 {
818     /* alloc trans_buff, CRYPT_BLOCK_SIZE align */
819     *trans_size = GET_ALIGNED_SIZE_DOWN(TRANS_BUFF_SIZE - get_fs_meta_size(), crypto_blocksize);
820     tlogd("trans_size = %u\n", *trans_size);
821     *trans_buff = TEE_Malloc(*trans_size, 0);
822     if (trans_buff == NULL) {
823         tloge("can't alloc trans_buff\n");
824         return TEE_ERROR_OUT_OF_MEMORY;
825     }
826 
827     *crypto_buff = TEE_Malloc(crypto_blocksize, 0);
828     if (crypto_buff == NULL) {
829         tloge("malloc crypto buffer failed\n");
830         TEE_Free(trans_buff);
831         return TEE_ERROR_OUT_OF_MEMORY;
832     }
833 
834     return TEE_SUCCESS;
835 }
836 
free_write_buffer(uint8_t * trans_buff,uint8_t * crypto_buff)837 static void free_write_buffer(uint8_t *trans_buff, uint8_t *crypto_buff)
838 {
839     TEE_Free(crypto_buff);
840     TEE_Free(trans_buff);
841 }
842 
ssa_init_write_info(struct ssa_rw_info * w_info,uint32_t count,struct sfd_t * sfd)843 static TEE_Result ssa_init_write_info(struct ssa_rw_info *w_info, uint32_t count, struct sfd_t *sfd)
844 {
845     TEE_Result ret;
846 
847     w_info->end_flag = 0;
848     w_info->start_flag = 0;
849     ret = get_file_info_fill_hole(sfd, count, &w_info->cur_pos);
850     if (ret != TEE_SUCCESS)
851         return ret;
852 
853     init_write_pos_info(w_info, sfd, count);
854 
855     if ((w_info->cur_pos + count) > sfd->size)
856         /*
857          * we can only update this value in sfd in memory,
858          * at the last stage, update this value and hmac in meta together.
859          */
860         sfd->last_block_size = (count + w_info->cur_pos) % w_info->crypto_blocksize;
861 
862     /* hmac reset to 0 */
863     ret = ssa_reset_mac(sfd);
864     if (ret != TEE_SUCCESS) {
865         tloge("reset mac failed\n");
866         return ret;
867     }
868 
869     sfd->update_backup = false;
870 
871     return TEE_SUCCESS;
872 }
873 
fill_start_block_origin(struct ssa_rw_info * w_info,struct sfd_t * sfd,uint8_t ** dst_addr,uint32_t * add_count,uint32_t * copy_count)874 static TEE_Result fill_start_block_origin(struct ssa_rw_info *w_info,
875     struct sfd_t *sfd, uint8_t **dst_addr, uint32_t *add_count, uint32_t *copy_count)
876 {
877     TEE_Result ret;
878     uint32_t start_blk_size;
879     uint32_t read_count;
880 
881     if (w_info->start_pos < sfd->size) {
882         /*
883          * set file pointer to blk head to read blk
884          * if attribute as meta, we should handle this.
885          */
886         ret = ssa_fs_fseek_blk_start(sfd, w_info->start_pos);
887         if (ret != TEE_SUCCESS)
888             return ret;
889 
890         start_blk_size = w_info->crypto_blocksize;
891         read_count = ssa_fs_fread(w_info->crypto_buff, start_blk_size, sfd->nfd, (int32_t *)&ret);
892         if (read_count < start_blk_size && ret != TEE_SUCCESS) {
893             /* read error, no need to update hash file */
894             tloge("a read error occurs, expected=%u, actual=%u, error=0x%x\n", start_blk_size, read_count, ret);
895             return get_spec_errno(TEE_ERROR_READ_DATA);
896         }
897 
898         ret = decrypt_data_block(sfd, read_count, w_info->start_pos / w_info->crypto_blocksize, w_info->crypto_buff);
899         if (ret != TEE_SUCCESS) {
900             tloge("decrypt data block failed\n");
901             return ret;
902         }
903 
904         errno_t rc = memmove_s(w_info->trans_buff, w_info->trans_size, w_info->crypto_buff, w_info->start_offset);
905         if (rc != EOK) {
906             tloge("memmove failed\n");
907             return TEE_ERROR_SECURITY;
908         }
909     }
910 
911     /*
912      * Notice :for else,it is file hole, the content is 0, should't be read out and descrypt
913      * Actually, else condition is not exist,
914      * Because if file hole exist, we will fill it will zero.
915      * Thus, the length of file will update.
916      */
917     *dst_addr += w_info->start_offset;
918     *copy_count -= w_info->start_offset;
919     *add_count += w_info->start_offset;
920 
921     return TEE_SUCCESS;
922 }
923 
fill_end_block_origin(struct ssa_rw_info * w_info,struct sfd_t * sfd,uint32_t * add_count)924 static TEE_Result fill_end_block_origin(struct ssa_rw_info *w_info,
925     struct sfd_t *sfd, uint32_t *add_count)
926 {
927     errno_t rc;
928     TEE_Result ret;
929     *add_count += (w_info->crypto_blocksize - w_info->end_offset);
930     if (w_info->end_pos < sfd->size) {
931         uint32_t end_blk_size;
932 
933         /* set file pointer to blk head to read block */
934         ret = ssa_fs_fseek_blk_end(sfd, w_info->end_pos, w_info->end_offset);
935         if (ret != TEE_SUCCESS)
936             return ret;
937 
938         /* notice:maybe last blk is not a full blk */
939         end_blk_size = w_info->crypto_blocksize;
940 
941         uint32_t read_count = ssa_fs_fread(w_info->crypto_buff, end_blk_size, sfd->nfd, (int32_t *)&ret);
942         if ((read_count < end_blk_size) && (ret != TEE_SUCCESS)) {
943             tloge("a read error occurs, expected=%u, actual=%u, error=0x%x\n", end_blk_size, read_count, ret);
944             return get_spec_errno(TEE_ERROR_READ_DATA);
945         }
946 
947         ret = decrypt_data_block(sfd, read_count,
948             (w_info->end_pos - w_info->end_offset) / w_info->crypto_blocksize, w_info->crypto_buff);
949         if (ret != TEE_SUCCESS) {
950             tloge("decrypt data block failed\n");
951             return ret;
952         }
953 
954         rc = memmove_s(w_info->trans_buff + (w_info->end_pos % w_info->trans_size),
955                        w_info->trans_size - (w_info->end_pos % w_info->trans_size),
956                        w_info->crypto_buff + w_info->end_offset, end_blk_size - w_info->end_offset);
957         if (rc != EOK)
958             return TEE_ERROR_SECURITY;
959     }
960     if (sfd->size == 0) {
961         rc = memmove_s(w_info->trans_buff + (w_info->end_pos % w_info->trans_size),
962                        w_info->trans_size - (w_info->end_pos % w_info->trans_size),
963                        w_info->crypto_buff + w_info->end_offset, w_info->crypto_blocksize - w_info->end_offset);
964         if (rc != EOK)
965             return TEE_ERROR_SECURITY;
966     }
967 
968     return TEE_SUCCESS;
969 }
970 
write_data(struct ssa_rw_info * w_info,uint32_t send_count,struct sfd_t * sfd,uint32_t * total_write_count)971 static TEE_Result write_data(struct ssa_rw_info *w_info, uint32_t send_count,
972     struct sfd_t *sfd, uint32_t *total_write_count)
973 {
974     TEE_Result ret;
975     uint32_t write_count;
976     uint32_t start_blockid = sfd->start_block_id;
977 
978     write_count = ssa_fs_fwrite(w_info->trans_buff, send_count, sfd->nfd);
979     if (write_count < send_count) {
980         tloge("write_count < send_count failed\n");
981         return get_spec_errno(TEE_ERROR_WRITE_DATA);
982     }
983 
984     if (judge_valid_version(sfd)) {
985         ret = update_block_hash(sfd, w_info->trans_buff, send_count, start_blockid);
986         if (ret != TEE_SUCCESS) {
987             tloge("update blocks hash failed\n");
988             return ret;
989         }
990     }
991 
992     *total_write_count += write_count;
993 
994     return TEE_SUCCESS;
995 }
996 
seek_write_pos(struct ssa_rw_info * w_info,struct sfd_t * sfd,uint32_t total_write_count)997 static TEE_Result seek_write_pos(struct ssa_rw_info *w_info,
998     struct sfd_t *sfd, uint32_t total_write_count)
999 {
1000     TEE_Result ret;
1001     uint32_t seek_start_pos = w_info->start_pos + total_write_count;
1002     /*
1003      * don't set end_flag=0,end seek will use it
1004      * set file pointer to blk head to read blk, because it had fread to change file pointer
1005      */
1006     if (w_info->start_flag != 0 || w_info->end_flag != 0) {
1007         w_info->start_flag = 0;
1008         ret = ssa_fs_fseek_blk_start(sfd, seek_start_pos);
1009         if (ret != TEE_SUCCESS) {
1010             tloge("seek file to written offset failed\n");
1011             return get_spec_errno(TEE_ERROR_SEEK_DATA);
1012         }
1013     }
1014 
1015     return TEE_SUCCESS;
1016 }
1017 
encrypt_trans_buff(struct sfd_t * sfd,struct ssa_rw_info * w_info,uint32_t send_count,uint32_t total_write_count)1018 static TEE_Result encrypt_trans_buff(struct sfd_t *sfd,
1019     struct ssa_rw_info *w_info, uint32_t send_count, uint32_t total_write_count)
1020 {
1021     TEE_Result ret;
1022 
1023     /*
1024      * encryt trans_buff, save in fsAgentBuffer's exchange buff
1025      * We should record write start block ID.
1026      * total_write_count is align to CRYPTO_BLOCK_SIZE forever, so we dont need to align.
1027      */
1028     sfd->crypto_block_size = w_info->crypto_blocksize;
1029     sfd->start_block_id    = (w_info->start_pos + total_write_count) / w_info->crypto_blocksize;
1030 
1031     ret = encrypt_blocks(w_info->trans_buff, send_count,
1032         w_info->trans_buff, sfd, TEE_MODE_ENCRYPT);
1033     if (ret != TEE_SUCCESS) {
1034         tloge("file encrypt failed\n");
1035         return ret;
1036     }
1037 
1038     return TEE_SUCCESS;
1039 }
1040 
write_data_process(struct ssa_rw_info * w_info,struct ssa_rw_count_process * cnt_proc,struct sfd_t * sfd,uint32_t * total_write_count)1041 static TEE_Result write_data_process(struct ssa_rw_info *w_info,
1042     struct ssa_rw_count_process *cnt_proc, struct sfd_t *sfd, uint32_t *total_write_count)
1043 {
1044     TEE_Result ret;
1045 
1046     ret = encrypt_trans_buff(sfd, w_info, cnt_proc->send_count, *total_write_count);
1047     if (ret != TEE_SUCCESS) {
1048         tloge("encrypt trans buff fail");
1049         return ret;
1050     }
1051 
1052     ret = seek_write_pos(w_info, sfd, *total_write_count);
1053     if (ret != TEE_SUCCESS) {
1054         tloge("seek write pos fail");
1055         return ret;
1056     };
1057 
1058     ret = write_data(w_info, cnt_proc->send_count, sfd, total_write_count);
1059     if (ret != TEE_SUCCESS) {
1060         tloge("write data fail");
1061         return ret;
1062     }
1063 
1064     return TEE_SUCCESS;
1065 }
1066 
write_content_to_file(struct ssa_rw_info * w_info,const uint8_t * content,uint32_t count,struct sfd_t * sfd,uint32_t * total_write_count)1067 static TEE_Result write_content_to_file(struct ssa_rw_info *w_info,
1068     const uint8_t *content, uint32_t count, struct sfd_t *sfd, uint32_t *total_write_count)
1069 {
1070     TEE_Result ret;
1071     uint32_t send_index;
1072     uint32_t send_times;
1073     uint8_t *dst_addr = NULL;
1074     uint32_t padding_size = 0;
1075     struct ssa_rw_count_process cnt_proc;
1076     const uint8_t *src_addr = content;
1077 
1078     /* s_fwrite actual writen length : content len + (start_blk add) + (end_blk add) */
1079     cnt_proc.actual_count = count + w_info->start_offset;
1080     cnt_proc.add_count = 0;
1081 
1082     if (w_info->end_offset != 0)
1083         cnt_proc.actual_count += (w_info->crypto_blocksize - w_info->end_offset);
1084 
1085     send_times = (cnt_proc.actual_count / w_info->trans_size) + ((cnt_proc.actual_count % w_info->trans_size) ? 1 : 0);
1086 
1087     for (send_index = 0; send_index < send_times; send_index++) {
1088         /* no need check return val */
1089         (void)memset_s((void *)(w_info->trans_buff), w_info->trans_size, 0, w_info->trans_size);
1090 
1091         cnt_proc.send_count = (*total_write_count + w_info->trans_size) <= cnt_proc.actual_count ?
1092             w_info->trans_size : (cnt_proc.actual_count % w_info->trans_size);
1093         dst_addr   = w_info->trans_buff;
1094         cnt_proc.copy_count = cnt_proc.send_count;
1095 
1096         /* fill trans_buff step1: start_blk 's origin part */
1097         if (send_index == 0 && w_info->start_offset) {
1098             w_info->start_flag = 1;
1099             ret = fill_start_block_origin(w_info, sfd, &dst_addr, &cnt_proc.add_count, &cnt_proc.copy_count);
1100             if (ret != TEE_SUCCESS)
1101                 return ret;
1102         }
1103         if ((send_index == send_times - 1) && w_info->end_offset)
1104             cnt_proc.copy_count -= (w_info->crypto_blocksize - w_info->end_offset);
1105 
1106         /* fill trans_buff step2 : middle_blk */
1107         if (memmove_s(dst_addr, w_info->trans_size - (dst_addr - w_info->trans_buff),
1108                       src_addr, cnt_proc.copy_count) != EOK)
1109             return TEE_ERROR_SECURITY;
1110         src_addr += cnt_proc.copy_count;
1111 
1112         /* fill trans_buff step3 : end_blk 's origin part */
1113         if ((send_index == send_times - 1) && w_info->end_offset) {
1114             w_info->end_flag = 1;
1115             ret = fill_end_block_origin(w_info, sfd, &cnt_proc.add_count);
1116             if (ret != TEE_SUCCESS)
1117                 return ret;
1118         }
1119 
1120         ret = write_data_process(w_info, &cnt_proc, sfd, total_write_count);
1121         if (ret != TEE_SUCCESS)
1122             return ret;
1123 
1124         padding_size = cnt_proc.add_count;
1125     }
1126 
1127     *total_write_count -= padding_size;
1128     return TEE_SUCCESS;
1129 }
1130 
1131 /*
1132  * Function    : safe file write,a serries call of fs to make encrypto fs write
1133  * Description : if error occurs, the crypto file is broken which can't be read again
1134  * Input       : content - content buffer
1135  *               count   - content size
1136  *               sfd     - file handler
1137  * Return      : number of element successfully write
1138  */
ssa_write(const uint8_t * content,uint32_t count,struct sfd_t * sfd,TEE_Result * error)1139 uint32_t ssa_write(const uint8_t *content, uint32_t count, struct sfd_t *sfd, TEE_Result *error)
1140 {
1141     TEE_Result ret;
1142     uint32_t total_write_count = 0;
1143     struct ssa_rw_info write_info;
1144 
1145     if (check_write_params(content, sfd, error) != TEE_SUCCESS)
1146         return 0;
1147 
1148     if (count == 0) {
1149         *error = TEE_SUCCESS;
1150         return 0;
1151     }
1152 
1153     *error = ssa_init_write_info(&write_info, count, sfd);
1154     if (*error != TEE_SUCCESS)
1155         return 0;
1156 
1157     *error = malloc_write_buffer(&write_info.trans_buff, &write_info.trans_size,
1158                                  &write_info.crypto_buff, write_info.crypto_blocksize);
1159     if (*error != TEE_SUCCESS)
1160         return 0;
1161 
1162     *error = write_content_to_file(&write_info, content, count, sfd, &total_write_count);
1163     if (*error != TEE_SUCCESS)
1164         goto out;
1165 
1166     if (write_info.end_flag != 0) {
1167         /* set file pointer pos */
1168         tlogd("we should seek to %u for real offset\n", write_info.end_pos);
1169         ret = ssa_fs_fseek_blk_end(sfd, write_info.end_pos, 0);
1170         if (ret != TEE_SUCCESS) {
1171             *error = TEE_ERROR_GENERIC;
1172             goto out;
1173         }
1174     }
1175 
1176     sfd->need_update_hmac = true;
1177 
1178 out:
1179     free_write_buffer(write_info.trans_buff, write_info.crypto_buff);
1180     sfd->size += total_write_count;
1181     return total_write_count;
1182 }
1183