FIT(3):基于FIT对镜像进行加密和解密
mkimage根据its配置对镜像进行加密,uboot解析FIT对加密部分进行解密,完成镜像内容保护。
1 生成FIT加密镜像
通过openssl rand生成32字节二进制秘钥文件:
openssl rand -out aes-key.bin 32
修改kernel.its文件,增加cipher节点:
/ {
images {
kernel {
cipher {
algo = "aes256";--使用aes256作为加解密算法。
key-name-hint = "aes-key";--会到-k <key dir>指定的目录中找名称为aes-key的秘钥文件作为输入秘钥。
};
};
};
};
mkimage根据its配置生成fit镜像,对镜像文件进行加密:
mkimage -k <key dir> -f kernel.its kernel.itb -K pub-key.dtb -r
生成的kernel.itb文件如下:
- data值是经过加密的数据。
- 新增IV值。
- algo指定解密算法。
- key-name-hint指定秘钥名称,从uboot dtb中获取秘钥。
/ { images { kernel {
data-size-unsiphered = <...>;
data = <...>; cipher {
iv = <...>; algo = "aes256"; key-name-hint = "aes-key"; }; }; }; };
生成的pub-key.dtb中包含的aes-key秘钥:
/ {
cipher {
key-aes256-aes-key {--根据kernel.itb中cipher的algo和key-name-hint配置可以匹配到对应的秘钥。
key-len = <0x20>;
key = <...>;
};
};
};
将上述cipher节点拷贝到uboot dtb的根节点下,uboot启动时,从dtb中获取秘钥。
2 uboot支持FIT解密
2.1 配置uboot支持FIT中加解密功能
打开CONFIG_FIT_CIPHER支持加解密功能:
Boot options
Boot images
Enable ciphering data in a FIT uImages
由于解密会通过malloc()分配内存,可以修改CONFIG_SYS_MALLOC_LEN增加内存容量。
2.2 uboot对FIT解密流程
当内核支持CONFIG_FIT_CIPHER后,如果FIT中存在cipher节点则会启动解密流程:
fit_image_load
fit_image_uncipher
fdt_subnode_offset--找到FIT中cipher节点。
fit_image_decrypt_data
fit_image_setup_decrypt
fit_get_name
fit_image_cipher_get_algo--获取cipher节点中加解密算法algo的值。
fdt_getprop--获取key-name-hint、iv、iv-name-hint的值。
image_get_cipher_algo--根据算法名称获取对应的struct cipher_algo。
fdt_getprop--根据keyname和ivname读取kery和iv的值。
info.cipher->decrypt--比如aes256算法,对应的函数是image_aes_decrypt。
支持的加解密算法如下:
struct cipher_algo cipher_algos[] = { { .name = "aes128", .key_len = AES128_KEY_LENGTH, .iv_len = AES_BLOCK_LENGTH, #if IMAGE_ENABLE_ENCRYPT .calculate_type = EVP_aes_128_cbc, #endif .encrypt = image_aes_encrypt, .decrypt = image_aes_decrypt, .add_cipher_data = image_aes_add_cipher_data }, { .name = "aes192", .key_len = AES192_KEY_LENGTH, .iv_len = AES_BLOCK_LENGTH, #if IMAGE_ENABLE_ENCRYPT .calculate_type = EVP_aes_192_cbc, #endif .encrypt = image_aes_encrypt, .decrypt = image_aes_decrypt, .add_cipher_data = image_aes_add_cipher_data }, { .name = "aes256", .key_len = AES256_KEY_LENGTH, .iv_len = AES_BLOCK_LENGTH, #if IMAGE_ENABLE_ENCRYPT .calculate_type = EVP_aes_256_cbc, #endif .encrypt = image_aes_encrypt, .decrypt = image_aes_decrypt, .add_cipher_data = image_aes_add_cipher_data } };
image_aes_decrypt使用AES CBC(128/192/256)算法对数据进行解密,需要的参数包括:源加密数据地址、源加密数据大小、从FIT中获取的解密算法/秘钥/IV,获取的参数包括解密数据地址和解密数据大小。
image_aes_decrypt
aes_expand_key
DIV_ROUND_UP--根据cipher_len对齐到128 bit block。
aes_cbc_decrypt_blocks--按照block为单位解密。
联系方式:arnoldlu@qq.com
浙公网安备 33010602011771号