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