Nelson, Mark
2018-05-25 11:46:04 UTC
Let me preface this by saying I'm using the xilinx-u-boot repo based on the 2017.4 tag.
I've been studying how to sign FIT images, using mkimage. I successfully signed an image and verified the signature as follows:
${UBTOOLS4}/mkimage -T multi -A arm64 -O linux -f images/linux/fitimage.its -K images/linux/public.dtb -k ${SEC_KEYSTORE} -r images/linux/image_secure.ub
${UBTOOLS4}/fit_check_sign -f images/linux/image_secure.ub -k images/linux/public.dtb
I'm signing the configuration in the fitimage.its as follows:
***@1 {
description = "Boot Linux kernel with FDT blob + ramdisk";
kernel = "***@0";
fdt = "***@0";
ramdisk = "***@0";
***@1 {
algo = "sha256,rsa2048";
key-name-hint = "linux_rsa_priv";
sign-images = "kernel", "fdt", "ramdisk";
};
};
However, when I tested booting the FIT image without providing the public key in Uboots control fdt, it booted successfully. It obviously should not boot a signed image without the key information. When I looked into this, I found that there are two routines called to verify required signatures when booting: fit_image_verify_required_sigs() and fit_config_verify_required_sigs(). The latter is for verifying the signatures in configuration nodes. Each of these routines begins with this logic:
/* Work out what we need to verify */
*no_sigsp = 1;
sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
if (sig_node < 0) {
debug("%s: No signature node found: %s\n", __func__,
fdt_strerror(sig_node));
return 0;
}
The problem is that if the fdt signature node(with the public key info) is not provided, this simply returns 0 for success, and the boot process continues successfully after it checks the hashes of the images. To fix the problem, I simply changed fit_config_verify_required_sigs() to return sig_node instead. If the signature is not there, the returned value is FDT_ERR_NOTFOUND, and the boot processing ends with:
Bad Data Hash
ERROR: can't get kernel image!
Notice that I didn't change the logic in fit_image_verify_required_sigs(), because I'm not including signatures on the images, just hashes. In that case, I want it to ignore the fact that it didn't find a signature node.
But surely, this solution is not the correct way. I know that IMAGE_ENABLE_VERIFY is used to gate access to fit_image_verify_required_sigs(), but there is nothing gating access to fit_config_verify_required_sigs() that I can see. I don't see any way to tell u-boot which signature method it should be using to verify: images or configs. It would seem that an additional preprocessor directive is needed. Am I missing something?
[cid:***@01D357D5.908FF380]<http://www.commscope.com/>
Mark Nelson
Principal Engineer
CommScope
250 Apollo Drive, Suite 100
Chelmsford, MA 01824
Mobile: 352-444-0150
I've been studying how to sign FIT images, using mkimage. I successfully signed an image and verified the signature as follows:
${UBTOOLS4}/mkimage -T multi -A arm64 -O linux -f images/linux/fitimage.its -K images/linux/public.dtb -k ${SEC_KEYSTORE} -r images/linux/image_secure.ub
${UBTOOLS4}/fit_check_sign -f images/linux/image_secure.ub -k images/linux/public.dtb
I'm signing the configuration in the fitimage.its as follows:
***@1 {
description = "Boot Linux kernel with FDT blob + ramdisk";
kernel = "***@0";
fdt = "***@0";
ramdisk = "***@0";
***@1 {
algo = "sha256,rsa2048";
key-name-hint = "linux_rsa_priv";
sign-images = "kernel", "fdt", "ramdisk";
};
};
However, when I tested booting the FIT image without providing the public key in Uboots control fdt, it booted successfully. It obviously should not boot a signed image without the key information. When I looked into this, I found that there are two routines called to verify required signatures when booting: fit_image_verify_required_sigs() and fit_config_verify_required_sigs(). The latter is for verifying the signatures in configuration nodes. Each of these routines begins with this logic:
/* Work out what we need to verify */
*no_sigsp = 1;
sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
if (sig_node < 0) {
debug("%s: No signature node found: %s\n", __func__,
fdt_strerror(sig_node));
return 0;
}
The problem is that if the fdt signature node(with the public key info) is not provided, this simply returns 0 for success, and the boot process continues successfully after it checks the hashes of the images. To fix the problem, I simply changed fit_config_verify_required_sigs() to return sig_node instead. If the signature is not there, the returned value is FDT_ERR_NOTFOUND, and the boot processing ends with:
Bad Data Hash
ERROR: can't get kernel image!
Notice that I didn't change the logic in fit_image_verify_required_sigs(), because I'm not including signatures on the images, just hashes. In that case, I want it to ignore the fact that it didn't find a signature node.
But surely, this solution is not the correct way. I know that IMAGE_ENABLE_VERIFY is used to gate access to fit_image_verify_required_sigs(), but there is nothing gating access to fit_config_verify_required_sigs() that I can see. I don't see any way to tell u-boot which signature method it should be using to verify: images or configs. It would seem that an additional preprocessor directive is needed. Am I missing something?
[cid:***@01D357D5.908FF380]<http://www.commscope.com/>
Mark Nelson
Principal Engineer
CommScope
250 Apollo Drive, Suite 100
Chelmsford, MA 01824
Mobile: 352-444-0150