5 Replies Latest reply on Jan 6, 2017 12:47 PM by Intel Corporation

    how to boot a signed kernel image from u-boot?

    jpkotta

      I want to boot a signed kernel.  Ideally, I could use u-boot's FIT image format.  I found many guides outlining how to do this, but most don't discuss x86 specifically.  Mostly I've just been trying to get the FIT image working.

       

      Normally I boot with a bzImage and an initrd, but the initrd can be ignored for now, because I can't even boot the kernel.

       

      If I try to boot with part of vmlinux image (`objcopy -O binary vmlinux vmlinux.bin`), it fails with `Image too large: increase CONFIG_SYS_BOOTM_LEN`, which I've increased to 32 MB and rebuilt u-boot, but it always happens.

       

      If I try to boot a bzImage, it fails with a general protection fault, which I think is actually due the `setup.bin` because the same error happens if I just load the `setup.bin` and do `go` on it.  I'm not even sure what `setup.bin` does, but apparently I need it according to the u-boot docs.

       

      I got `setup.bin` from `arch/x86/boot/setup.bin` in the kernel build tree.  I got vmlinux and bzImage from `build/tmp/deploy/images/edison/`.

       

      I've changed edison_defconfig in the u-boot source tree with CONFIG_FIT=y and CONFIG_SYS_BOOTM_LEN=33554432.  U-boot is correctly reading the FIT image, I just don't have the kernel/setup.bin images correct, or loading them at the wrong place, or something like that.

       

      Here's my fit-image.its:

       

      // see <uboot>/doc/uImage.FIT/source_file_format.txt
      // http://www.denx.de/wiki/pub/U-Boot/Documentation/multi_image_booting_scenarios.pdf
      
      
      /dts-v1/;
      / {
          description = "Linux kernel";
          #address-cells = <1>;
      
      
          images {
              kernel@1 {
                  description = "Linux kernel";
                  data = /incbin/("vmlinux.bin");
                  arch = "x86";
                  os = "linux";
                  type = "kernel";
                  // not compressed from u-boot's perspective
                  compression = "none";
                  load = <0x800000>;
                  entry = <0x800000>;
                  hash@1 {
                      algo = "sha256";
                  };
      
      
                  /*sigature@1 {
                      algo = "sha256,rsa2048";
                      key-name-hint = "xrd";
                  };*/
              };
      
      
              ramdisk@1 {
                  description = "initrd";
                  data = /incbin/("initrd");
                  type = "ramdisk";
                  arch = "x86";
                  os = "linux";
                  // not compressed from u-boot's perspective
                  compression = "none";
                  load = <0x100000>;
                  entry = <0x100000>;
                  hash@1 {
                      algo = "sha256";
                  };
      
      
                  /*sigature@1 {
                      algo = "sha256,rsa2048";
                      key-name-hint = "xrd";
                  };*/
              };
      
      
              setup@1 {
                  description = "setup.bin";
                  data = /incbin/("setup.bin");
                  type = "x86_setup";
                  arch = "x86";
                  os = "linux";
                  compression = "none";
                  load = <0x90000>;
                  entry = <0x90000>;
                  hash@1 {
                      algo = "sha256";
                  };
              };
          };
      
      
          configurations {
              default = "conf@1";
              conf@1 {
                  description = "Boot Linux Kernel";
                  kernel = "kernel@1";
                  ramdisk = "ramdisk@1";
                  setup = "setup@1";
      
      
                  /*signature@1 {
                      algo = "sha256,rsa2048";
                      key-name-hint = "xrd";
                      sign-images = "kernel,fdt";
                  };*/
              };
          };
      };
      
        • 1. Re: how to boot a signed kernel image from u-boot?
          Intel Corporation
          This message was posted on behalf of Intel Corporation

          Hello jpkotta,
           
          Thanks for reaching out!
           
          Please let me investigate to see if I can find some information that can help you. However, I must point out that U-boot modifications are not supported by us.
           
          -Peter.

          • 2. Re: how to boot a signed kernel image from u-boot?
            jpkotta

            After posting this I got the FIT image booting, including my initrd.  I needed to use `arch/x86/boot/vmlinux.bin`, which is different from both the `vmlinux.bin` that ends up in the root of the kernel build tree, and the `vmlinux.bin` that I created with `objcopy`.  I'll note that I'm using an XZ compressed kernel, but I'm sure a gzip or bzip2 kernel would work too, and no compression support needs to be in u-boot because the kernel decompresses itself.  I haven't gotten signing working yet, as I'm working on other things for a few days, but I'm guessing it will be a matter of following the docs.

            • 3. Re: how to boot a signed kernel image from u-boot?
              Intel Corporation
              This message was posted on behalf of Intel Corporation

              I'm glad to hear that you have managed to progress in your project. I encourage you to continue working on it and to share your progress in the community. Other users might find it helpful.

              I look forward to hear from you again.
              -Peter.

              • 4. Re: how to boot a signed kernel image from u-boot?
                jpkotta

                I got it working.  I found that the best tutorial was the BeagleBone tutorial from u-boot.

                 

                To create the FIT image, I needed my initrd (optional), arch/x86/boot/vmlinux.bin, and arch/x86/boot/setup.bin from a successfully built kernel (I added a .bbappend to the kernel recipe to make a new package containing these).  As explained before, the kernel is compressed and will decompress itself, thus there's no need to compress in the FIT.

                 

                Here's the boot.its:

                 

                // see <uboot>/doc/uImage.FIT/source_file_format.txt
                // http://www.denx.de/wiki/pub/U-Boot/Documentation/multi_image_booting_scenarios.pdf
                
                
                /dts-v1/;
                / {
                    description = "FIT Image";
                    //#address-cells = <1>;
                
                
                    images {
                        kernel@1 {
                            description = "Linux kernel";
                            data = /incbin/("vmlinux.bin");
                            arch = "x86";
                            os = "linux";
                            type = "kernel";
                            // not compressed from u-boot's perspective
                            compression = "none";
                            load = <0x1200000>;
                            entry = <0x1200000>;
                            hash@1 {
                                algo = "sha256";
                            };
                        };
                
                
                        ramdisk@1 {
                            description = "initrd";
                            data = /incbin/("initrd");
                            type = "ramdisk";
                            arch = "x86";
                            os = "linux";
                            // not compressed from u-boot's perspective
                            compression = "none";
                            load = <0x100000>;
                            entry = <0x100000>;
                            hash@1 {
                                algo = "sha256";
                            };
                        };
                
                
                        setup@1 {
                            description = "setup.bin";
                            data = /incbin/("setup.bin");
                            type = "x86_setup";
                            arch = "x86";
                            os = "linux";
                            compression = "none";
                            load = <0x90000>;
                            entry = <0x90000>;
                            hash@1 {
                                algo = "sha256";
                            };
                        };
                    };
                
                
                    configurations {
                        default = "conf@1";
                        conf@1 {
                            description = "Boot Linux Kernel";
                            kernel = "kernel@1";
                            ramdisk = "ramdisk@1";
                            setup = "setup@1";
                
                
                            signature@1 {
                                algo = "sha256,rsa2048";
                                key-name-hint = "xrd";
                                sign-images = "kernel","ramdisk","setup";
                            };
                        };
                    };
                };
                

                 

                I made the keys as directed in the tutorial, and named them `keys/xrd.crt` and `keys/xrd.key` ("xrd" is a codename for our device, the important thing is that this matches the "key-name-hint" field).

                 

                I needed to add these options to u-boot's defconfig:

                 

                CONFIG_FIT=y
                CONFIG_FIT_SIGNATURE=y
                CONFIG_RSA=y
                

                 

                And build u-boot with a dtb using `make EXT_DTB=/path/to/edison-pubkey.dtb`.  I made the dtb by taking the original dtb from `dts/dt.dtb` in a successfully built u-boot source tree.  Most tutorials will tell you to use `CONFIG_OF_SEPARATE=y`, and I got a working u-boot with that option (after figuring out all the weird post processing that edison expects), but it wouldn't recognize the key (I probably just had some small detail wrong).  Using the original dtb, I made the public key dtb with:

                 

                cp $uboot_src/dt.dtb edison-pubkey.dtb
                mkimage -f boot.its -k keys -K edison-pubkey.dtb -r boot.itb
                

                 

                The pwd should have the files referenced in boot.its (kernel, setup.bin, initrd), the `keys/` directory, and `edison-pubkey.dtb`.  After running that command, you get both a signed FIT (boot.itb) and an edited u-boot dtb with the public key (edison-pubkey.dtb).  To sign more images, you don't need the `-K foo.dtb` option.

                 

                Finally, in u-boot, to boot the FIT you can simply load the FIT somewhere that doesn't interfere with the load addresses in the FIT.

                 

                setenv loadaddr 0x20000000 # loadaddr is a special variable
                fatload mmc 1 $loadaddr boot.itb
                bootm
                

                 

                It should fail if the sig/hashes don't match.  It's checking the key if you see the lines:

                 

                   Using 'conf@1' configuration                 
                   Verifying Hash Integrity ... sha256,rsa2048:xrd+ OK
                

                 

                The "+" and "OK" means it passed the check, and the "rsa2048" means it's checking the sig.

                • 5. Re: how to boot a signed kernel image from u-boot?
                  Intel Corporation
                  This message was posted on behalf of Intel Corporation

                  Those are great new! Thank you for sharing this information with the community, we look forward to hearing more from you. In case you ever have any doubts, please don't hesitate to come back to the community, we'll try to help you in any way we can.

                  -Peter.