美文网首页
OP-TEE5-RPMB FS2

OP-TEE5-RPMB FS2

作者: 阿棍儿_Leon | 来源:发表于2019-04-06 17:24 被阅读0次

RPMB FS流程

具体见注释。

rpmb_fs_open

@optee_os/core/tee/tee_rpmb_fs.c
主要

  • 构建struct rpmb_file_handle数据结构指针——文件指针
  • 加/解锁
  • call rpmb_fs_open_internal——open的主要逻辑
static TEE_Result rpmb_fs_open(struct tee_pobj *po, size_t *size,
                   struct tee_file_handle **ret_fh)
{
    TEE_Result res;
    //申请一个文件句柄,相当于fopen的FILE指针,po是上层的句柄,在这一层我们要用的是fh
    struct rpmb_file_handle *fh = alloc_file_handle(po, po->temporary);

    if (!fh)
        return TEE_ERROR_OUT_OF_MEMORY;

    mutex_lock(&rpmb_mutex);//日常加锁
    //真·open
    res = rpmb_fs_open_internal(fh, &po->uuid, false);
    if (!res && size)
        *size = fh->fat_entry.data_size;

    mutex_unlock(&rpmb_mutex);//日常解锁

    if (res)
        free(fh);
    else
        *ret_fh = (struct tee_file_handle *)fh;

    return res;
}

rpmb_fs_open_internal

@optee_os/core/tee/tee_rpmb_fs.c
主要

  • call rpmb_fs_setup——初始化
  • 如果创建文件
    准备在RPMB申请新数据空间
  • 构造新的或读取已有的fat表项[1]
  • 如果创建文件
    生成EFEK[2]
    写入新fat表项
static TEE_Result rpmb_fs_open_internal(struct rpmb_file_handle *fh,
                    const TEE_UUID *uuid, bool create)
{
    tee_mm_pool_t p;
    bool pool_result;
    TEE_Result res = TEE_ERROR_GENERIC;

    /* We need to do setup in order to make sure fs_par is filled in */
    res = rpmb_fs_setup(); //为使用FS的使用做准备,属于初始化动作
    if (res != TEE_SUCCESS)
        goto out;

    fh->uuid = uuid;
    if (create) { //如果创建文件
        /* Upper memory allocation must be used for RPMB_FS. */
        //准备在RPMB中申请一块空间用来存储新文件
        pool_result = tee_mm_init(&p,
                      RPMB_STORAGE_START_ADDRESS,
                      fs_par->max_rpmb_address,
                      RPMB_BLOCK_SIZE_SHIFT,
                      TEE_MM_POOL_HI_ALLOC);

        if (!pool_result) {
            res = TEE_ERROR_OUT_OF_MEMORY;
            goto out;
        }
        //读取fat表,为新的文件构造表项,fat表是用来管理RPMB FS的元数据
        res = read_fat(fh, &p);
        tee_mm_final(&p);
        if (res != TEE_SUCCESS)
            goto out;
    } else { //如果不是创建文件
        //读取fat表,为新的文件构造表项,fat表是用来管理RPMB FS的元数据
        res = read_fat(fh, NULL);
        if (res != TEE_SUCCESS)
            goto out;
    }

    /*
     * If this is opened with create and the entry found was not active
     * then this is a new file and the FAT entry must be written
     */
    if (create) { //如果创建文件
        if ((fh->fat_entry.flags & FILE_IS_ACTIVE) == 0) { //如果分到的fat表项是没有被使用的
            memset(&fh->fat_entry, 0,
                sizeof(struct rpmb_fat_entry));
            memcpy(fh->fat_entry.filename, fh->filename,
                strlen(fh->filename));
            /* Start address and size are 0 */
            fh->fat_entry.flags = FILE_IS_ACTIVE; //设置fat表项为被使用的

            res = generate_fek(&fh->fat_entry, uuid); //生成EFEK,用来给文件数据加密的
            if (res != TEE_SUCCESS)
                goto out;
            DMSG("GENERATE FEK key: %p",
                 (void *)fh->fat_entry.fek);
            DHEXDUMP(fh->fat_entry.fek, sizeof(fh->fat_entry.fek));

            res = write_fat_entry(fh, true); //把新建的表项写入RPMB
            if (res != TEE_SUCCESS)
                goto out;
        }
    }

    res = TEE_SUCCESS;

out:
    return res;
}

rpmb_fs_setup

@optee_os/core/tee/tee_rpmb_fs.c
主要:

  • fs_par已经赋值,说明这个结构体填充完了,立刻成功返回,不再初始化
  • 获取RPMB分区块数,块大小是1<<RPMB_BLOCK_SIZE_SHIFT——256
  • 读取struct rpmb_fs_partition,确定是否需要重置分区
  • (可能会)重置分区
  • fs_par指针申请结构体空间,并给成员赋值
static TEE_Result rpmb_fs_setup(void)
{
    TEE_Result res = TEE_ERROR_GENERIC;
    struct rpmb_fs_partition *partition_data = NULL;
    struct rpmb_file_handle *fh = NULL;
    uint32_t max_rpmb_block = 0;

    if (fs_par) {
        res = TEE_SUCCESS;
        goto out;
    }
    //获取最大块数,后面用来填充fs_par
    res = tee_rpmb_get_max_block(CFG_RPMB_FS_DEV_ID, &max_rpmb_block);
    if (res != TEE_SUCCESS)
        goto out;

    partition_data = calloc(1, sizeof(struct rpmb_fs_partition));
    if (!partition_data) {
        res = TEE_ERROR_OUT_OF_MEMORY;
        goto out;
    }
    //读取RPMB中最开始的那段数据,解析为struct rpmb_fs_partition
    res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS,
                (uint8_t *)partition_data,
                sizeof(struct rpmb_fs_partition), NULL, NULL);
    if (res != TEE_SUCCESS)
        goto out;

#ifndef CFG_RPMB_RESET_FAT
    if (partition_data->rpmb_fs_magic == RPMB_FS_MAGIC) { //核对魔数
        if (partition_data->fs_version == FS_VERSION) { //核对版本
            res = TEE_SUCCESS;
            goto store_fs_par; // 正常情况会走这里
        } else { //版本不对就不能访问
            /* Wrong software is in use. */
            res = TEE_ERROR_ACCESS_DENIED;
            goto out;
        }
    }
#else
    EMSG("**** Clearing Storage ****"); //正常不会走这里,这里会重置RPMB分区
#endif

    //下面开始重置RPMB分区
    /* Setup new partition data. */
    partition_data->rpmb_fs_magic = RPMB_FS_MAGIC;
    partition_data->fs_version = FS_VERSION;
    partition_data->fat_start_address = RPMB_FS_FAT_START_ADDRESS; //512

    /* Initial FAT entry with FILE_IS_LAST_ENTRY flag set. */
    fh = alloc_file_handle(NULL, false); //准备写入一个fat表项
    if (!fh) {
        res = TEE_ERROR_OUT_OF_MEMORY;
        goto out;
    }
    fh->fat_entry.flags = FILE_IS_LAST_ENTRY; //这个表项标记为最后一项
    fh->rpmb_fat_address = partition_data->fat_start_address;

    /* Write init FAT entry and partition data to RPMB. */
    res = write_fat_entry(fh, true); //写入这个唯一的表项,这个表项对应的范围是从512开始所有空间
    if (res != TEE_SUCCESS)
        goto out;
    //记下目前的write counter,在TEE OS里面好像没什么用
    res =
        tee_rpmb_get_write_counter(CFG_RPMB_FS_DEV_ID,
                       &partition_data->write_counter);
    if (res != TEE_SUCCESS)
        goto out;
    //将新的struct rpmb_fs_partition写进去
    res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS,
                 (uint8_t *)partition_data,
                 sizeof(struct rpmb_fs_partition), NULL, NULL);

#ifndef CFG_RPMB_RESET_FAT
store_fs_par: //正常情况会从上面直接跳到这里
#endif
    //开始填充fs_par
    /* Store FAT start address. */
    fs_par = calloc(1, sizeof(struct rpmb_fs_parameters));
    if (!fs_par) {
        res = TEE_ERROR_OUT_OF_MEMORY;
        goto out;
    }
    //就填充这两个东西:fat表起始位置+RPMB分区最后一块的地址
    fs_par->fat_start_address = partition_data->fat_start_address;
    fs_par->max_rpmb_address = max_rpmb_block << RPMB_BLOCK_SIZE_SHIFT;

    dump_fat();

out:
    free(fh);
    free(partition_data);
    return res;
}

  1. fat表是RPMB分区的元数据,和FAT32文件系统的类似,但是更简单。

  2. EFEK是用来给文件加密的密钥,在存储到REE FS或RPMB FS之前,文件都需要先被加密。

相关文章

  • OP-TEE5-RPMB FS2

    RPMB FS流程 具体见注释。 rpmb_fs_open @optee_os/core/tee/tee_rpmb...

  • OP-TEE5-RPMB FS1

    RPMB FS流程 首先说软件的层次结构。代码主要在optee_os/core/tee/tee_rpmb_fs.c...

  • OP-TEE5-RPMB FS0

    RPMB FS 讲到RPMB FS,就要说一下RPMB访问的规则了。这个规则在OP-TEE的源码中有部分体现。 为...

网友评论

      本文标题:OP-TEE5-RPMB FS2

      本文链接:https://www.haomeiwen.com/subject/grqzbqtx.html