X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=inline;f=doc%2FuImage.FIT%2Fsignature.txt;h=b2f89fcc65d0fd2a14693b26ce7f93ce0fe3412d;hb=8c8dc4c61518124eb35f4dd9d8466378ba247e9c;hp=0d145e00714278ebe625f8564b74dd6fee0d4990;hpb=3e569a6b1eb7ef0c8144f8c243f9e33c834bf003;p=u-boot diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt index 0d145e0071..b2f89fcc65 100644 --- a/doc/uImage.FIT/signature.txt +++ b/doc/uImage.FIT/signature.txt @@ -66,7 +66,8 @@ Creating an RSA key and certificate ----------------------------------- To create a new public key, size 2048 bits: -$ openssl genrsa -F4 -out keys/dev.key 2048 +$ openssl genpkey -algorithm RSA -out keys/dev.key \ + -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 To create a certificate for this: @@ -105,8 +106,27 @@ When the image is signed, the following properties are optional: - comment: Additional information about the signer or image +For config bindings (see Signed Configurations below), the following +additional properties are optional: -Example: See sign-images.its for an example image tree source file. +- sign-images: A list of images to sign, each being a property of the conf +node that contains then. The default is "kernel,fdt" which means that these +two images will be looked up in the config and signed if present. + +For config bindings, these properties are added by the signer: + +- hashed-nodes: A list of nodes which were hashed by the signer. Each is + a string - the full path to node. A typical value might be: + + hashed-nodes = "/", "/configurations/conf@1", "/images/kernel@1", + "/images/kernel@1/hash@1", "/images/fdt@1", + "/images/fdt@1/hash@1"; + +- hashed-strings: The start and size of the string region of the FIT that + was hashed + +Example: See sign-images.its for an example image tree source file and +sign-configs.its for config signing. Public Key Storage @@ -140,10 +160,158 @@ For RSA the following are mandatory: - rsa,num-bits: Number of key bits (e.g. 2048) - rsa,modulus: Modulus (N) as a big-endian multi-word integer +- rsa,exponent: Public exponent (E) as a 64 bit unsigned integer - rsa,r-squared: (2^num-bits)^2 as a big-endian multi-word integer - rsa,n0-inverse: -1 / modulus[0] mod 2^32 +Signed Configurations +--------------------- +While signing images is useful, it does not provide complete protection +against several types of attack. For example, it it possible to create a +FIT with the same signed images, but with the configuration changed such +that a different one is selected (mix and match attack). It is also possible +to substitute a signed image from an older FIT version into a newer FIT +(roll-back attack). + +As an example, consider this FIT: + +/ { + images { + kernel@1 { + data = + signature@1 { + algo = "sha1,rsa2048"; + value = <...kernel signature 1...> + }; + }; + kernel@2 { + data = + signature@1 { + algo = "sha1,rsa2048"; + value = <...kernel signature 2...> + }; + }; + fdt@1 { + data = ; + signature@1 { + algo = "sha1,rsa2048"; + vaue = <...fdt signature 1...> + }; + }; + fdt@2 { + data = ; + signature@1 { + algo = "sha1,rsa2048"; + vaue = <...fdt signature 2...> + }; + }; + }; + configurations { + default = "conf@1"; + conf@1 { + kernel = "kernel@1"; + fdt = "fdt@1"; + }; + conf@1 { + kernel = "kernel@2"; + fdt = "fdt@2"; + }; + }; +}; + +Since both kernels are signed it is easy for an attacker to add a new +configuration 3 with kernel 1 and fdt 2: + + configurations { + default = "conf@1"; + conf@1 { + kernel = "kernel@1"; + fdt = "fdt@1"; + }; + conf@1 { + kernel = "kernel@2"; + fdt = "fdt@2"; + }; + conf@3 { + kernel = "kernel@1"; + fdt = "fdt@2"; + }; + }; + +With signed images, nothing protects against this. Whether it gains an +advantage for the attacker is debatable, but it is not secure. + +To solved this problem, we support signed configurations. In this case it +is the configurations that are signed, not the image. Each image has its +own hash, and we include the hash in the configuration signature. + +So the above example is adjusted to look like this: + +/ { + images { + kernel@1 { + data = + hash@1 { + algo = "sha1"; + value = <...kernel hash 1...> + }; + }; + kernel@2 { + data = + hash@1 { + algo = "sha1"; + value = <...kernel hash 2...> + }; + }; + fdt@1 { + data = ; + hash@1 { + algo = "sha1"; + value = <...fdt hash 1...> + }; + }; + fdt@2 { + data = ; + hash@1 { + algo = "sha1"; + value = <...fdt hash 2...> + }; + }; + }; + configurations { + default = "conf@1"; + conf@1 { + kernel = "kernel@1"; + fdt = "fdt@1"; + signature@1 { + algo = "sha1,rsa2048"; + value = <...conf 1 signature...>; + }; + }; + conf@2 { + kernel = "kernel@2"; + fdt = "fdt@2"; + signature@1 { + algo = "sha1,rsa2048"; + value = <...conf 1 signature...>; + }; + }; + }; +}; + + +You can see that we have added hashes for all images (since they are no +longer signed), and a signature to each configuration. In the above example, +mkimage will sign configurations/conf@1, the kernel and fdt that are +pointed to by the configuration (/images/kernel@1, /images/kernel@1/hash@1, +/images/fdt@1, /images/fdt@1/hash@1) and the root structure of the image +(so that it isn't possible to add or remove root nodes). The signature is +written into /configurations/conf@1/signature@1/value. It can easily be +verified later even if the FIT has been signed with other keys in the +meantime. + + Verification ------------ FITs are verified when loaded. After the configuration is selected a list @@ -162,6 +330,9 @@ be enabled: CONFIG_FIT_SIGNATURE - enable signing and verfication in FITs CONFIG_RSA - enable RSA algorithm for signing +WARNING: When relying on signed FIT images with required signature check +the legacy image format is default disabled by not defining +CONFIG_IMAGE_FORMAT_LEGACY Testing ------- @@ -180,7 +351,9 @@ Simple Verified Boot Test Please see doc/uImage.FIT/verified-boot.txt for more information +/home/hs/ids/u-boot/sandbox/tools/mkimage -D -I dts -O dtb -p 2000 Build keys +do sha1 test Build FIT with signed images Test Verified Boot Run: unsigned signatures:: OK Sign images @@ -189,6 +362,25 @@ Build FIT with signed configuration Test Verified Boot Run: unsigned config: OK Sign images Test Verified Boot Run: signed config: OK +check signed config on the host +Signature check OK +OK +Test Verified Boot Run: signed config: OK +Test Verified Boot Run: signed config with bad hash: OK +do sha256 test +Build FIT with signed images +Test Verified Boot Run: unsigned signatures:: OK +Sign images +Test Verified Boot Run: signed images: OK +Build FIT with signed configuration +Test Verified Boot Run: unsigned config: OK +Sign images +Test Verified Boot Run: signed config: OK +check signed config on the host +Signature check OK +OK +Test Verified Boot Run: signed config: OK +Test Verified Boot Run: signed config with bad hash: OK Test passed