From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ron Brash Date: Thu, 23 Feb 2017 10:48:10 -0500 Subject: [U-Boot] Complete verified uboot example In-Reply-To: References: Message-ID: List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hello all (and thanks Mr. Altherr for this insight), Excellent feedback and I agree that all of this needs to find a home either on the global docs on the website and/or the text-only documentation. Regardless, this leads me to a few questions. NOTE: the use of a uboot control DTS, control DTB and control FTD even in Mr. Altherr's email is confusion provoking. One term to rule them all is needed ;) 1.) What if a board doesn't have OR has ever been configured to use u-boot DTS (could we call this a UDTS or something friendly to differentiate that fact?); this was a point of misunderstanding until I started scampering around into arch/arm/dts/? * For example, my board is a derivative of an Atmel at91sam9g20. It had a very generic implementation of a DTS that covered reference boards in the Linux kernel, but required a fair bit of modification to make it work. As the at91sam(legacy platform) isn't in u-boot's source tree for a DTS - what would someone like me need to do - do we have a barebones tutorial (again I don't mind publishing such with proofing)? Is it even required if we have a platform/board already working in the traditional u-boot way? 2.) Just to summarise - everything winds up in two binaries: u-boot and the FIT image. So the partition scheme would more or less would look like: /----------------- * Bootstrap/ROM (optional) /---------------- * U-boot * Control DTB * Has keys * Driver loadout/init /---------------- * U-boot env *---------------- * FIT image * ITS * Kernel * DTS * .... /--------------- * Rootfs etc... * ... /--------------- 3.) What people used to use to load X address into Z location in memory is now removed by the usage of a DTB in u-boot correct? I assume that the u-boot DTB now does this and bootarg/bootcmd is partially done away with - as its arguments are augmented by said file. Anybody have the spare cycles to organise a web-tutorial/presentation/recording with me on a play-by-play to make all of this make sense? I'm aiming to be in Prague for the 2017 conference in October, might be a good place to showcase this fine-tuning. Ron On 22 February 2017 at 13:51, Rick Altherr wrote: > > On Tue, Feb 21, 2017 at 10:08 AM, Ron Brash wrote: > >> Hello all, >> >> I am adding verified kernel support on a board we are using and I am >> struggling to fully understand all of the concepts and steps required to >> pull everything together (on ARM, using ZImages and booting with a working >> DTB on 4.4.3x). I also looked at the test script inside of examples, but >> it left me with more questions than understanding. >> >> Please correct me where appropriate in my understanding, but if I am >> confused, likely others are too and I hope this helps everyone involved >> overall. >> > > You've asked some really good questions. Hopefully this discussion will > end up with patches to clarify the docs. > > >> >> Steps: >> --------------------------------------------------------------- >> >> First, u-boot needs to have the appropriate features enabled and to be >> built using them. At a minimum, I suspect: >> >> CONFIG_RSA=y >> CONFIG_FIT=y >> CONFIG_FIT_SIGNATURE=y >> CONFIG_OF_CONTROL=y >> >> > Yup. That looks right. > > >> Next, we need to derive the appropriate cryptographic primitives/keys. >> >> #Generate a private signing key (RSA2048): >> openssl genrsa -F4 -out \ >> "${key_dir}"/"${key_name}".key 2048 >> >> # Generate a public key: >> openssl req -batch -new -x509 \ >> -key "${key_dir}"/"${key_name}".key \ >> -out "${key_dir}"/"${key_name}".crt >> >> > So far so good. In general, I suggest having multiple signing keys. You > can put all the public keys in your u-boot so an image signed with any of > those keys will be accepted. If you happen to have a signing key > compromised, you can switch to one of the other ones. With that other key, > you can sign an update the removes the compromised public key from future > images. > > >> Then we derive the ITS or image source file - a file that hints/describes >> the elements that will be verified and/or inside of the FIT image? Lets >> call this $FIT_ITS >> >> FIT is a container format. Generally, you'll create a FIT that contains > the zImage, dtb, initramfs, etc. With FIT support enabled in u-boot, you > only need to provide the single FIT image address to 'bootm'. u-boot will > use the config section to find the individual elements, load them into RAM > as needed, and boot. > > >> / dts - v1 /; >> / { >> description = "Configuration to load a Xen Kernel"; >> #address-cells = <1>; >> images { >> linux_kernel @ 1 { >> description = "Linux zImage"; >> data = /incbin / ("pathToImage/zImage"); >> type = "kernel"; >> arch = "arm"; >> os = "linux"; >> compression = "none"; >> load = <0xaf600000 >; >> entry = <0xaf600000 >; >> hash @ 1 { >> algo = "sha1"; >> }; >> }; >> fdt @ 1 { >> description = "FDT blob"; >> data = /incbin / ("PathToDTBUsedByBootingKernel/ex.dtb"); >> type = "flat_dt"; >> arch = "arm"; >> compression = "none"; >> load = <0xaec00000 >; >> > > You generally don't need a 'load' property for the FDT or an initramfs. > Without one, U-Boot will allocate RAM dynamically, if needed, and pass the > relocated address to the kernel. > > hash @ 1 { >> algo = "sha1"; >> }; >> }; >> }; >> configurations { >> default = "config at 1"; >> config @ 1 { >> description = "Plain Linux"; >> kernel = "linux_kernel at 1"; >> fdt = "fdt at 1"; >> loadables = "linux_kernel at 1"; >> > > 'loadables' is for other types of firmware. You only need the 'kernel' > property for loading and booting the kernel. > > >> }; >> }; >> }; >> >> Question: Does a signature section go into this as well? underneath the >> hash node for each value? > > >> signature at 1 { >> algo = "sha1,rsa2048"; >> value = <...kernel signature 1...> >> }; >> > > You add a signature section to each image you want signed within the FIT. > In your case, add one for both the kernel and FDT images. Signatures go > _next_ to the hash section, not in it. Omit the 'value' property as it > will be generated for you later. > > >> >> Then using the device-tree-compiler (dtc), I create a DTB for u-boot. >> This >> is the control FDT and this defines what keys are used etc.. >> > > The control FDT is used for U-Boot's driver model _as well as_ providing > public keys for verifying images. Your board may not currently use a > control FDT in which case you create one from scratch. > > >> >> #Assemble control FDT for U-Boot with space for public key: >> $DTC -p 0x1000 u-boot.dts -O dtb -o u-boot.dtb >> >> Question: What is required inside of the u-boot.dts for u-boot? Is it >> simply the same .dts used by the booting kernel, but with a section >> proclaiming the keys? >> > > This depends on the board you are using. For example, an AST2500 requires > a DTB for U-Boot to load the right drivers. The DTB used by U-Boot is > slightly different from that used by Linux as the Linux DTB often includes > addition configuration information. When using verified boot, the U-Boot > DTB includes the public keys whereas the FDT/DTB stored in the FIT does not > as Linux doesn't need them. > > >> >> Question: Where will the compiled u-boot.dtb eventually go? Is this put >> into a FIT image, or flashed onto the board alongside the u-boot >> bootloader >> itself? >> > > The U-Boot control FDT is compiled into the U-Boot binary. The FDT in the > FIT is the FDT that is provided to Linux. > > >> >> Next, given that the above steps are completed, I need to create a FIT >> image with space for the signature. >> >> # Generate fitImage with space for signature: >> $MKIMG -D "-I dts -O dtb -p 2000" \ >> -f f$FIT_ITS $FIT_IMG >> >> Question: Is the FIT_IMAGE the actual zimage or is it an output image that >> contains all of the values contained within the ITS? >> > > The latter. It will have a compiled version of the ITS as well as the > actual images specified in the ITS (kernel, fdt). > > >> >> Next this FIT_IMAGE (assuming that this is the final FIT image that >> contains the FDT and zImage) needs to be signed and the public key added >> to >> it; given that that the key information is in the uboot. >> > > You sign the FIT_IMAGE and put the public keys in the control DTB. > > >> >> # Sign fitImage and add public key into u-boot.dtb: >> $MKIMG -D "-I dts -O dtb -p 2000" -F \ >> -k "${key dir}" -K u-boot.dtb -r $FIT_IMG >> > > This is putting the public keys used by the FIT image into the control DTB > > >> >> Then, we sign the subsequent fitImage again - correct? >> >> # Signing subsequent fitImage: >> $MKIMG -D "-I dts -O dtb -p 2000" \ >> -k "${key dir}" -f $FIT_ITS -r $FIT_IMG >> > > This is generating signatures for the images in the FIT and storing those > signatures in the FIT. > > >> >> Now that all of the above is done - we need to: >> 1. Write our uboot to the flash >> 2. Write our FIT_IMAGE to flash >> >> Question: Do we write anything else to persistent storage? The ITS? etc.. >> > > No. Everything is contained in the U-Boot binary (control FDT including > public keys) and the FIT (images, signatures) > >> >> Question: Do we just boot using anything else or just bootm >> 0xLocationOfTheFitImageInRAM >> > > The latter. bootm will check the config section in the FIT and use the > kernel, fdt, etc specified there. > > >> >> Greatly appreciate any assistance to all of these questions and I'm sure >> this threat will be of interest to anyone else too. >> >> Thanks! > > _______________________________________________ >> U-Boot mailing list >> U-Boot at lists.denx.de >> http://lists.denx.de/mailman/listinfo/u-boot >> > >