u-boot: signature check for u-boot scripts

Heiko Schocher hs at denx.de
Tue Jan 10 14:18:22 CET 2023


Hello Simon,

I just digging into the topic "check a signed U-Boot script
before sourcing it" ...

Therefore I have packed the U-Boot script into a FIT image
and enabled FIT_SIGNATURE. In cmd/source.c

136                 /* verify integrity */
137                 if (verify) {
138                         if (!fit_image_verify(fit_hdr, noffset)) {
139                                 puts ("Bad Data Hash\n");
140                                 return 1;
141                         }
142                 }

fit_image_verify() gets called which seems fine .. but
fit_image_verify() always returns 0 ... and so, script gets always executed,
also if I source a fitimage containing a script without *any* signature
nodes, see [1]!

When I source a signed script and changing the hash before calling it,
there is output [2] ... at least it shows "sha256,rsa2048:dev-" ... so
correct detected, that hash is wrong ... but script gets executed...

comment in boot/image-fit.c fit_image_verify_with_data()
"""
1388                         /*
1389                          * Show an indication on failure, but do not return
1390                          * an error. Only keys marked 'required' can cause
1391                          * an image validation failure. See the call to
1392                          * fit_image_verify_required_sigs() above.
1393                          */
"""

Hmm... see dump of signature node from u-boot-dtb [3]

Hmm... It seems I miss something obvious?

BTW: checking signature of an fitimage (used for booting kernel/dts/ramdisk)
works fine ...

May you have an its file as an example for creating a signed script?
(But at least, it should not execute a script, without any signature info!)

Am I correct?

While writting this email ... in [3] the line

 require = "conf"

poped into my eyes .... and in fit_image_verify_required_sigs() there is check:

                if (!required || strcmp(required, "image"))
                        continue;

and yes! changing in [3]

-required = "conf";
+required = "image";

makes sourcing the signed script working (error in case of no
signature or wrong signature)! ... but booting the signed fitimage
now breaks ... so it seems, I cannot use configuration signing with
images signing ?

I tried to add two key nodes in signature node of u-boot dtb ... one with
require = "conf" and one with require = "image" ... but no luck...

Also adding a configurations section to scripts its file did not helped
(which will not prevent the problem sourcing a not signed script)

Any ideas?

(In the meantime I mamanged to get it working, by adding also a configuration
 node to my its file, and adding configuration parsing in cmd/source.c, see [4],
 which solves all above problems ... but no idea if there is an eleganter
 solution?)

Thanks!

bye,
Heiko

[1] log (with some printfs in code)

=> tftp 100000 script.bin;setenv verify 1;source 100000
Speed: 1000, full duplex
Using ethernet at 24000 device
TFTP from server 192.168.3.1; our IP address is 192.168.3.40
Filename 'script.bin'.
Load address: 0x100000
Loading: #
         150.4 KiB/s
done
Bytes transferred = 464 (1d0 hex)
## Executing script at 00100000
image_source_script: fit_uname: script-1
fit_image_verify_with_data: ------------
fit_image_verify_required_sigs: ------------ key_node: 96
fit_image_verify_with_data: ------------ after fit_image_verify_required_sigs verify_all: 1
fit_image_verify_with_data: ------------ name: hash-1 FIT_SIG_NODENAME: signature
sha256+ Hallo from script
=> fdt addr 100000
Working FDT set to 100000
=> fdt print
/ {
        timestamp = <0x63bd2ea4>;
        description = "Bootscript";
        #address-cells = <0x00000001>;
        images {
                default = "script-1";
                script-1 {
                        data = "echo Hallo from script
";
                        type = "script";
                        compression = "none";
                        hash-1 {
                                value = <0x4f9ef4c9 0x64b6027a 0xc0bf7019 0x2f21411f 0x3a03bb96
0x526e6cc0 0x172a6203 0x07ebd90e>;
                                algo = "sha256";
                        };
                };
        };
};
=>

[2] executing signed script but with changing hash

=> tftp 100000 script.bin.signed;setenv verify 1;mw 001001c0 0 1;source 100000
Speed: 1000, full duplex
Using ethernet at 24000 device
TFTP from server 192.168.3.1; our IP address is 192.168.3.40
Filename 'script.bin.signed'.
Load address: 0x100000
Loading: #
         230.5 KiB/s
done
Bytes transferred = 947 (3b3 hex)
## Executing script at 00100000
image_source_script: fit_uname: script-1
fit_image_verify_with_data: ------------
fit_image_verify_required_sigs: ------------ key_node: 96
fit_image_verify_with_data: ------------ after fit_image_verify_required_sigs verify_all: 1
fit_image_verify_with_data: ------------ name: hash-1 FIT_SIG_NODENAME: signature
sha256+ fit_image_verify_with_data: ------------ name: signature FIT_SIG_NODENAME: signature
sha256,rsa2048:dev- Hallo from script
=>
=> fdt addr 100000
Working FDT set to 100000
=> fdt print
/ {
        timestamp = <0x63bd4956>;
        description = "Bootscript";
        #address-cells = <0x00000001>;
        images {
                default = "script-1";
                script-1 {
                        data = "echo Hallo from script
";
                        type = "script";
                        compression = "none";
                        hash-1 {
                                value = <0x4f9ef4c9 0x64b6027a 0xc0bf7019 0x2f21411f 0x3a03bb96
0x526e6cc0 0x172a6203 0x07ebd90e>;
                                algo = "sha256";
                        };
                        signature {
                                timestamp = <0x63bd4956>;
                                signer-version = "2023.01";
                                signer-name = "mkimage";
                                value = <0x2e93fd56 0xe68c3438 0x29440a3d 0x96a84453 0xfbf74c67
0x1ca47d4c 0xe712e5b0 0xa02a20ee 0xeda24836 0xab68efda 0xdae0e1a6 0x40b084e8 0x3adf3f72 0x977167dc
0x222b8897 0xb04323da 0x48b00d5a 0x00000000 0x23589310 0x8e5c84d1 0xf1b90ae0 0x37a96c48 0x1de295ed
0xdd02fbc4 0x7d97da60 0x2bfb9254 0xafff2fe9 0xb49034b5 0xc709f2aa 0xb7035c1c 0xc4219f9c 0x68f68b7d
0x8be03f02 0x83dc2a25 0x7b9056c0 0x1f6dbb5d 0xdc409948 0x9265fd61 0x10e78ef6 0xd7d6ba6a 0x0f45f622
0xaee09fee 0x65347dcd 0xbf1e640a 0x91f2aa7d 0x6a1aad9e 0x40edda89 0x7b4e1074 0xf0bda924 0xff8f95bf
0x6a743aa6 0x739cf6cc 0x77455534 0x958a79b0 0xf58a0f77 0x546d55ae 0xb4332204 0x2b69d4bf 0xcf2277b3
0xe6a5b9fa 0xbe0c2984 0x2a9b3a06 0xb1bfee79 0x1719227f>;
                                algo = "sha256,rsa2048";
                                key-name-hint = "dev";
                                sign-images = "script";
                        };
                };
        };
};
=>

[3] u-boot.dtb
        signature {

                key-dev {
                        required = "conf";
                        algo = "sha256,rsa2048";
                        rsa,r-squared = < 0x4d76ec8 0x32c73f36 0x1885a88a 0x38c5f9da 0x76058623
0x144a9f4e 0x3b68693 0x12a3a7c3 0x63fe3d39 0x64050d31 0x3b4d47ec 0x43c0d6c0 0x5b473005 0x6ba07db0
0x834b69cf 0xc77d3d18 0x90a16449 0xca7ea292 0xbd5c7e8d 0xb12873b2 0xbd9854e6 0xa12bd2ca 0x49524aca
0x666fa5ad 0x60b46068 0xf8beb7 0x4f035cac 0x3d7f0d00 0x307cb78a 0xf7d69d41 0x4458b11e 0x796593b4
0x70f5d606 0x730a7eea 0xfacdf9c 0x944a88a0 0x91485179 0x86f28224 0xc753ad58 0xa108107c 0x7211253d
0x48c11ce4 0xaabdd41f 0x867090c 0x908feb8b 0x2eb6c136 0x723d4628 0xfa398444 0x5ce50ddc 0xf213d06e
0x5109ec8d 0xa7aa27ec 0x31877d93 0x140a82b8 0x5637d12e 0x1df9457d 0xfa461126 0x284b3222 0x40251e90
0x921ed1cb 0xeb1d610a 0xa4350b0a 0x35c82d04 0x6d1de495 >;
                        rsa,modulus = < 0xb389fbdd 0xeac4c5c2 0xd5cdc76d 0x6bc8baef 0xcb1ccbb8
0xb045b4bc 0x61050af2 0x6fb72ee2 0x2cd1ebda 0x1935151a 0x1737507b 0xd99d7fcc 0xf7260741 0xcf27e93c
0x20e10005 0xa50b6358 0x6d5425d0 0x46668c49 0xa0e6d424 0x58be4ea2 0xd150aad9 0x15e48d65 0x96015d2e
0xf51eff2b 0x60490625 0xfa3e9e42 0x7c73be97 0x45e478be 0x52f57239 0x1682038d 0xd967dabc 0xafda9fd7
0xfe33a251 0xa5dc776c 0x966b36ab 0xeff0e172 0xdd3ab637 0xd061cbbd 0x5f498c4b 0xfdbb51df 0xb2dd74c4
0x98211ba0 0x3f711d0a 0xdf10c112 0x482ad0b2 0x7e48cea4 0x98ad8437 0x3aa3da75 0x3054d5fd 0x23c77cc5
0x3bc2ba2e 0x303d7d57 0x2a2d54e0 0xf740c870 0x1df2aca7 0x456dd158 0xe41796a 0xec9a7d09 0xad858e31
0xc95e53f9 0x5384346f 0x31f05039 0xe1121bd4 0x6c039a05 >;
                        rsa,exponent = < 0x00 0x10001 >;
                        rsa,n0-inverse = < 0x38aadd33 >;
                        rsa,num-bits = < 0x800 >;
                        key-name-hint = "dev";
                };
        };

[4] hack to get signed scripts working
diff --git a/cmd/source.c b/cmd/source.c
index 698d9f86d9..c658a77ea3 100644
--- a/cmd/source.c
+++ b/cmd/source.c
@@ -134,10 +134,23 @@ int image_source_script(ulong addr, const char *fit_uname)

                /* verify integrity */
                if (verify) {
+                       int cfg_noffset;
+
                        if (!fit_image_verify(fit_hdr, noffset)) {
                                puts ("Bad Data Hash\n");
                                return 1;
                        }
+
+                       cfg_noffset = fdt_path_offset(fit_hdr, "/configurations/conf-1");
+                       if (cfg_noffset < 0) {
+                               puts("no config node\n");
+                               return 1;
+                       }
+
+                       if (fit_config_verify(fit_hdr, cfg_noffset)) {
+                               puts("Bad Data Hash\n");
+                               return 1;
+                       }
                }

                /* get script subimage data address and length */

[5] its file to get [4] working
$ cat temp/script.its
/dts-v1/;

/ {

        description = "Bootscript";
        #address-cells = <1>;
        images {
                default = "script-1";
                script-1 {
                        data = /incbin/("/work/big2/hs/temp/script.scr");
                        type = "script";
                        compression = "none";
                        hash-1 {
                                algo = "sha256";
                        };
                };
        };

        configurations {
                default = "conf-1";
                conf-1 {
                        description = "First signed script";
                        script = "script-1";
                        signature {
                                algo = "sha256,rsa2048";
                                key-name-hint = "dev";
                                sign-images = "script";
                        };
                };
        };
};
-- 
DENX Software Engineering GmbH,      Managing Director: Erika Unter
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs at denx.de


More information about the U-Boot mailing list