2 * Copyright (c) 2014, STMicroelectronics International N.V.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
29 #include <kernel/tee_common.h>
30 #include <kernel/mutex.h>
31 #include <kernel/panic.h>
32 #include <kernel/tee_common_otp.h>
33 #include <kernel/thread.h>
34 #include <mm/core_memprot.h>
35 #include <mm/tee_mm.h>
36 #include <optee_msg_supplicant.h>
39 #include <string_ext.h>
40 #include <sys/queue.h>
41 #include <tee/tee_cryp_provider.h>
42 #include <tee/tee_fs_defs.h>
43 #include <tee/tee_fs.h>
44 #include <tee/tee_fs_key_manager.h>
48 #define RPMB_STORAGE_START_ADDRESS 0
49 #define RPMB_FS_FAT_START_ADDRESS 512
50 #define RPMB_BLOCK_SIZE_SHIFT 8
52 #define RPMB_FS_MAGIC 0x52504D42
56 #define FILE_IS_ACTIVE (1u << 0)
57 #define FILE_IS_LAST_ENTRY (1u << 1)
59 #define TEE_RPMB_FS_FILENAME_LENGTH 224
62 * FS parameters: Information often used by internal functions.
63 * fat_start_address will be set by rpmb_fs_setup().
64 * rpmb_fs_parameters can be read by any other function.
66 struct rpmb_fs_parameters {
67 uint32_t fat_start_address;
68 uint32_t max_rpmb_address;
72 * File entry for a single file in a RPMB_FS partition.
74 struct rpmb_fat_entry {
75 uint32_t start_address;
78 uint32_t write_counter;
79 uint8_t fek[TEE_FS_KM_FEK_SIZE];
80 char filename[TEE_RPMB_FS_FILENAME_LENGTH];
84 * FAT entry context with reference to a FAT entry and its
87 struct rpmb_file_handle {
88 struct rpmb_fat_entry fat_entry;
89 char filename[TEE_RPMB_FS_FILENAME_LENGTH];
90 /* Address for current entry in RPMB */
91 uint32_t rpmb_fat_address;
92 /* Current position */
97 * RPMB_FS partition data
99 struct rpmb_fs_partition {
100 uint32_t rpmb_fs_magic;
102 uint32_t write_counter;
103 uint32_t fat_start_address;
104 /* Do not use reserved[] for other purpose than partition data. */
105 uint8_t reserved[112];
109 * A node in a list of directory entries. entry->name is a
110 * pointer to name here.
112 struct tee_rpmb_fs_dirent {
113 struct tee_fs_dirent entry;
114 char name[TEE_RPMB_FS_FILENAME_LENGTH];
116 SIMPLEQ_ENTRY(tee_rpmb_fs_dirent) link;
120 * The RPMB directory representation. It contains a queue of
121 * RPMB directory entries: 'next'.
122 * The current pointer points to the last directory entry
123 * returned by readdir().
126 struct tee_rpmb_fs_dirent *current;
128 SIMPLEQ_HEAD(next_head, tee_rpmb_fs_dirent) next;
131 static struct rpmb_fs_parameters *fs_par;
134 * Lower interface to RPMB device
137 #define RPMB_DATA_OFFSET (RPMB_STUFF_DATA_SIZE + RPMB_KEY_MAC_SIZE)
138 #define RPMB_MAC_PROTECT_DATA_SIZE (RPMB_DATA_FRAME_SIZE - RPMB_DATA_OFFSET)
140 #define RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM 0x0001
141 #define RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ 0x0002
142 #define RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE 0x0003
143 #define RPMB_MSG_TYPE_REQ_AUTH_DATA_READ 0x0004
144 #define RPMB_MSG_TYPE_REQ_RESULT_READ 0x0005
145 #define RPMB_MSG_TYPE_RESP_AUTH_KEY_PROGRAM 0x0100
146 #define RPMB_MSG_TYPE_RESP_WRITE_COUNTER_VAL_READ 0x0200
147 #define RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE 0x0300
148 #define RPMB_MSG_TYPE_RESP_AUTH_DATA_READ 0x0400
150 #define RPMB_STUFF_DATA_SIZE 196
151 #define RPMB_KEY_MAC_SIZE 32
152 #define RPMB_DATA_SIZE 256
153 #define RPMB_NONCE_SIZE 16
154 #define RPMB_DATA_FRAME_SIZE 512
156 #define RPMB_RESULT_OK 0x00
157 #define RPMB_RESULT_GENERAL_FAILURE 0x01
158 #define RPMB_RESULT_AUTH_FAILURE 0x02
159 #define RPMB_RESULT_COUNTER_FAILURE 0x03
160 #define RPMB_RESULT_ADDRESS_FAILURE 0x04
161 #define RPMB_RESULT_WRITE_FAILURE 0x05
162 #define RPMB_RESULT_READ_FAILURE 0x06
163 #define RPMB_RESULT_AUTH_KEY_NOT_PROGRAMMED 0x07
164 #define RPMB_RESULT_MASK 0x3F
165 #define RPMB_RESULT_WR_CNT_EXPIRED 0x80
167 /* RPMB internal commands */
168 #define RPMB_CMD_DATA_REQ 0x00
169 #define RPMB_CMD_GET_DEV_INFO 0x01
171 #define RPMB_SIZE_SINGLE (128 * 1024)
173 /* Error codes for get_dev_info request/response. */
174 #define RPMB_CMD_GET_DEV_INFO_RET_OK 0x00
175 #define RPMB_CMD_GET_DEV_INFO_RET_ERROR 0x01
177 struct rpmb_data_frame {
178 uint8_t stuff_bytes[RPMB_STUFF_DATA_SIZE];
179 uint8_t key_mac[RPMB_KEY_MAC_SIZE];
180 uint8_t data[RPMB_DATA_SIZE];
181 uint8_t nonce[RPMB_NONCE_SIZE];
182 uint8_t write_counter[4];
184 uint8_t block_count[2];
185 uint8_t op_result[2];
192 uint16_t block_count;
193 /* variable length of data */
194 /* uint8_t data[]; REMOVED! */
197 #define TEE_RPMB_REQ_DATA(req) \
198 ((void *)((struct rpmb_req *)(req) + 1))
200 struct rpmb_raw_data {
203 uint16_t *block_count;
205 uint32_t *write_counter;
209 /* data length to read or write */
211 /* Byte address offset in the first block involved */
215 #define RPMB_EMMC_CID_SIZE 16
216 struct rpmb_dev_info {
217 uint8_t cid[RPMB_EMMC_CID_SIZE];
218 /* EXT CSD-slice 168 "RPMB Size" */
219 uint8_t rpmb_size_mult;
220 /* EXT CSD-slice 222 "Reliable Write Sector Count" */
221 uint8_t rel_wr_sec_c;
222 /* Check the ret code and accept the data only if it is OK. */
227 * Struct for rpmb context data.
231 * @hash_ctx_size Hash context size
232 * @wr_cnt Current write counter.
233 * @max_blk_idx The highest block index supported by current device.
234 * @rel_wr_blkcnt Max number of data blocks for each reliable write.
235 * @dev_id Device ID of the eMMC device.
236 * @wr_cnt_synced Flag indicating if write counter is synced to RPMB.
237 * @key_derived Flag indicating if key has been generated.
238 * @key_verified Flag indicating the key generated is verified ok.
239 * @dev_info_synced Flag indicating if dev info has been retrieved from RPMB.
241 struct tee_rpmb_ctx {
242 uint8_t key[RPMB_KEY_MAC_SIZE];
243 uint8_t cid[RPMB_EMMC_CID_SIZE];
244 size_t hash_ctx_size;
246 uint16_t max_blk_idx;
247 uint16_t rel_wr_blkcnt;
252 bool dev_info_synced;
255 static struct tee_rpmb_ctx *rpmb_ctx;
258 * Mutex to serialize the operations exported by this file.
259 * It protects rpmb_ctx and prevents overlapping operations on eMMC devices with
262 static struct mutex rpmb_mutex = MUTEX_INITIALIZER;
264 #ifdef CFG_RPMB_TESTKEY
266 static const uint8_t rpmb_test_key[RPMB_KEY_MAC_SIZE] = {
267 0xD3, 0xEB, 0x3E, 0xC3, 0x6E, 0x33, 0x4C, 0x9F,
268 0x98, 0x8C, 0xE2, 0xC0, 0xB8, 0x59, 0x54, 0x61,
269 0x0D, 0x2B, 0xCF, 0x86, 0x64, 0x84, 0x4D, 0xF2,
270 0xAB, 0x56, 0xE6, 0xC6, 0x1B, 0xB7, 0x01, 0xE4
273 static TEE_Result tee_rpmb_key_gen(uint16_t dev_id __unused,
274 uint8_t *key, uint32_t len)
276 TEE_Result res = TEE_SUCCESS;
278 if (!key || RPMB_KEY_MAC_SIZE != len) {
279 res = TEE_ERROR_BAD_PARAMETERS;
283 DMSG("RPMB: Using test key");
284 memcpy(key, rpmb_test_key, RPMB_KEY_MAC_SIZE);
290 #else /* !CFG_RPMB_TESTKEY */
293 * NOTE: We need a common API to get hw unique key and it
294 * should return error when the hw unique is not a valid
295 * one as stated below.
296 * We need to make sure the hw unique we get is valid by:
297 * 1. In case of HUK is used, checking if OTP is hidden (in
298 * which case only zeros will be returned) or not;
299 * 2. In case of SSK is used, checking if SSK in OTP is
300 * write_locked (which means a valid key is provisioned)
303 * Maybe tee_get_hw_unique_key() should be exposed as
304 * generic API for getting hw unique key!
305 * We should change the API tee_otp_get_hw_unique_key()
306 * to return error code!
308 static TEE_Result tee_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
311 return TEE_ERROR_BAD_PARAMETERS;
313 tee_otp_get_hw_unique_key(hwkey);
318 static TEE_Result tee_rpmb_key_gen(uint16_t dev_id __unused,
319 uint8_t *key, uint32_t len)
322 struct tee_hw_unique_key hwkey;
325 if (!key || RPMB_KEY_MAC_SIZE != len) {
326 res = TEE_ERROR_BAD_PARAMETERS;
330 IMSG("RPMB: Using generated key");
331 res = tee_get_hw_unique_key(&hwkey);
332 if (res != TEE_SUCCESS)
335 ctx = malloc(rpmb_ctx->hash_ctx_size);
337 res = TEE_ERROR_OUT_OF_MEMORY;
341 res = crypto_ops.mac.init(ctx, TEE_ALG_HMAC_SHA256, hwkey.data,
342 HW_UNIQUE_KEY_LENGTH);
343 if (res != TEE_SUCCESS)
346 res = crypto_ops.mac.update(ctx, TEE_ALG_HMAC_SHA256,
347 (uint8_t *)rpmb_ctx->cid,
349 if (res != TEE_SUCCESS)
352 res = crypto_ops.mac.final(ctx, TEE_ALG_HMAC_SHA256, key, len);
359 #endif /* !CFG_RPMB_TESTKEY */
361 static void u32_to_bytes(uint32_t u32, uint8_t *bytes)
363 *bytes = (uint8_t) (u32 >> 24);
364 *(bytes + 1) = (uint8_t) (u32 >> 16);
365 *(bytes + 2) = (uint8_t) (u32 >> 8);
366 *(bytes + 3) = (uint8_t) u32;
369 static void bytes_to_u32(uint8_t *bytes, uint32_t *u32)
371 *u32 = (uint32_t) ((*(bytes) << 24) +
372 (*(bytes + 1) << 16) +
373 (*(bytes + 2) << 8) + (*(bytes + 3)));
376 static void u16_to_bytes(uint16_t u16, uint8_t *bytes)
378 *bytes = (uint8_t) (u16 >> 8);
379 *(bytes + 1) = (uint8_t) u16;
382 static void bytes_to_u16(uint8_t *bytes, uint16_t *u16)
384 *u16 = (uint16_t) ((*bytes << 8) + *(bytes + 1));
387 static TEE_Result tee_rpmb_mac_calc(uint8_t *mac, uint32_t macsize,
388 uint8_t *key, uint32_t keysize,
389 struct rpmb_data_frame *datafrms,
392 TEE_Result res = TEE_ERROR_GENERIC;
396 if (!mac || !key || !datafrms)
397 return TEE_ERROR_BAD_PARAMETERS;
399 ctx = malloc(rpmb_ctx->hash_ctx_size);
401 return TEE_ERROR_OUT_OF_MEMORY;
403 res = crypto_ops.mac.init(ctx, TEE_ALG_HMAC_SHA256, key, keysize);
404 if (res != TEE_SUCCESS)
407 for (i = 0; i < blkcnt; i++) {
408 res = crypto_ops.mac.update(ctx, TEE_ALG_HMAC_SHA256,
410 RPMB_MAC_PROTECT_DATA_SIZE);
411 if (res != TEE_SUCCESS)
415 res = crypto_ops.mac.final(ctx, TEE_ALG_HMAC_SHA256, mac, macsize);
416 if (res != TEE_SUCCESS)
426 struct tee_rpmb_mem {
428 uint64_t phreq_cookie;
430 uint64_t phresp_cookie;
435 static void tee_rpmb_free(struct tee_rpmb_mem *mem)
441 thread_rpc_free_payload(mem->phreq_cookie);
442 mem->phreq_cookie = 0;
446 thread_rpc_free_payload(mem->phresp_cookie);
447 mem->phresp_cookie = 0;
453 static TEE_Result tee_rpmb_alloc(size_t req_size, size_t resp_size,
454 struct tee_rpmb_mem *mem, void **req, void **resp)
456 TEE_Result res = TEE_SUCCESS;
457 size_t req_s = ROUNDUP(req_size, sizeof(uint32_t));
458 size_t resp_s = ROUNDUP(resp_size, sizeof(uint32_t));
461 return TEE_ERROR_BAD_PARAMETERS;
463 memset(mem, 0, sizeof(*mem));
464 thread_rpc_alloc_payload(req_s, &mem->phreq, &mem->phreq_cookie);
465 thread_rpc_alloc_payload(resp_s, &mem->phresp, &mem->phresp_cookie);
466 if (!mem->phreq || !mem->phresp) {
467 res = TEE_ERROR_OUT_OF_MEMORY;
471 *req = phys_to_virt(mem->phreq, MEM_AREA_NSEC_SHM);
472 *resp = phys_to_virt(mem->phresp, MEM_AREA_NSEC_SHM);
473 if (!*req || !*resp) {
474 res = TEE_ERROR_GENERIC;
478 mem->req_size = req_size;
479 mem->resp_size = resp_size;
482 if (res != TEE_SUCCESS)
487 static TEE_Result tee_rpmb_invoke(struct tee_rpmb_mem *mem)
489 struct optee_msg_param params[2];
491 memset(params, 0, sizeof(params));
492 params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
493 params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT;
494 params[0].u.tmem.buf_ptr = mem->phreq;
495 params[0].u.tmem.size = mem->req_size;
496 params[0].u.tmem.shm_ref = mem->phreq_cookie;
497 params[1].u.tmem.buf_ptr = mem->phresp;
498 params[1].u.tmem.size = mem->resp_size;
499 params[1].u.tmem.shm_ref = mem->phresp_cookie;
501 return thread_rpc_cmd(OPTEE_MSG_RPC_CMD_RPMB, 2, params);
504 static bool is_zero(const uint8_t *buf, size_t size)
508 for (i = 0; i < size; i++)
514 static TEE_Result encrypt_block(uint8_t *out, const uint8_t *in,
515 uint16_t blk_idx, const uint8_t *fek)
517 return tee_fs_crypt_block(out, in, RPMB_DATA_SIZE, blk_idx, fek,
521 static TEE_Result decrypt_block(uint8_t *out, const uint8_t *in,
522 uint16_t blk_idx, const uint8_t *fek)
524 return tee_fs_crypt_block(out, in, RPMB_DATA_SIZE, blk_idx, fek,
528 /* Decrypt/copy at most one block of data */
529 static TEE_Result decrypt(uint8_t *out, const struct rpmb_data_frame *frm,
530 size_t size, size_t offset,
531 uint16_t blk_idx __maybe_unused, const uint8_t *fek)
533 uint8_t *tmp __maybe_unused;
536 if ((size + offset < size) || (size + offset > RPMB_DATA_SIZE))
537 panic("invalid size or offset");
540 /* Block is not encrypted (not a file data block) */
541 memcpy(out, frm->data + offset, size);
542 } else if (is_zero(fek, TEE_FS_KM_FEK_SIZE)) {
543 /* The file was created with encryption disabled */
544 return TEE_ERROR_SECURITY;
546 /* Block is encrypted */
547 if (size < RPMB_DATA_SIZE) {
549 * Since output buffer is not large enough to hold one
550 * block we must allocate a temporary buffer.
552 tmp = malloc(RPMB_DATA_SIZE);
554 return TEE_ERROR_OUT_OF_MEMORY;
555 decrypt_block(tmp, frm->data, blk_idx, fek);
556 memcpy(out, tmp + offset, size);
559 decrypt_block(out, frm->data, blk_idx, fek);
566 static TEE_Result tee_rpmb_req_pack(struct rpmb_req *req,
567 struct rpmb_raw_data *rawdata,
568 uint16_t nbr_frms, uint16_t dev_id,
571 TEE_Result res = TEE_ERROR_GENERIC;
573 struct rpmb_data_frame *datafrm;
575 if (!req || !rawdata || !nbr_frms)
576 return TEE_ERROR_BAD_PARAMETERS;
579 * Check write blockcount is not bigger than reliable write
582 if ((rawdata->msg_type == RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE) &&
583 (nbr_frms > rpmb_ctx->rel_wr_blkcnt)) {
584 DMSG("wr_blkcnt(%d) > rel_wr_blkcnt(%d)", nbr_frms,
585 rpmb_ctx->rel_wr_blkcnt);
586 return TEE_ERROR_GENERIC;
589 req->cmd = RPMB_CMD_DATA_REQ;
590 req->dev_id = dev_id;
592 /* Allocate memory for construct all data packets and calculate MAC. */
593 datafrm = calloc(nbr_frms, RPMB_DATA_FRAME_SIZE);
595 return TEE_ERROR_OUT_OF_MEMORY;
597 for (i = 0; i < nbr_frms; i++) {
598 u16_to_bytes(rawdata->msg_type, datafrm[i].msg_type);
600 if (rawdata->block_count)
601 u16_to_bytes(*rawdata->block_count,
602 datafrm[i].block_count);
604 if (rawdata->blk_idx) {
605 /* Check the block index is within range. */
606 if ((*rawdata->blk_idx + nbr_frms) >
607 rpmb_ctx->max_blk_idx) {
608 res = TEE_ERROR_GENERIC;
611 u16_to_bytes(*rawdata->blk_idx, datafrm[i].address);
614 if (rawdata->write_counter)
615 u32_to_bytes(*rawdata->write_counter,
616 datafrm[i].write_counter);
619 memcpy(datafrm[i].nonce, rawdata->nonce,
624 encrypt_block(datafrm[i].data,
625 rawdata->data + (i * RPMB_DATA_SIZE),
626 *rawdata->blk_idx + i, fek);
628 memcpy(datafrm[i].data,
629 rawdata->data + (i * RPMB_DATA_SIZE),
634 if (rawdata->key_mac) {
635 if (rawdata->msg_type == RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE) {
637 tee_rpmb_mac_calc(rawdata->key_mac,
638 RPMB_KEY_MAC_SIZE, rpmb_ctx->key,
639 RPMB_KEY_MAC_SIZE, datafrm,
641 if (res != TEE_SUCCESS)
644 memcpy(datafrm[nbr_frms - 1].key_mac,
645 rawdata->key_mac, RPMB_KEY_MAC_SIZE);
648 memcpy(TEE_RPMB_REQ_DATA(req), datafrm,
649 nbr_frms * RPMB_DATA_FRAME_SIZE);
651 #ifdef CFG_RPMB_FS_DEBUG_DATA
652 for (i = 0; i < nbr_frms; i++) {
653 DMSG("Dumping data frame %d:", i);
654 DHEXDUMP((uint8_t *)&datafrm[i] + RPMB_STUFF_DATA_SIZE,
655 512 - RPMB_STUFF_DATA_SIZE);
665 static TEE_Result data_cpy_mac_calc_1b(struct rpmb_raw_data *rawdata,
666 struct rpmb_data_frame *frm,
673 if (rawdata->len + rawdata->byte_offset > RPMB_DATA_SIZE)
674 return TEE_ERROR_BAD_PARAMETERS;
676 res = tee_rpmb_mac_calc(rawdata->key_mac, RPMB_KEY_MAC_SIZE,
677 rpmb_ctx->key, RPMB_KEY_MAC_SIZE, frm, 1);
678 if (res != TEE_SUCCESS)
681 data = rawdata->data;
682 bytes_to_u16(frm->address, &idx);
684 res = decrypt(data, frm, rawdata->len, rawdata->byte_offset, idx, fek);
688 static TEE_Result tee_rpmb_data_cpy_mac_calc(struct rpmb_data_frame *datafrm,
689 struct rpmb_raw_data *rawdata,
691 struct rpmb_data_frame *lastfrm,
694 TEE_Result res = TEE_ERROR_GENERIC;
701 struct rpmb_data_frame localfrm;
703 if (!datafrm || !rawdata || !nbr_frms || !lastfrm)
704 return TEE_ERROR_BAD_PARAMETERS;
707 return data_cpy_mac_calc_1b(rawdata, lastfrm, fek);
711 data = rawdata->data;
713 ctx = malloc(rpmb_ctx->hash_ctx_size);
715 res = TEE_ERROR_OUT_OF_MEMORY;
719 res = crypto_ops.mac.init(ctx, TEE_ALG_HMAC_SHA256, rpmb_ctx->key,
721 if (res != TEE_SUCCESS)
725 * Note: JEDEC JESD84-B51: "In every packet the address is the start
726 * address of the full access (not address of the individual half a
729 bytes_to_u16(lastfrm->address, &start_idx);
731 for (i = 0; i < (nbr_frms - 1); i++) {
734 * By working on a local copy of the RPMB frame, we ensure that
735 * the data can not be modified after the MAC is computed but
736 * before the payload is decrypted/copied to the output buffer.
738 memcpy(&localfrm, &datafrm[i], RPMB_DATA_FRAME_SIZE);
740 res = crypto_ops.mac.update(ctx, TEE_ALG_HMAC_SHA256,
742 RPMB_MAC_PROTECT_DATA_SIZE);
743 if (res != TEE_SUCCESS)
748 offset = rawdata->byte_offset;
749 size = RPMB_DATA_SIZE - offset;
752 size = RPMB_DATA_SIZE;
756 res = decrypt(data, &localfrm, size, offset, start_idx + i,
758 if (res != TEE_SUCCESS)
765 size = (rawdata->len + rawdata->byte_offset) % RPMB_DATA_SIZE;
767 size = RPMB_DATA_SIZE;
768 res = decrypt(data, lastfrm, size, 0, start_idx + nbr_frms - 1, fek);
769 if (res != TEE_SUCCESS)
772 /* Update MAC against the last block */
773 res = crypto_ops.mac.update(ctx, TEE_ALG_HMAC_SHA256, lastfrm->data,
774 RPMB_MAC_PROTECT_DATA_SIZE);
775 if (res != TEE_SUCCESS)
778 res = crypto_ops.mac.final(ctx, TEE_ALG_HMAC_SHA256, rawdata->key_mac,
780 if (res != TEE_SUCCESS)
790 static TEE_Result tee_rpmb_resp_unpack_verify(struct rpmb_data_frame *datafrm,
791 struct rpmb_raw_data *rawdata,
792 uint16_t nbr_frms, uint8_t *fek)
794 TEE_Result res = TEE_ERROR_GENERIC;
799 struct rpmb_data_frame lastfrm;
801 if (!datafrm || !rawdata || !nbr_frms)
802 return TEE_ERROR_BAD_PARAMETERS;
804 #ifdef CFG_RPMB_FS_DEBUG_DATA
805 for (uint32_t i = 0; i < nbr_frms; i++) {
806 DMSG("Dumping data frame %d:", i);
807 DHEXDUMP((uint8_t *)&datafrm[i] + RPMB_STUFF_DATA_SIZE,
808 512 - RPMB_STUFF_DATA_SIZE);
812 /* Make sure the last data packet can't be modified once verified */
813 memcpy(&lastfrm, &datafrm[nbr_frms - 1], RPMB_DATA_FRAME_SIZE);
815 /* Handle operation result and translate to TEEC error code. */
816 bytes_to_u16(lastfrm.op_result, &op_result);
817 if (rawdata->op_result)
818 *rawdata->op_result = op_result;
819 if (op_result != RPMB_RESULT_OK)
820 return TEE_ERROR_GENERIC;
822 /* Check the response msg_type. */
823 bytes_to_u16(lastfrm.msg_type, &msg_type);
824 if (msg_type != rawdata->msg_type) {
825 DMSG("Unexpected msg_type (0x%04x != 0x%04x)", msg_type,
827 return TEE_ERROR_GENERIC;
830 if (rawdata->blk_idx) {
831 bytes_to_u16(lastfrm.address, &blk_idx);
832 if (blk_idx != *rawdata->blk_idx) {
833 DMSG("Unexpected block index");
834 return TEE_ERROR_GENERIC;
838 if (rawdata->write_counter) {
839 wr_cnt = *rawdata->write_counter;
840 bytes_to_u32(lastfrm.write_counter, rawdata->write_counter);
841 if (msg_type == RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE) {
842 /* Verify the write counter is incremented by 1 */
843 if (*rawdata->write_counter != wr_cnt + 1) {
844 DMSG("Counter mismatched (0x%04x/0x%04x)",
845 *rawdata->write_counter, wr_cnt + 1);
846 return TEE_ERROR_SECURITY;
852 if (rawdata->nonce) {
853 if (buf_compare_ct(rawdata->nonce, lastfrm.nonce,
854 RPMB_NONCE_SIZE) != 0) {
855 DMSG("Nonce mismatched");
856 return TEE_ERROR_SECURITY;
860 if (rawdata->key_mac) {
861 if (msg_type == RPMB_MSG_TYPE_RESP_AUTH_DATA_READ) {
863 return TEE_ERROR_GENERIC;
865 res = tee_rpmb_data_cpy_mac_calc(datafrm, rawdata,
869 if (res != TEE_SUCCESS)
873 * There should be only one data frame for
877 return TEE_ERROR_GENERIC;
879 res = tee_rpmb_mac_calc(rawdata->key_mac,
885 if (res != TEE_SUCCESS)
889 #ifndef CFG_RPMB_FS_NO_MAC
890 if (buf_compare_ct(rawdata->key_mac,
891 (datafrm + nbr_frms - 1)->key_mac,
892 RPMB_KEY_MAC_SIZE) != 0) {
893 DMSG("MAC mismatched:");
894 #ifdef CFG_RPMB_FS_DEBUG_DATA
895 DHEXDUMP((uint8_t *)rawdata->key_mac, 32);
897 return TEE_ERROR_SECURITY;
899 #endif /* !CFG_RPMB_FS_NO_MAC */
905 static TEE_Result tee_rpmb_get_dev_info(uint16_t dev_id,
906 struct rpmb_dev_info *dev_info)
908 TEE_Result res = TEE_ERROR_GENERIC;
909 struct tee_rpmb_mem mem;
910 struct rpmb_dev_info *di;
911 struct rpmb_req *req = NULL;
912 uint8_t *resp = NULL;
917 return TEE_ERROR_BAD_PARAMETERS;
919 req_size = sizeof(struct rpmb_req);
920 resp_size = sizeof(struct rpmb_dev_info);
921 res = tee_rpmb_alloc(req_size, resp_size, &mem,
922 (void *)&req, (void *)&resp);
923 if (res != TEE_SUCCESS)
926 req->cmd = RPMB_CMD_GET_DEV_INFO;
927 req->dev_id = dev_id;
929 di = (struct rpmb_dev_info *)resp;
930 di->ret_code = RPMB_CMD_GET_DEV_INFO_RET_ERROR;
932 res = tee_rpmb_invoke(&mem);
933 if (res != TEE_SUCCESS)
936 if (di->ret_code != RPMB_CMD_GET_DEV_INFO_RET_OK) {
937 res = TEE_ERROR_GENERIC;
941 memcpy((uint8_t *)dev_info, resp, sizeof(struct rpmb_dev_info));
943 #ifdef CFG_RPMB_FS_DEBUG_DATA
944 DMSG("Dumping dev_info:");
945 DHEXDUMP((uint8_t *)dev_info, sizeof(struct rpmb_dev_info));
955 static TEE_Result tee_rpmb_init_read_wr_cnt(uint16_t dev_id,
959 TEE_Result res = TEE_ERROR_GENERIC;
960 struct tee_rpmb_mem mem;
962 uint8_t nonce[RPMB_NONCE_SIZE];
963 uint8_t hmac[RPMB_KEY_MAC_SIZE];
964 struct rpmb_req *req = NULL;
965 struct rpmb_data_frame *resp = NULL;
966 struct rpmb_raw_data rawdata;
971 return TEE_ERROR_BAD_PARAMETERS;
973 req_size = sizeof(struct rpmb_req) + RPMB_DATA_FRAME_SIZE;
974 resp_size = RPMB_DATA_FRAME_SIZE;
975 res = tee_rpmb_alloc(req_size, resp_size, &mem,
976 (void *)&req, (void *)&resp);
977 if (res != TEE_SUCCESS)
980 res = crypto_ops.prng.read(nonce, RPMB_NONCE_SIZE);
981 if (res != TEE_SUCCESS)
984 msg_type = RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ;
986 memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data));
987 rawdata.msg_type = msg_type;
988 rawdata.nonce = nonce;
990 res = tee_rpmb_req_pack(req, &rawdata, 1, dev_id, NULL);
991 if (res != TEE_SUCCESS)
994 res = tee_rpmb_invoke(&mem);
995 if (res != TEE_SUCCESS)
998 msg_type = RPMB_MSG_TYPE_RESP_WRITE_COUNTER_VAL_READ;
1000 memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data));
1001 rawdata.msg_type = msg_type;
1002 rawdata.op_result = op_result;
1003 rawdata.write_counter = wr_cnt;
1004 rawdata.nonce = nonce;
1005 rawdata.key_mac = hmac;
1007 res = tee_rpmb_resp_unpack_verify(resp, &rawdata, 1, NULL);
1008 if (res != TEE_SUCCESS)
1014 tee_rpmb_free(&mem);
1018 static TEE_Result tee_rpmb_verify_key_sync_counter(uint16_t dev_id)
1020 uint16_t op_result = 0;
1021 TEE_Result res = TEE_ERROR_GENERIC;
1023 res = tee_rpmb_init_read_wr_cnt(dev_id, &rpmb_ctx->wr_cnt,
1026 if (res == TEE_SUCCESS) {
1027 rpmb_ctx->key_verified = true;
1028 rpmb_ctx->wr_cnt_synced = true;
1031 DMSG("Verify key returning 0x%x\n", res);
1035 #ifdef CFG_RPMB_WRITE_KEY
1036 static TEE_Result tee_rpmb_write_key(uint16_t dev_id)
1038 TEE_Result res = TEE_ERROR_GENERIC;
1039 struct tee_rpmb_mem mem = { 0 };
1041 struct rpmb_req *req = NULL;
1042 struct rpmb_data_frame *resp = NULL;
1043 struct rpmb_raw_data rawdata;
1047 req_size = sizeof(struct rpmb_req) + RPMB_DATA_FRAME_SIZE;
1048 resp_size = RPMB_DATA_FRAME_SIZE;
1049 res = tee_rpmb_alloc(req_size, resp_size, &mem,
1050 (void *)&req, (void *)&resp);
1051 if (res != TEE_SUCCESS)
1054 msg_type = RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM;
1056 memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data));
1057 rawdata.msg_type = msg_type;
1058 rawdata.key_mac = rpmb_ctx->key;
1060 res = tee_rpmb_req_pack(req, &rawdata, 1, dev_id, NULL);
1061 if (res != TEE_SUCCESS)
1064 res = tee_rpmb_invoke(&mem);
1065 if (res != TEE_SUCCESS)
1068 msg_type = RPMB_MSG_TYPE_RESP_AUTH_KEY_PROGRAM;
1070 memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data));
1071 rawdata.msg_type = msg_type;
1073 res = tee_rpmb_resp_unpack_verify(resp, &rawdata, 1, NULL);
1074 if (res != TEE_SUCCESS)
1080 tee_rpmb_free(&mem);
1084 static TEE_Result tee_rpmb_write_and_verify_key(uint16_t dev_id)
1088 DMSG("RPMB INIT: Writing Key");
1089 res = tee_rpmb_write_key(dev_id);
1090 if (res == TEE_SUCCESS) {
1091 DMSG("RPMB INIT: Verifying Key");
1092 res = tee_rpmb_verify_key_sync_counter(dev_id);
1097 static TEE_Result tee_rpmb_write_and_verify_key(uint16_t dev_id __unused)
1099 return TEE_ERROR_BAD_STATE;
1103 /* True when all the required crypto functions are available */
1104 static bool have_crypto_ops(void)
1106 return (crypto_ops.mac.init && crypto_ops.mac.update &&
1107 crypto_ops.mac.final && crypto_ops.prng.read);
1110 /* This function must never return TEE_SUCCESS if rpmb_ctx == NULL */
1111 static TEE_Result tee_rpmb_init(uint16_t dev_id)
1113 TEE_Result res = TEE_SUCCESS;
1114 struct rpmb_dev_info dev_info;
1116 if (!have_crypto_ops())
1117 return TEE_ERROR_NOT_SUPPORTED;
1120 rpmb_ctx = calloc(1, sizeof(struct tee_rpmb_ctx));
1122 return TEE_ERROR_OUT_OF_MEMORY;
1123 } else if (rpmb_ctx->dev_id != dev_id) {
1124 memset(rpmb_ctx, 0x00, sizeof(struct tee_rpmb_ctx));
1127 rpmb_ctx->dev_id = dev_id;
1129 if (!rpmb_ctx->dev_info_synced) {
1130 DMSG("RPMB: Syncing device information");
1132 dev_info.rpmb_size_mult = 0;
1133 dev_info.rel_wr_sec_c = 0;
1134 res = tee_rpmb_get_dev_info(dev_id, &dev_info);
1135 if (res != TEE_SUCCESS)
1138 DMSG("RPMB: RPMB size is %d*128 KB", dev_info.rpmb_size_mult);
1139 DMSG("RPMB: Reliable Write Sector Count is %d",
1140 dev_info.rel_wr_sec_c);
1142 if (dev_info.rpmb_size_mult == 0) {
1143 res = TEE_ERROR_GENERIC;
1147 rpmb_ctx->max_blk_idx = (dev_info.rpmb_size_mult *
1148 RPMB_SIZE_SINGLE / RPMB_DATA_SIZE) - 1;
1150 memcpy(rpmb_ctx->cid, dev_info.cid, RPMB_EMMC_CID_SIZE);
1152 if ((rpmb_ctx->hash_ctx_size == 0) &&
1153 (crypto_ops.mac.get_ctx_size(
1154 TEE_ALG_HMAC_SHA256,
1155 &rpmb_ctx->hash_ctx_size))) {
1156 rpmb_ctx->hash_ctx_size = 0;
1157 res = TEE_ERROR_GENERIC;
1161 #ifdef RPMB_DRIVER_MULTIPLE_WRITE_FIXED
1162 rpmb_ctx->rel_wr_blkcnt = dev_info.rel_wr_sec_c * 2;
1164 rpmb_ctx->rel_wr_blkcnt = 1;
1167 rpmb_ctx->dev_info_synced = true;
1170 if (!rpmb_ctx->key_derived) {
1171 DMSG("RPMB INIT: Deriving key");
1173 res = tee_rpmb_key_gen(dev_id, rpmb_ctx->key,
1175 if (res != TEE_SUCCESS)
1178 rpmb_ctx->key_derived = true;
1181 /* Perform a write counter read to verify if the key is ok. */
1182 if (!rpmb_ctx->wr_cnt_synced || !rpmb_ctx->key_verified) {
1183 DMSG("RPMB INIT: Verifying Key");
1185 res = tee_rpmb_verify_key_sync_counter(dev_id);
1186 if (res != TEE_SUCCESS && !rpmb_ctx->key_verified) {
1188 * Need to write the key here and verify it.
1190 res = tee_rpmb_write_and_verify_key(dev_id);
1199 * Read RPMB data in bytes.
1201 * @dev_id Device ID of the eMMC device.
1202 * @addr Byte address of data.
1203 * @data Pointer to the data.
1204 * @len Size of data in bytes.
1205 * @fek Encrypted File Encryption Key or NULL.
1207 static TEE_Result tee_rpmb_read(uint16_t dev_id, uint32_t addr, uint8_t *data,
1208 uint32_t len, uint8_t *fek)
1210 TEE_Result res = TEE_ERROR_GENERIC;
1211 struct tee_rpmb_mem mem = { 0 };
1213 uint8_t nonce[RPMB_NONCE_SIZE];
1214 uint8_t hmac[RPMB_KEY_MAC_SIZE];
1215 struct rpmb_req *req = NULL;
1216 struct rpmb_data_frame *resp = NULL;
1217 struct rpmb_raw_data rawdata;
1222 uint8_t byte_offset;
1225 return TEE_ERROR_BAD_PARAMETERS;
1227 blk_idx = addr / RPMB_DATA_SIZE;
1228 byte_offset = addr % RPMB_DATA_SIZE;
1231 ROUNDUP(len + byte_offset, RPMB_DATA_SIZE) / RPMB_DATA_SIZE;
1232 res = tee_rpmb_init(dev_id);
1233 if (res != TEE_SUCCESS)
1236 req_size = sizeof(struct rpmb_req) + RPMB_DATA_FRAME_SIZE;
1237 resp_size = RPMB_DATA_FRAME_SIZE * blkcnt;
1238 res = tee_rpmb_alloc(req_size, resp_size, &mem,
1239 (void *)&req, (void *)&resp);
1240 if (res != TEE_SUCCESS)
1243 msg_type = RPMB_MSG_TYPE_REQ_AUTH_DATA_READ;
1244 res = crypto_ops.prng.read(nonce, RPMB_NONCE_SIZE);
1245 if (res != TEE_SUCCESS)
1248 memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data));
1249 rawdata.msg_type = msg_type;
1250 rawdata.nonce = nonce;
1251 rawdata.blk_idx = &blk_idx;
1252 res = tee_rpmb_req_pack(req, &rawdata, 1, dev_id, NULL);
1253 if (res != TEE_SUCCESS)
1256 req->block_count = blkcnt;
1258 DMSG("Read %u block%s at index %u", blkcnt, ((blkcnt > 1) ? "s" : ""),
1261 res = tee_rpmb_invoke(&mem);
1262 if (res != TEE_SUCCESS)
1265 msg_type = RPMB_MSG_TYPE_RESP_AUTH_DATA_READ;
1267 memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data));
1268 rawdata.msg_type = msg_type;
1269 rawdata.block_count = &blkcnt;
1270 rawdata.blk_idx = &blk_idx;
1271 rawdata.nonce = nonce;
1272 rawdata.key_mac = hmac;
1273 rawdata.data = data;
1276 rawdata.byte_offset = byte_offset;
1278 res = tee_rpmb_resp_unpack_verify(resp, &rawdata, blkcnt, fek);
1279 if (res != TEE_SUCCESS)
1285 tee_rpmb_free(&mem);
1289 static TEE_Result tee_rpmb_write_blk(uint16_t dev_id, uint16_t blk_idx,
1290 const uint8_t *data_blks, uint16_t blkcnt,
1294 struct tee_rpmb_mem mem;
1297 uint8_t hmac[RPMB_KEY_MAC_SIZE];
1298 struct rpmb_req *req = NULL;
1299 struct rpmb_data_frame *resp = NULL;
1300 struct rpmb_raw_data rawdata;
1303 uint32_t nbr_writes;
1304 uint16_t tmp_blkcnt;
1305 uint16_t tmp_blk_idx;
1308 DMSG("Write %u block%s at index %u", blkcnt, ((blkcnt > 1) ? "s" : ""),
1311 if (!data_blks || !blkcnt)
1312 return TEE_ERROR_BAD_PARAMETERS;
1314 res = tee_rpmb_init(dev_id);
1315 if (res != TEE_SUCCESS)
1319 * We need to split data when block count
1320 * is bigger than reliable block write count.
1322 if (blkcnt < rpmb_ctx->rel_wr_blkcnt)
1323 req_size = sizeof(struct rpmb_req) +
1324 RPMB_DATA_FRAME_SIZE * blkcnt;
1326 req_size = sizeof(struct rpmb_req) +
1327 RPMB_DATA_FRAME_SIZE * rpmb_ctx->rel_wr_blkcnt;
1329 resp_size = RPMB_DATA_FRAME_SIZE;
1330 res = tee_rpmb_alloc(req_size, resp_size, &mem,
1331 (void *)&req, (void *)&resp);
1332 if (res != TEE_SUCCESS)
1335 nbr_writes = blkcnt / rpmb_ctx->rel_wr_blkcnt;
1336 if (blkcnt % rpmb_ctx->rel_wr_blkcnt > 0)
1339 tmp_blkcnt = rpmb_ctx->rel_wr_blkcnt;
1340 tmp_blk_idx = blk_idx;
1341 for (i = 0; i < nbr_writes; i++) {
1343 * To handle the last write of block count which is
1344 * equal or smaller than reliable write block count.
1346 if (i == nbr_writes - 1)
1347 tmp_blkcnt = blkcnt - rpmb_ctx->rel_wr_blkcnt *
1350 msg_type = RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE;
1351 wr_cnt = rpmb_ctx->wr_cnt;
1353 memset(req, 0x00, req_size);
1354 memset(resp, 0x00, resp_size);
1356 memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data));
1357 rawdata.msg_type = msg_type;
1358 rawdata.block_count = &tmp_blkcnt;
1359 rawdata.blk_idx = &tmp_blk_idx;
1360 rawdata.write_counter = &wr_cnt;
1361 rawdata.key_mac = hmac;
1362 rawdata.data = (uint8_t *)data_blks +
1363 i * rpmb_ctx->rel_wr_blkcnt * RPMB_DATA_SIZE;
1365 res = tee_rpmb_req_pack(req, &rawdata, tmp_blkcnt, dev_id,
1367 if (res != TEE_SUCCESS)
1370 res = tee_rpmb_invoke(&mem);
1371 if (res != TEE_SUCCESS) {
1373 * To force wr_cnt sync next time, as it might get
1374 * out of sync due to inconsistent operation result!
1376 rpmb_ctx->wr_cnt_synced = false;
1380 msg_type = RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE;
1382 memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data));
1383 rawdata.msg_type = msg_type;
1384 rawdata.block_count = &tmp_blkcnt;
1385 rawdata.blk_idx = &tmp_blk_idx;
1386 rawdata.write_counter = &wr_cnt;
1387 rawdata.key_mac = hmac;
1389 res = tee_rpmb_resp_unpack_verify(resp, &rawdata, 1, NULL);
1390 if (res != TEE_SUCCESS) {
1392 * To force wr_cnt sync next time, as it might get
1393 * out of sync due to inconsistent operation result!
1395 rpmb_ctx->wr_cnt_synced = false;
1399 tmp_blk_idx += tmp_blkcnt;
1403 tee_rpmb_free(&mem);
1407 static bool tee_rpmb_write_is_atomic(uint16_t dev_id __unused, uint32_t addr,
1410 uint8_t byte_offset = addr % RPMB_DATA_SIZE;
1411 uint16_t blkcnt = ROUNDUP(len + byte_offset,
1412 RPMB_DATA_SIZE) / RPMB_DATA_SIZE;
1414 return (blkcnt <= rpmb_ctx->rel_wr_blkcnt);
1418 * Write RPMB data in bytes.
1420 * @dev_id Device ID of the eMMC device.
1421 * @addr Byte address of data.
1422 * @data Pointer to the data.
1423 * @len Size of data in bytes.
1424 * @fek Encrypted File Encryption Key or NULL.
1426 static TEE_Result tee_rpmb_write(uint16_t dev_id, uint32_t addr,
1427 const uint8_t *data, uint32_t len,
1430 TEE_Result res = TEE_ERROR_GENERIC;
1431 uint8_t *data_tmp = NULL;
1434 uint8_t byte_offset;
1436 blk_idx = addr / RPMB_DATA_SIZE;
1437 byte_offset = addr % RPMB_DATA_SIZE;
1440 ROUNDUP(len + byte_offset, RPMB_DATA_SIZE) / RPMB_DATA_SIZE;
1442 if (byte_offset == 0 && (len % RPMB_DATA_SIZE) == 0) {
1443 res = tee_rpmb_write_blk(dev_id, blk_idx, data, blkcnt, fek);
1444 if (res != TEE_SUCCESS)
1447 data_tmp = calloc(blkcnt, RPMB_DATA_SIZE);
1449 res = TEE_ERROR_OUT_OF_MEMORY;
1453 /* Read the complete blocks */
1454 res = tee_rpmb_read(dev_id, blk_idx * RPMB_DATA_SIZE, data_tmp,
1455 blkcnt * RPMB_DATA_SIZE, fek);
1456 if (res != TEE_SUCCESS)
1459 /* Partial update of the data blocks */
1460 memcpy(data_tmp + byte_offset, data, len);
1462 res = tee_rpmb_write_blk(dev_id, blk_idx, data_tmp, blkcnt,
1464 if (res != TEE_SUCCESS)
1476 * Read the RPMB write counter.
1478 * @dev_id Device ID of the eMMC device.
1479 * @counter Pointer to the counter.
1481 static TEE_Result tee_rpmb_get_write_counter(uint16_t dev_id,
1484 TEE_Result res = TEE_SUCCESS;
1487 return TEE_ERROR_BAD_PARAMETERS;
1489 if (!rpmb_ctx || !rpmb_ctx->wr_cnt_synced) {
1490 res = tee_rpmb_init(dev_id);
1491 if (res != TEE_SUCCESS)
1495 *counter = rpmb_ctx->wr_cnt;
1502 * Read the RPMB max block.
1504 * @dev_id Device ID of the eMMC device.
1505 * @counter Pointer to receive the max block.
1507 static TEE_Result tee_rpmb_get_max_block(uint16_t dev_id, uint32_t *max_block)
1509 TEE_Result res = TEE_SUCCESS;
1512 return TEE_ERROR_BAD_PARAMETERS;
1514 if (!rpmb_ctx || !rpmb_ctx->dev_info_synced) {
1515 res = tee_rpmb_init(dev_id);
1516 if (res != TEE_SUCCESS)
1520 *max_block = rpmb_ctx->max_blk_idx;
1527 * End of lower interface to RPMB device
1530 static TEE_Result get_fat_start_address(uint32_t *addr);
1532 static void dump_fat(void)
1534 TEE_Result res = TEE_ERROR_GENERIC;
1535 struct rpmb_fat_entry *fat_entries = NULL;
1536 uint32_t fat_address;
1539 bool last_entry_found = false;
1541 res = get_fat_start_address(&fat_address);
1542 if (res != TEE_SUCCESS)
1545 size = N_ENTRIES * sizeof(struct rpmb_fat_entry);
1546 fat_entries = malloc(size);
1548 res = TEE_ERROR_OUT_OF_MEMORY;
1552 while (!last_entry_found) {
1553 res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, fat_address,
1554 (uint8_t *)fat_entries, size, NULL);
1555 if (res != TEE_SUCCESS)
1558 for (i = 0; i < N_ENTRIES; i++) {
1560 FMSG("flags 0x%x, size %d, address 0x%x, filename '%s'",
1561 fat_entries[i].flags,
1562 fat_entries[i].data_size,
1563 fat_entries[i].start_address,
1564 fat_entries[i].filename);
1566 if ((fat_entries[i].flags & FILE_IS_LAST_ENTRY) != 0) {
1567 last_entry_found = true;
1571 /* Move to next fat_entry. */
1572 fat_address += sizeof(struct rpmb_fat_entry);
1580 #if (TRACE_LEVEL >= TRACE_DEBUG)
1581 static void dump_fh(struct rpmb_file_handle *fh)
1583 DMSG("fh->filename=%s", fh->filename);
1584 DMSG("fh->pos=%u", fh->pos);
1585 DMSG("fh->rpmb_fat_address=%u", fh->rpmb_fat_address);
1586 DMSG("fh->fat_entry.start_address=%u", fh->fat_entry.start_address);
1587 DMSG("fh->fat_entry.data_size=%u", fh->fat_entry.data_size);
1590 static void dump_fh(struct rpmb_file_handle *fh __unused)
1595 static struct rpmb_file_handle *alloc_file_handle(const char *filename)
1597 struct rpmb_file_handle *fh = NULL;
1599 fh = calloc(1, sizeof(struct rpmb_file_handle));
1604 strlcpy(fh->filename, filename, sizeof(fh->filename));
1610 * write_fat_entry: Store info in a fat_entry to RPMB.
1612 static TEE_Result write_fat_entry(struct rpmb_file_handle *fh,
1613 bool update_write_counter)
1615 TEE_Result res = TEE_ERROR_GENERIC;
1617 /* Protect partition data. */
1618 if (fh->rpmb_fat_address < sizeof(struct rpmb_fs_partition)) {
1619 res = TEE_ERROR_ACCESS_CONFLICT;
1623 if (fh->rpmb_fat_address % sizeof(struct rpmb_fat_entry) != 0) {
1624 res = TEE_ERROR_BAD_PARAMETERS;
1628 if (update_write_counter) {
1629 res = tee_rpmb_get_write_counter(CFG_RPMB_FS_DEV_ID,
1630 &fh->fat_entry.write_counter);
1631 if (res != TEE_SUCCESS)
1635 res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, fh->rpmb_fat_address,
1636 (uint8_t *)&fh->fat_entry,
1637 sizeof(struct rpmb_fat_entry), NULL);
1646 * rpmb_fs_setup: Setup rpmb fs.
1647 * Set initial partition and FS values and write to RPMB.
1648 * Store frequently used data in RAM.
1650 static TEE_Result rpmb_fs_setup(void)
1652 TEE_Result res = TEE_ERROR_GENERIC;
1653 struct rpmb_fs_partition *partition_data = NULL;
1654 struct rpmb_file_handle *fh = NULL;
1655 uint32_t max_rpmb_block = 0;
1662 res = tee_rpmb_get_max_block(CFG_RPMB_FS_DEV_ID, &max_rpmb_block);
1663 if (res != TEE_SUCCESS)
1666 partition_data = calloc(1, sizeof(struct rpmb_fs_partition));
1667 if (!partition_data) {
1668 res = TEE_ERROR_OUT_OF_MEMORY;
1672 res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS,
1673 (uint8_t *)partition_data,
1674 sizeof(struct rpmb_fs_partition), NULL);
1675 if (res != TEE_SUCCESS)
1678 #ifndef CFG_RPMB_RESET_FAT
1679 if (partition_data->rpmb_fs_magic == RPMB_FS_MAGIC) {
1680 if (partition_data->fs_version == FS_VERSION) {
1684 /* Wrong software is in use. */
1685 res = TEE_ERROR_ACCESS_DENIED;
1690 EMSG("**** Clearing Storage ****");
1693 /* Setup new partition data. */
1694 partition_data->rpmb_fs_magic = RPMB_FS_MAGIC;
1695 partition_data->fs_version = FS_VERSION;
1696 partition_data->fat_start_address = RPMB_FS_FAT_START_ADDRESS;
1698 /* Initial FAT entry with FILE_IS_LAST_ENTRY flag set. */
1699 fh = alloc_file_handle(NULL);
1701 res = TEE_ERROR_OUT_OF_MEMORY;
1704 fh->fat_entry.flags = FILE_IS_LAST_ENTRY;
1705 fh->rpmb_fat_address = partition_data->fat_start_address;
1707 /* Write init FAT entry and partition data to RPMB. */
1708 res = write_fat_entry(fh, true);
1709 if (res != TEE_SUCCESS)
1713 tee_rpmb_get_write_counter(CFG_RPMB_FS_DEV_ID,
1714 &partition_data->write_counter);
1715 if (res != TEE_SUCCESS)
1717 res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS,
1718 (uint8_t *)partition_data,
1719 sizeof(struct rpmb_fs_partition), NULL);
1721 #ifndef CFG_RPMB_RESET_FAT
1725 /* Store FAT start address. */
1726 fs_par = calloc(1, sizeof(struct rpmb_fs_parameters));
1728 res = TEE_ERROR_OUT_OF_MEMORY;
1732 fs_par->fat_start_address = partition_data->fat_start_address;
1733 fs_par->max_rpmb_address = max_rpmb_block << RPMB_BLOCK_SIZE_SHIFT;
1739 free(partition_data);
1744 * get_fat_start_address:
1745 * FAT start_address from fs_par.
1747 static TEE_Result get_fat_start_address(uint32_t *addr)
1750 return TEE_ERROR_NO_DATA;
1752 *addr = fs_par->fat_start_address;
1758 * read_fat: Read FAT entries
1759 * Return matching FAT entry for read, rm rename and stat.
1760 * Build up memory pool and return matching entry for write operation.
1761 * "Last FAT entry" can be returned during write.
1763 static TEE_Result read_fat(struct rpmb_file_handle *fh, tee_mm_pool_t *p)
1765 TEE_Result res = TEE_ERROR_GENERIC;
1766 tee_mm_entry_t *mm = NULL;
1767 struct rpmb_fat_entry *fat_entries = NULL;
1768 uint32_t fat_address;
1771 bool entry_found = false;
1772 bool last_entry_found = false;
1773 bool expand_fat = false;
1774 struct rpmb_file_handle last_fh;
1776 DMSG("fat_address %d", fh->rpmb_fat_address);
1778 res = rpmb_fs_setup();
1779 if (res != TEE_SUCCESS)
1782 res = get_fat_start_address(&fat_address);
1783 if (res != TEE_SUCCESS)
1786 size = N_ENTRIES * sizeof(struct rpmb_fat_entry);
1787 fat_entries = malloc(size);
1789 res = TEE_ERROR_OUT_OF_MEMORY;
1794 * The pool is used to represent the current RPMB layout. To find
1795 * a slot for the file tee_mm_alloc is called on the pool. Thus
1796 * if it is not NULL the entire FAT must be traversed to fill in
1799 while (!last_entry_found && (!entry_found || p)) {
1800 res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, fat_address,
1801 (uint8_t *)fat_entries, size, NULL);
1802 if (res != TEE_SUCCESS)
1805 for (i = 0; i < N_ENTRIES; i++) {
1807 * Look for an entry, matching filenames. (read, rm,
1808 * rename and stat.). Only store first filename match.
1811 (strcmp(fh->filename,
1812 fat_entries[i].filename) == 0) &&
1813 (fat_entries[i].flags & FILE_IS_ACTIVE) &&
1816 fh->rpmb_fat_address = fat_address;
1817 memcpy(&fh->fat_entry, &fat_entries[i],
1818 sizeof(struct rpmb_fat_entry));
1823 /* Add existing files to memory pool. (write) */
1825 if ((fat_entries[i].flags & FILE_IS_ACTIVE) &&
1826 (fat_entries[i].data_size > 0)) {
1830 fat_entries[i].start_address,
1831 fat_entries[i].data_size);
1833 res = TEE_ERROR_OUT_OF_MEMORY;
1838 /* Unused FAT entries can be reused (write) */
1839 if (((fat_entries[i].flags & FILE_IS_ACTIVE) ==
1840 0) && (fh->rpmb_fat_address == 0)) {
1841 fh->rpmb_fat_address = fat_address;
1842 memcpy(&fh->fat_entry, &fat_entries[i],
1843 sizeof(struct rpmb_fat_entry));
1847 if ((fat_entries[i].flags & FILE_IS_LAST_ENTRY) != 0) {
1848 last_entry_found = true;
1851 * If the last entry was reached and was chosen
1852 * by the previous check, then the FAT needs to
1854 * fh->rpmb_fat_address is the address chosen
1855 * to store the files FAT entry and fat_address
1856 * is the current FAT entry address being
1859 if (p && fh->rpmb_fat_address == fat_address)
1864 /* Move to next fat_entry. */
1865 fat_address += sizeof(struct rpmb_fat_entry);
1870 * Represent the FAT table in the pool.
1874 * Since fat_address is the start of the last entry it needs to
1875 * be moved up by an entry.
1877 fat_address += sizeof(struct rpmb_fat_entry);
1879 /* Make room for yet a FAT entry and add to memory pool. */
1881 fat_address += sizeof(struct rpmb_fat_entry);
1883 mm = tee_mm_alloc2(p, RPMB_STORAGE_START_ADDRESS, fat_address);
1885 res = TEE_ERROR_OUT_OF_MEMORY;
1891 * Point fat_address to the beginning of the new
1894 fat_address -= sizeof(struct rpmb_fat_entry);
1895 memset(&last_fh, 0, sizeof(last_fh));
1896 last_fh.fat_entry.flags = FILE_IS_LAST_ENTRY;
1897 last_fh.rpmb_fat_address = fat_address;
1898 res = write_fat_entry(&last_fh, true);
1899 if (res != TEE_SUCCESS)
1904 if (fh->filename && !fh->rpmb_fat_address)
1905 res = TEE_ERROR_ITEM_NOT_FOUND;
1912 static TEE_Result generate_fek(struct rpmb_fat_entry *fe)
1917 res = tee_fs_generate_fek(fe->fek, sizeof(fe->fek));
1918 if (res != TEE_SUCCESS)
1921 if (is_zero(fe->fek, sizeof(fe->fek)))
1927 static TEE_Result rpmb_fs_open_internal(const char *file, bool create,
1928 struct tee_file_handle **ret_fh)
1930 struct rpmb_file_handle *fh = NULL;
1934 TEE_Result res = TEE_ERROR_GENERIC;
1936 mutex_lock(&rpmb_mutex);
1938 filelen = strlen(file);
1939 if (filelen >= TEE_RPMB_FS_FILENAME_LENGTH - 1 || filelen == 0) {
1940 res = TEE_ERROR_BAD_PARAMETERS;
1944 if (file[filelen - 1] == '/') {
1945 res = TEE_ERROR_BAD_PARAMETERS;
1949 fh = alloc_file_handle(file);
1951 res = TEE_ERROR_OUT_OF_MEMORY;
1955 /* We need to do setup in order to make sure fs_par is filled in */
1956 res = rpmb_fs_setup();
1957 if (res != TEE_SUCCESS)
1961 /* Upper memory allocation must be used for RPMB_FS. */
1962 pool_result = tee_mm_init(&p,
1963 RPMB_STORAGE_START_ADDRESS,
1964 fs_par->max_rpmb_address,
1965 RPMB_BLOCK_SIZE_SHIFT,
1966 TEE_MM_POOL_HI_ALLOC);
1969 res = TEE_ERROR_OUT_OF_MEMORY;
1973 res = read_fat(fh, &p);
1975 if (res != TEE_SUCCESS)
1978 res = read_fat(fh, NULL);
1979 if (res != TEE_SUCCESS)
1984 * If this is opened with create and the entry found was not active
1985 * then this is a new file and the FAT entry must be written
1988 if ((fh->fat_entry.flags & FILE_IS_ACTIVE) == 0) {
1989 memset(&fh->fat_entry, 0,
1990 sizeof(struct rpmb_fat_entry));
1991 memcpy(fh->fat_entry.filename, file, strlen(file));
1992 /* Start address and size are 0 */
1993 fh->fat_entry.flags = FILE_IS_ACTIVE;
1995 res = generate_fek(&fh->fat_entry);
1996 if (res != TEE_SUCCESS)
1998 DMSG("GENERATE FEK key: %p",
1999 (void *)fh->fat_entry.fek);
2000 DHEXDUMP(fh->fat_entry.fek, sizeof(fh->fat_entry.fek));
2002 res = write_fat_entry(fh, true);
2003 if (res != TEE_SUCCESS)
2011 if (res == TEE_SUCCESS)
2012 *ret_fh = (struct tee_file_handle *)fh;
2016 mutex_unlock(&rpmb_mutex);
2020 static void rpmb_fs_close(struct tee_file_handle **tfh)
2022 struct rpmb_file_handle *fh = (struct rpmb_file_handle *)*tfh;
2028 static TEE_Result rpmb_fs_read(struct tee_file_handle *tfh, void *buf,
2032 struct rpmb_file_handle *fh = (struct rpmb_file_handle *)tfh;
2038 mutex_lock(&rpmb_mutex);
2042 res = read_fat(fh, NULL);
2043 if (res != TEE_SUCCESS)
2046 if (fh->pos >= fh->fat_entry.data_size) {
2051 size = MIN(size, fh->fat_entry.data_size - fh->pos);
2053 res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID,
2054 fh->fat_entry.start_address + fh->pos, buf,
2055 size, fh->fat_entry.fek);
2056 if (res != TEE_SUCCESS)
2063 mutex_unlock(&rpmb_mutex);
2067 static TEE_Result rpmb_fs_write(struct tee_file_handle *tfh, const void *buf,
2071 struct rpmb_file_handle *fh = (struct rpmb_file_handle *)tfh;
2073 bool pool_result = false;
2077 uint8_t *newbuf = NULL;
2079 uint32_t start_addr;
2084 mutex_lock(&rpmb_mutex);
2087 res = TEE_ERROR_GENERIC;
2093 /* Upper memory allocation must be used for RPMB_FS. */
2094 pool_result = tee_mm_init(&p,
2095 RPMB_STORAGE_START_ADDRESS,
2096 fs_par->max_rpmb_address,
2097 RPMB_BLOCK_SIZE_SHIFT,
2098 TEE_MM_POOL_HI_ALLOC);
2100 res = TEE_ERROR_OUT_OF_MEMORY;
2104 res = read_fat(fh, &p);
2105 if (res != TEE_SUCCESS)
2108 if (fh->fat_entry.flags & FILE_IS_LAST_ENTRY)
2109 panic("invalid last entry flag");
2111 end = fh->pos + size;
2112 start_addr = fh->fat_entry.start_address + fh->pos;
2114 if (end <= fh->fat_entry.data_size &&
2115 tee_rpmb_write_is_atomic(CFG_RPMB_FS_DEV_ID, start_addr, size)) {
2117 DMSG("Updating data in-place");
2118 res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, start_addr, buf,
2119 size, fh->fat_entry.fek);
2120 if (res != TEE_SUCCESS)
2124 * File must be extended, or update cannot be atomic: allocate,
2125 * read, update, write.
2128 DMSG("Need to re-allocate");
2129 newsize = MAX(end, fh->fat_entry.data_size);
2130 mm = tee_mm_alloc(&p, newsize);
2131 newbuf = calloc(newsize, 1);
2132 if (!mm || !newbuf) {
2133 res = TEE_ERROR_OUT_OF_MEMORY;
2137 if (fh->fat_entry.data_size) {
2138 res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID,
2139 fh->fat_entry.start_address,
2140 newbuf, fh->fat_entry.data_size,
2142 if (res != TEE_SUCCESS)
2146 memcpy(newbuf + fh->pos, buf, size);
2148 newaddr = tee_mm_get_smem(mm);
2149 res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, newaddr, newbuf,
2150 newsize, fh->fat_entry.fek);
2151 if (res != TEE_SUCCESS)
2154 fh->fat_entry.data_size = newsize;
2155 fh->fat_entry.start_address = newaddr;
2156 res = write_fat_entry(fh, true);
2157 if (res != TEE_SUCCESS)
2163 mutex_unlock(&rpmb_mutex);
2172 static TEE_Result rpmb_fs_seek(struct tee_file_handle *tfh, int32_t offset,
2173 TEE_Whence whence, int32_t *new_offs)
2176 struct rpmb_file_handle *fh = (struct rpmb_file_handle *)tfh;
2178 tee_fs_off_t new_pos;
2180 mutex_lock(&rpmb_mutex);
2182 res = read_fat(fh, NULL);
2183 if (res != TEE_SUCCESS)
2187 case TEE_DATA_SEEK_SET:
2191 case TEE_DATA_SEEK_CUR:
2192 new_pos = fh->pos + offset;
2195 case TEE_DATA_SEEK_END:
2196 new_pos = fh->fat_entry.data_size + offset;
2200 res = TEE_ERROR_BAD_PARAMETERS;
2207 if (new_pos > TEE_DATA_MAX_POSITION) {
2208 EMSG("Position is beyond TEE_DATA_MAX_POSITION");
2209 res = TEE_ERROR_BAD_PARAMETERS;
2215 *new_offs = new_pos;
2217 mutex_unlock(&rpmb_mutex);
2221 static TEE_Result rpmb_fs_remove(const char *filename)
2223 TEE_Result res = TEE_ERROR_GENERIC;
2224 struct rpmb_file_handle *fh = NULL;
2226 mutex_lock(&rpmb_mutex);
2228 if (!filename || strlen(filename) >= TEE_RPMB_FS_FILENAME_LENGTH - 1) {
2229 res = TEE_ERROR_BAD_PARAMETERS;
2233 fh = alloc_file_handle(filename);
2235 res = TEE_ERROR_OUT_OF_MEMORY;
2239 res = read_fat(fh, NULL);
2240 if (res != TEE_SUCCESS)
2243 /* Clear this file entry. */
2244 memset(&fh->fat_entry, 0, sizeof(struct rpmb_fat_entry));
2245 res = write_fat_entry(fh, false);
2248 mutex_unlock(&rpmb_mutex);
2253 static TEE_Result rpmb_fs_rename(const char *old_name, const char *new_name,
2256 TEE_Result res = TEE_ERROR_GENERIC;
2257 struct rpmb_file_handle *fh_old = NULL;
2258 struct rpmb_file_handle *fh_new = NULL;
2262 mutex_lock(&rpmb_mutex);
2264 if (!old_name || !new_name) {
2265 res = TEE_ERROR_BAD_PARAMETERS;
2269 old_len = strlen(old_name);
2270 new_len = strlen(new_name);
2272 if ((old_len >= TEE_RPMB_FS_FILENAME_LENGTH - 1) ||
2273 (new_len >= TEE_RPMB_FS_FILENAME_LENGTH - 1) || (new_len == 0)) {
2275 res = TEE_ERROR_BAD_PARAMETERS;
2279 fh_old = alloc_file_handle(old_name);
2281 res = TEE_ERROR_OUT_OF_MEMORY;
2285 fh_new = alloc_file_handle(new_name);
2287 res = TEE_ERROR_OUT_OF_MEMORY;
2291 res = read_fat(fh_old, NULL);
2292 if (res != TEE_SUCCESS)
2295 res = read_fat(fh_new, NULL);
2296 if (res == TEE_SUCCESS) {
2298 res = TEE_ERROR_BAD_PARAMETERS;
2302 /* Clear this file entry. */
2303 memset(&fh_new->fat_entry, 0, sizeof(struct rpmb_fat_entry));
2304 res = write_fat_entry(fh_new, false);
2305 if (res != TEE_SUCCESS)
2309 memset(fh_old->fat_entry.filename, 0, TEE_RPMB_FS_FILENAME_LENGTH);
2310 memcpy(fh_old->fat_entry.filename, new_name, new_len);
2312 res = write_fat_entry(fh_old, false);
2315 mutex_unlock(&rpmb_mutex);
2322 static TEE_Result rpmb_fs_truncate(struct tee_file_handle *tfh, size_t length)
2324 struct rpmb_file_handle *fh = (struct rpmb_file_handle *)tfh;
2326 bool pool_result = false;
2329 uint8_t *newbuf = NULL;
2331 TEE_Result res = TEE_ERROR_GENERIC;
2333 mutex_lock(&rpmb_mutex);
2335 if (length > INT32_MAX) {
2336 res = TEE_ERROR_BAD_PARAMETERS;
2341 res = read_fat(fh, NULL);
2342 if (res != TEE_SUCCESS)
2345 if (newsize > fh->fat_entry.data_size) {
2348 pool_result = tee_mm_init(&p,
2349 RPMB_STORAGE_START_ADDRESS,
2350 fs_par->max_rpmb_address,
2351 RPMB_BLOCK_SIZE_SHIFT,
2352 TEE_MM_POOL_HI_ALLOC);
2354 res = TEE_ERROR_OUT_OF_MEMORY;
2357 res = read_fat(fh, &p);
2358 if (res != TEE_SUCCESS)
2361 mm = tee_mm_alloc(&p, newsize);
2362 newbuf = calloc(newsize, 1);
2363 if (!mm || !newbuf) {
2364 res = TEE_ERROR_OUT_OF_MEMORY;
2368 if (fh->fat_entry.data_size) {
2369 res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID,
2370 fh->fat_entry.start_address,
2371 newbuf, fh->fat_entry.data_size,
2373 if (res != TEE_SUCCESS)
2377 newaddr = tee_mm_get_smem(mm);
2378 res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, newaddr, newbuf,
2379 newsize, fh->fat_entry.fek);
2380 if (res != TEE_SUCCESS)
2384 /* Don't change file location */
2385 newaddr = fh->fat_entry.start_address;
2388 /* fh->pos is unchanged */
2389 fh->fat_entry.data_size = newsize;
2390 fh->fat_entry.start_address = newaddr;
2391 res = write_fat_entry(fh, true);
2394 mutex_unlock(&rpmb_mutex);
2403 static void rpmb_fs_dir_free(struct tee_fs_dir *dir)
2405 struct tee_rpmb_fs_dirent *e;
2412 while ((e = SIMPLEQ_FIRST(&dir->next))) {
2413 SIMPLEQ_REMOVE_HEAD(&dir->next, link);
2418 static TEE_Result rpmb_fs_dir_populate(const char *path,
2419 struct tee_fs_dir *dir)
2421 struct tee_rpmb_fs_dirent *current = NULL;
2422 struct rpmb_fat_entry *fat_entries = NULL;
2423 uint32_t fat_address;
2427 bool last_entry_found = false;
2429 struct tee_rpmb_fs_dirent *next = NULL;
2431 TEE_Result res = TEE_ERROR_GENERIC;
2435 mutex_lock(&rpmb_mutex);
2437 res = rpmb_fs_setup();
2438 if (res != TEE_SUCCESS)
2441 res = get_fat_start_address(&fat_address);
2442 if (res != TEE_SUCCESS)
2445 size = N_ENTRIES * sizeof(struct rpmb_fat_entry);
2446 fat_entries = malloc(size);
2448 res = TEE_ERROR_OUT_OF_MEMORY;
2452 pathlen = strlen(path);
2453 while (!last_entry_found) {
2454 res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, fat_address,
2455 (uint8_t *)fat_entries, size, NULL);
2456 if (res != TEE_SUCCESS)
2459 for (i = 0; i < N_ENTRIES; i++) {
2460 filename = fat_entries[i].filename;
2461 if (fat_entries[i].flags & FILE_IS_ACTIVE) {
2463 filelen = strlen(filename);
2464 if (filelen > pathlen) {
2465 temp = filename[pathlen];
2466 filename[pathlen] = '\0';
2467 if (strcmp(filename, path) == 0)
2470 filename[pathlen] = temp;
2474 next = malloc(sizeof(*next));
2476 res = TEE_ERROR_OUT_OF_MEMORY;
2480 memset(next, 0, sizeof(*next));
2481 next->entry.d_name = next->name;
2486 SIMPLEQ_INSERT_TAIL(&dir->next, next,
2492 if (fat_entries[i].flags & FILE_IS_LAST_ENTRY) {
2493 last_entry_found = true;
2497 /* Move to next fat_entry. */
2498 fat_address += sizeof(struct rpmb_fat_entry);
2505 res = TEE_ERROR_ITEM_NOT_FOUND; /* No directories were found. */
2508 mutex_unlock(&rpmb_mutex);
2509 if (res != TEE_SUCCESS)
2510 rpmb_fs_dir_free(dir);
2517 static TEE_Result rpmb_fs_opendir(const char *path, struct tee_fs_dir **dir)
2521 char path_local[TEE_RPMB_FS_FILENAME_LENGTH];
2522 TEE_Result res = TEE_ERROR_GENERIC;
2523 struct tee_fs_dir *rpmb_dir = NULL;
2525 if (!path || !dir) {
2526 res = TEE_ERROR_BAD_PARAMETERS;
2531 * There must be room for at least the NULL char and a char for the
2532 * filename after the path.
2534 max_size = TEE_RPMB_FS_FILENAME_LENGTH - 2;
2536 if (len > max_size || len == 0) {
2537 res = TEE_ERROR_BAD_PARAMETERS;
2541 memset(path_local, 0, sizeof(path_local));
2542 memcpy(path_local, path, len);
2544 /* Add a slash to correctly match the full directory name. */
2545 if (path_local[len - 1] != '/')
2546 path_local[len] = '/';
2548 rpmb_dir = calloc(1, sizeof(*rpmb_dir));
2550 res = TEE_ERROR_OUT_OF_MEMORY;
2553 SIMPLEQ_INIT(&rpmb_dir->next);
2555 res = rpmb_fs_dir_populate(path_local, rpmb_dir);
2556 if (res != TEE_SUCCESS) {
2568 static TEE_Result rpmb_fs_readdir(struct tee_fs_dir *dir,
2569 struct tee_fs_dirent **ent)
2572 return TEE_ERROR_GENERIC;
2576 dir->current = SIMPLEQ_FIRST(&dir->next);
2578 return TEE_ERROR_ITEM_NOT_FOUND;
2580 SIMPLEQ_REMOVE_HEAD(&dir->next, link);
2582 *ent = &dir->current->entry;
2586 static void rpmb_fs_closedir(struct tee_fs_dir *dir)
2589 rpmb_fs_dir_free(dir);
2594 static TEE_Result rpmb_fs_open(const char *file, struct tee_file_handle **fh)
2596 return rpmb_fs_open_internal(file, false, fh);
2599 static TEE_Result rpmb_fs_create(const char *file, struct tee_file_handle **fh)
2601 return rpmb_fs_open_internal(file, true, fh);
2604 const struct tee_file_operations rpmb_fs_ops = {
2605 .open = rpmb_fs_open,
2606 .create = rpmb_fs_create,
2607 .close = rpmb_fs_close,
2608 .read = rpmb_fs_read,
2609 .write = rpmb_fs_write,
2610 .seek = rpmb_fs_seek,
2611 .truncate = rpmb_fs_truncate,
2612 .rename = rpmb_fs_rename,
2613 .remove = rpmb_fs_remove,
2614 .opendir = rpmb_fs_opendir,
2615 .closedir = rpmb_fs_closedir,
2616 .readdir = rpmb_fs_readdir,