system 镜像签名 fec等信息

如何编译生成system镜像

  • 首先来看编译过程中的log输出,并结合log输出可以一窥究竟。

不知道csdn咋回事,上传的图片一点儿都清晰。。输出的log可以参照末尾该处的信息

编译过程log信息

  • 编译生成verity_medatata.img的核心python代码如下

编译生成system verity_medatata的关键python代码system/extras/verity/build_verity_metadata.py

VERSION = 0
MAGIC_NUMBER = 0xb001b001
BLOCK_SIZE = 4096
METADATA_SIZE = BLOCK_SIZE * 8

def build_verity_table(block_device, data_blocks, root_hash, salt):
    table = "1 %s %s %s %s %s %s sha256 %s %s"
    table %= (  block_device,
                block_device,
                BLOCK_SIZE,
                BLOCK_SIZE,
                data_blocks,
                data_blocks,
                root_hash,
                salt)
    return table

各个成员分别代表的含义:

FieldPurposeSizeValue
magic numberused by fs_mgr as a sanity check4 bytes0xb001b001
versionused to version the metadata block4 bytescurrent 0
signaturethe signature of the table PKCS1.5 padded from256 bytes
table lengththe length of the dm-verity table in bytes4 bytes
tablethe dm-verity table described earlier‘table length’ bytes
paddingthis structure is 0-padded to 32k in length0
  • 编译过程的示意图

编译system镜像过程

  • 编译生成fecdata信息的关键代码

相关数据结构system/extras/libfec/include/fec/io.h

#define FEC_BLOCKSIZE 4096
#define FEC_DEFAULT_ROOTS 2
#define FEC_MAGIC 0xFECFECFE
#define FEC_VERSION 0

/* disk format for the header */
struct fec_header {
    uint32_t magic;
    uint32_t version;
    uint32_t size;
    uint32_t roots;
    uint32_t fec_size;
    uint64_t inp_size;
    uint8_t hash[SHA256_DIGEST_LENGTH];
};

struct fec_verity_metadata {
    bool disabled;
    uint64_t data_size;
    uint8_t signature[RSANUMBYTES];
    uint8_t ecc_signature[RSANUMBYTES];
    const char *table;
    uint32_t table_length;
};

通过dump镜像来看信息

fec 保存的信息


我是分割线。。。。。。


计算得到hash tree的位置

上面的两张图说的比较清楚了,就不在赘述其计算过程。

通过代码来研究

system/extras/libfec/fec_open.cpp
system/core/fs_mgr/fs_mgr_verity.cpp

Created with Raphaël 2.1.0 fs_mgr_verity.cpp fs_mgr_verity.cpp fec_open.cpp fec_open.cpp fs_mgr_setup_verity get_size() load_ecc() load_verity() fec_verity_get_metadata open("/dev/device-mapper", O_RDWR) create_verity_device get_verity_device_name load_verity_state verify_verity_signature

其中核心代码片段如下所示

//system/core/fs_mgr/fs_mgr_verity.cpp
int fs_mgr_setup_verity(struct fstab_rec *fstab){
    alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
    struct dm_ioctl *io = (struct dm_ioctl *) buffer;
    char *mount_point = basename(fstab->mount_point);

    if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE,
            FEC_DEFAULT_ROOTS) < 0) {
        ERROR("Failed to open '%s' (%s)\n", fstab->blk_device,
            strerror(errno));
        return retval;
    }

    // read verity metadata
    if (fec_verity_get_metadata(f, &verity) < 0) {
        ERROR("Failed to get verity metadata '%s' (%s)\n", fstab->blk_device,
            strerror(errno));
        goto out;
    }

#ifdef ALLOW_ADBD_DISABLE_VERITY
    if (verity.disabled) {
        retval = FS_MGR_SETUP_VERITY_DISABLED;
        INFO("Attempt to cleanly disable verity - only works in USERDEBUG\n");
        goto out;
    }
#endif

    // read ecc metadata
    if (fec_ecc_get_metadata(f, &params.ecc) < 0) {
        params.ecc.valid = false;
    }

    params.ecc_dev = fstab->blk_device;

    // get the device mapper fd
    if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
        ERROR("Error opening device mapper (%s)\n", strerror(errno));
        goto out;
    }

    // create the device
    if (create_verity_device(io, mount_point, fd) < 0) {
        ERROR("Couldn't create verity device!\n");
        goto out;
    }

    // get the name of the device file
    if (get_verity_device_name(io, mount_point, fd, &verity_blk_name) < 0) {
        ERROR("Couldn't get verity device number!\n");
        goto out;
    }

    if (load_verity_state(fstab, &params.mode) < 0) {
        /* if accessing or updating the state failed, switch to the default
         * safe mode. This makes sure the device won't end up in an endless
         * restart loop, and no corrupted data will be exposed to userspace
         * without a warning. */
        params.mode = VERITY_MODE_EIO;
    }

    // verify the signature on the table
    if (verify_verity_signature(verity) < 0) {
        if (params.mode == VERITY_MODE_LOGGING) {
        //....
    } else {
        //....
    }

    // activate the device
    // 激活创建的mapped device 设备
    if (resume_verity_table(io, mount_point, fd) < 0) {
        goto out;
    }

    // mark the underlying block device as read-only
    //设置为只读模式
    fs_mgr_set_blk_ro(fstab->blk_device);

    // assign the new verity block device as the block device
    //重新分配verity block设备
    free(fstab->blk_device);
    fstab->blk_device = verity_blk_name;
    verity_blk_name = 0;

    // make sure we've set everything up properly
    if (test_access(fstab->blk_device) < 0) {
        goto out;
    }

    retval = FS_MGR_SETUP_VERITY_SUCCESS;
}

//system/extras/libfec/fec_open.cpp
/* locates, validates, and loads ecc data from `f->fd' */
static int load_ecc(fec_handle *f){
    //此处的data_size 为整个镜像的大小。
    //FEC header 大小为4KB(4096 byte)且存放在镜像的最后一个4KB
    //故:offset = data_size - FEC_BLOCKSIZE 为 FEC header 的起始地址
    uint64_t offset = f->data_size - FEC_BLOCKSIZE;
    if (parse_ecc(f, offset) == 0)
        //...
}

/* attempts to read an ecc header from `offset', and checks for a
 * backup copy at the end of the block if the primary header is
 *  not valid 
 */
static int parse_ecc(fec_handle *f, uint64_t offset){
    /* check the primary header at the beginning of the block */
    //读取主 fec header中的内容
    if (parse_ecc_header(f, offset) == 0) {
        return 0;
    }

    /* check the backup header at the end of the block */
    //读取备份的fec内容
    //offset+FEC_BLOCKSIZE 就到了文件的末尾
    //说明镜像的最后4KB存储的是备份的FEC相关信息
    if (parse_ecc_header(f, offset + FEC_BLOCKSIZE - sizeof(fec_header)) == 0) {
        //...
    }
}
/* attempts to read and validate an ecc header from file position `offset' */
static int parse_ecc_header(fec_handle *f, uint64_t offset){
    check(f);
    //先判断rsn的值是否在 (0,255)范围内
    check(f->ecc.rsn > 0 && f->ecc.rsn < FEC_RSM);
    //f->size 要大于 sizeof fec_header 
    check(f->size > sizeof(fec_header));

    debug("offset = %" PRIu64, offset);
    //镜像的起始相对地址为0,offset的值必须要小于f->size - sizeof fec_header
    if (offset > f->size - sizeof(fec_header)) {
        return -1;
    }

    fec_header header;

    /* there's obviously no ecc data at this point, so there is no need to
       call fec_pread to access this data */
    if (!raw_pread(f, &header, sizeof(fec_header), offset)) {
        error("failed to read: %s", strerror(errno));
        return -1;
    }

    /* move offset back to the beginning of the block for validating header */
    //TODO:
    offset -= offset % FEC_BLOCKSIZE;
    /* structure: data | ecc | header */
    if (offset < header.fec_size ||
            offset - header.fec_size != header.inp_size) {
        error("unexpected input size: %" PRIu64 " vs %" PRIu64, offset,
            header.inp_size);
        return -1;
    }

    f->data_size = header.inp_size;
    f->ecc.blocks = fec_div_round_up(f->data_size, FEC_BLOCKSIZE);
    f->ecc.rounds = fec_div_round_up(f->ecc.blocks, f->ecc.rsn);

    if (header.fec_size !=
            (uint32_t)f->ecc.rounds * f->ecc.roots * FEC_BLOCKSIZE) {
        error("inconsistent ecc size %u", header.fec_size);
        return -1;
    }

    f->ecc.size = header.fec_size;
    f->ecc.start = header.inp_size;

    /* validate encoding data; caller may opt not to use it if invalid */
    SHA256_CTX ctx;
    SHA256_Init(&ctx);

    uint8_t buf[FEC_BLOCKSIZE];
    uint32_t n = 0;
    uint32_t len = FEC_BLOCKSIZE;

    while (n < f->ecc.size) {
        if (len > f->ecc.size - n) {
            len = f->ecc.size - n;
        }

        if (!raw_pread(f, buf, len, f->ecc.start + n)) {
            error("failed to read ecc: %s", strerror(errno));
            return -1;
        }
        SHA256_Update(&ctx, buf, len);
        n += len;
    }

    uint8_t hash[SHA256_DIGEST_LENGTH];
    SHA256_Final(hash, &ctx);

    //校验结果
    f->ecc.valid = !memcmp(hash, header.hash, SHA256_DIGEST_LENGTH);
}

编译log附件

[ 87% 37962/43356] Target system fs image: out/target/product/chopin/obj/PACKAGING/systemimage_intermediates/system.img
BuildImage: in_dir = out/target/product/chopin/system, out_file = out/target/product/chopin/obj/PACKAGING/systemimage_intermediates/system.img

Running:  mkuserimg.sh -s out/target/product/chopin/system 
                        out/target/product/chopin/obj/PACKAGING/systemimage_intermediates/system.img 
                        ext4 system 3666415616
                        -D out/target/product/chopin/system -L system 
                        out/target/product/chopin/root/file_contexts.bin

make_ext4fs -s -T -1 -S out/target/product/chopin/root/file_contexts.bin
            -L system -l 3666415616 
            -a system out/target/product/chopin/obj/PACKAGING/systemimage_intermediates/system.img 
            out/target/product/chopin/system out/target/product/chopin/system

Creating filesystem with parameters:
    Size: 3666415616
    Block size: 4096
    Blocks per group: 32768
    Inodes per group: 8000
    Inode size: 256
    Journal blocks: 13986
    Label: system
    Blocks: 895121
    Block groups: 28
    Reserved block group size: 223
Created filesystem with 3833/224000 inodes and 328224/895121 blocks
Running ['mkuserimg.sh', '-s', 'out/target/product/chopin/system', 
            'out/target/product/chopin/obj/PACKAGING/systemimage_intermediates/system.img', 
            'ext4', 'system', '3666415616',
            '-D', 'out/target/product/chopin/system', '-L', 'system',
            'out/target/product/chopin/root/file_contexts.bin'
        ]command, exit code = 0

build_verity_tree -A axxxxxe7e7 out/target/product/chopin/obj/PACKAGING/systemimage_intermediates/system.img /tmp/tmptAeT9M_verity_images/verity.img
system/extras/verity/build_verity_metadata.py 3666415616 /tmp/tmptAeT9M_verity_images/verity_metadata.img 
                                            5fdddddd
                                            axxxxxe7e7
                                            /dev/block/bootdevice/by-name/system 
                                            verity_signer build/target/product/security/verity.pk8

cat /tmp/tmptAeT9M_verity_images/verity_metadata.img >> /tmp/tmptAeT9M_verity_images/verity.img
fec -e out/target/product/chopin/obj/PACKAGING/systemimage_intermediates/system.img 
        /tmp/tmptAeT9M_verity_images/verity.img 
        /tmp/tmptAeT9M_verity_images/verity_fec.img

cat /tmp/tmptAeT9M_verity_images/verity_fec.img >> /tmp/tmptAeT9M_verity_images/verity.img

append2simg out/target/product/chopin/obj/PACKAGING/systemimage_intermediates/system.img /tmp/tmptAeT9M_verity_images/verity.img
[ 87% 37963/43356] Install system fs image: out/target/product/chopin/system.img

out/target/product/chopin/system.img+out/target/product/chopin/obj/PACKAGING/recovery_patch_intermediates/recovery_from_boot.p 
maxsize=3802411008 blocksize=135168 total=1343068018 reserve=38522880
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值