OLD | NEW |
1 #!/bin/bash | 1 #!/bin/bash |
2 | 2 |
3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 # Helper script that generates the signed kernel image | 7 # Helper script that generates the signed kernel image |
8 | 8 |
9 . "$(dirname "$0")/common.sh" | 9 . "$(dirname "$0")/common.sh" |
10 | 10 |
11 get_default_board | 11 get_default_board |
12 | 12 |
13 # Flags. | 13 # Flags. |
14 DEFINE_string arch "x86" \ | 14 DEFINE_string arch "x86" \ |
15 "The boot architecture: arm or x86. (Default: x86)" | 15 "The boot architecture: arm or x86. (Default: x86)" |
16 DEFINE_string to "/tmp/vmlinuz.image" \ | 16 DEFINE_string to "/tmp/vmlinuz.image" \ |
17 "The path to the kernel image to be created. (Default: /tmp/vmlinuz.image)" | 17 "The path to the kernel image to be created. (Default: /tmp/vmlinuz.image)" |
18 DEFINE_string vmlinuz "vmlinuz" \ | 18 DEFINE_string vmlinuz "vmlinuz" \ |
19 "The path to the kernel (Default: vmlinuz)" | 19 "The path to the kernel (Default: vmlinuz)" |
20 DEFINE_string working_dir "/tmp/vmlinuz.working" \ | 20 DEFINE_string working_dir "/tmp/vmlinuz.working" \ |
21 "Working directory for in-progress files. (Default: /tmp/vmlinuz.working)" | 21 "Working directory for in-progress files. (Default: /tmp/vmlinuz.working)" |
22 DEFINE_boolean keep_work ${FLAGS_FALSE} \ | 22 DEFINE_boolean keep_work ${FLAGS_FALSE} \ |
23 "Keep temporary files (*.keyblock, *.vbpubk). (Default: false)" | 23 "Keep temporary files (*.keyblock, *.vbpubk). (Default: false)" |
24 DEFINE_string keys_dir "${SRC_ROOT}/platform/vboot_reference/tests/testkeys" \ | 24 DEFINE_string keys_dir "${SRC_ROOT}/platform/vboot_reference/tests/testkeys" \ |
25 "Directory with the RSA signing keys. (Defaults to test keys)" | 25 "Directory with the RSA signing keys. (Defaults to test keys)" |
26 # Note, to enable verified boot, the caller would pass: | 26 # Note, to enable verified boot, the caller would manually pass: |
27 # --boot_args='dm="... /dev/sd%D%P /dev/sd%D%P ..." \ | 27 # --boot_args='dm="... /dev/sd%D%P /dev/sd%D%P ..." \ |
28 # --root=/dev/dm-0 | 28 # --root=/dev/dm-0 |
29 DEFINE_string boot_args "noinitrd" \ | 29 DEFINE_string boot_args "noinitrd" \ |
30 "Additional boot arguments to pass to the commandline (Default: noinitrd)" | 30 "Additional boot arguments to pass to the commandline (Default: noinitrd)" |
31 DEFINE_string root "/dev/sd%D%P" \ | 31 DEFINE_string root "/dev/sd%D%P" \ |
32 "Expected device root (Default: root=/dev/sd%D%P)" | 32 "Expected device root (Default: root=/dev/sd%D%P)" |
33 | 33 |
| 34 # If provided, will automatically add verified boot arguments. |
| 35 DEFINE_string rootfs_image "" \ |
| 36 "Optional path to the rootfs device or image.(Default: \"\")" |
| 37 DEFINE_string rootfs_hash "" \ |
| 38 "Optional path to output the rootfs hash to. (Default: \"\")" |
| 39 DEFINE_integer vboot_error_behavior 2 \ |
| 40 "Verified boot error behavior [0: I/O errors, 1: reboot, 2: nothing] \ |
| 41 (Default: 2)" |
| 42 DEFINE_integer vboot_tree_depth 1 \ |
| 43 "Optional Verified boot hash tree depth. (Default: 1)" |
| 44 DEFINE_integer vboot_max_ios 1024 \ |
| 45 "Optional number of outstanding I/O operations. (Default: 1024)" |
| 46 DEFINE_string vboot_hash_alg "sha1" \ |
| 47 "Cryptographic hash algorithm used for vboot. (Default: sha1)" |
| 48 |
34 # Parse flags | 49 # Parse flags |
35 FLAGS "$@" || exit 1 | 50 FLAGS "$@" || exit 1 |
36 eval set -- "${FLAGS_ARGV}" | 51 eval set -- "${FLAGS_ARGV}" |
37 | 52 |
38 # Die on error | 53 # Die on error |
39 set -e | 54 set -e |
40 | 55 |
| 56 vboot_args= |
| 57 # Even with a rootfs_image, root= is not changed unless specified. |
| 58 if [[ -n "${FLAGS_rootfs_image}" && -n "${FLAGS_rootfs_hash}" ]]; then |
| 59 info "Determining root fs block count." |
| 60 # Gets the number of blocks. 4096 byte blocks _are_ expected. |
| 61 root_fs_blocks=$(sudo dumpe2fs "${FLAGS_rootfs_image}" 2> /dev/null | |
| 62 grep "Block count" | |
| 63 tr -d ' ' | |
| 64 cut -f2 -d:) |
| 65 info "Checking root fs block size." |
| 66 root_fs_block_sz=$(sudo dumpe2fs "${FLAGS_rootfs_image}" 2> /dev/null | |
| 67 grep "Block size" | |
| 68 tr -d ' ' | |
| 69 cut -f2 -d:) |
| 70 if [[ ${root_fs_block_sz} -ne 4096 ]]; then |
| 71 error "Root file system blocks are not 4k!" |
| 72 fi |
| 73 |
| 74 info "Generating root fs hash tree." |
| 75 # Runs as sudo in case the image is a block device. |
| 76 table=$(sudo verity create ${FLAGS_vboot_tree_depth} \ |
| 77 ${FLAGS_vboot_hash_alg} \ |
| 78 ${FLAGS_rootfs_image} \ |
| 79 ${root_fs_blocks} \ |
| 80 ${FLAGS_rootfs_hash}) |
| 81 # Don't claim the root device unless the root= flag is pointed to |
| 82 # the verified boot device. Doing so will claim /dev/sdDP out from |
| 83 # under the system. |
| 84 if [[ ${FLAGS_root} = "/dev/dm-0" ]]; then |
| 85 table=${table//HASH_DEV/\/dev\/sd%D%P} |
| 86 table=${table//ROOT_DEV/\/dev\/sd%D%P} |
| 87 fi |
| 88 vboot_args="dm=\"${table}\"" |
| 89 info "dm-verity configuration: ${vboot_args}" |
| 90 fi |
| 91 |
| 92 mkdir -p "${FLAGS_working_dir}" |
| 93 cat <<EOF > "${FLAGS_working_dir}/boot.config" |
| 94 root=${FLAGS_root} |
| 95 dm_verity.error_behavior=${FLAGS_vboot_error_behavior} |
| 96 dm_verity.max_bios=${FLAGS_vboot_max_ios} |
| 97 ${vboot_args} |
| 98 ${FLAGS_boot_args} |
| 99 EOF |
| 100 |
| 101 WORK="${WORK} ${FLAGS_working_dir}/boot.config" |
| 102 info "Emitted cross-platform boot params to ${FLAGS_working_dir}/boot.config" |
| 103 |
41 # FIXME: At the moment, we're working on signed images for x86 only. ARM will | 104 # FIXME: At the moment, we're working on signed images for x86 only. ARM will |
42 # support this before shipping, but at the moment they don't. | 105 # support this before shipping, but at the moment they don't. |
43 if [[ "${FLAGS_arch}" = "x86" ]]; then | 106 if [[ "${FLAGS_arch}" = "x86" ]]; then |
44 | 107 |
45 # Legacy BIOS will use the kernel in the rootfs (via syslinux), as will | 108 # Legacy BIOS will use the kernel in the rootfs (via syslinux), as will |
46 # standard EFI BIOS (via grub, from the EFI System Partition). Chrome OS | 109 # standard EFI BIOS (via grub, from the EFI System Partition). Chrome OS |
47 # BIOS will use a separate signed kernel partition, which we'll create now. | 110 # BIOS will use a separate signed kernel partition, which we'll create now. |
48 # FIXME: remove serial output, debugging messages. | 111 # FIXME: remove serial output, debugging messages. |
49 mkdir -p ${FLAGS_working_dir} | 112 mkdir -p ${FLAGS_working_dir} |
50 cat <<EOF > "${FLAGS_working_dir}/config.txt" | 113 cat <<EOF | cat - "${FLAGS_working_dir}/boot.config" \ |
| 114 > "${FLAGS_working_dir}/config.txt" |
51 earlyprintk=serial,ttyS0,115200 | 115 earlyprintk=serial,ttyS0,115200 |
52 console=ttyS0,115200 | 116 console=ttyS0,115200 |
53 init=/sbin/init | 117 init=/sbin/init |
54 add_efi_memmap | 118 add_efi_memmap |
55 boot=local | 119 boot=local |
56 rootwait | 120 rootwait |
57 root=${FLAGS_root} | |
58 ro | 121 ro |
59 noresume | 122 noresume |
60 noswap | 123 noswap |
61 i915.modeset=1 | 124 i915.modeset=1 |
62 loglevel=7 | 125 loglevel=7 |
63 cros_secure | 126 cros_secure |
64 ${FLAGS_boot_args} | |
65 EOF | 127 EOF |
66 WORK="${FLAGS_working_dir}/config.txt" | 128 WORK="${WORK} ${FLAGS_working_dir}/config.txt" |
67 | 129 |
68 | 130 |
69 # FIX: The .vbprivk files are not encrypted, so we shouldn't just leave them | 131 # FIX: The .vbprivk files are not encrypted, so we shouldn't just leave them |
70 # lying around as a general thing. | 132 # lying around as a general thing. |
71 | 133 |
72 # Wrap the kernel data keypair, used for the kernel body | 134 # Wrap the kernel data keypair, used for the kernel body |
73 vbutil_key \ | 135 vbutil_key \ |
74 --pack "${FLAGS_working_dir}/kernel_data_key.vbpubk" \ | 136 --pack "${FLAGS_working_dir}/kernel_data_key.vbpubk" \ |
75 --key "${FLAGS_keys_dir}/key_rsa2048.keyb" \ | 137 --key "${FLAGS_keys_dir}/key_rsa2048.keyb" \ |
76 --version 1 \ | 138 --version 1 \ |
77 --algorithm 4 | 139 --algorithm 4 |
78 WORK="${WORK} ${FLAGS_working_dir}/kernel_data_key.vbpubk" | 140 WORK="${WORK} ${FLAGS_working_dir}/kernel_data_key.vbpubk" |
79 | 141 |
80 vbutil_key \ | 142 vbutil_key \ |
81 --pack "${FLAGS_working_dir}/kernel_data_key.vbprivk" \ | 143 --pack "${FLAGS_working_dir}/kernel_data_key.vbprivk" \ |
82 --key "${FLAGS_keys_dir}/key_rsa2048.pem" \ | 144 --key "${FLAGS_keys_dir}/key_rsa2048.pem" \ |
83 --algorithm 4 | 145 --algorithm 4 |
84 WORK="${WORK} ${FLAGS_working_dir}/kernel_data_key.vbprivk" | 146 WORK="${WORK} ${FLAGS_working_dir}/kernel_data_key.vbprivk" |
85 | 147 |
86 | 148 |
87 # Wrap the kernel subkey pair, used for the kernel's keyblock | 149 # Wrap the kernel subkey pair, used for the kernel's keyblock |
88 vbutil_key \ | 150 vbutil_key \ |
89 --pack "${FLAGS_working_dir}/kernel_subkey.vbpubk" \ | 151 --pack "${FLAGS_working_dir}/kernel_subkey.vbpubk" \ |
90 --key "${FLAGS_keys_dir}/key_rsa4096.keyb" \ | 152 --key "${FLAGS_keys_dir}/key_rsa4096.keyb" \ |
91 --version 1 \ | 153 --version 1 \ |
92 --algorithm 8 | 154 --algorithm 8 |
93 WORK="${WORK} ${FLAGS_working_dir}/kernel_subkey.vbpubk" | 155 WORK="${WORK} ${FLAGS_working_dir}/kernel_subkey.vbpubk" |
94 | 156 |
95 vbutil_key \ | 157 vbutil_key \ |
96 --pack "${FLAGS_working_dir}/kernel_subkey.vbprivk" \ | 158 --pack "${FLAGS_working_dir}/kernel_subkey.vbprivk" \ |
97 --key "${FLAGS_keys_dir}/key_rsa4096.pem" \ | 159 --key "${FLAGS_keys_dir}/key_rsa4096.pem" \ |
98 --algorithm 8 | 160 --algorithm 8 |
99 WORK="${WORK} ${FLAGS_working_dir}/kernel_subkey.vbprivk" | 161 WORK="${WORK} ${FLAGS_working_dir}/kernel_subkey.vbprivk" |
100 | 162 |
101 | 163 |
102 # Create the kernel keyblock, containing the kernel data key | 164 # Create the kernel keyblock, containing the kernel data key |
103 vbutil_keyblock \ | 165 vbutil_keyblock \ |
104 --pack "${FLAGS_working_dir}/kernel.keyblock" \ | 166 --pack "${FLAGS_working_dir}/kernel.keyblock" \ |
105 --datapubkey "${FLAGS_working_dir}/kernel_data_key.vbpubk" \ | 167 --datapubkey "${FLAGS_working_dir}/kernel_data_key.vbpubk" \ |
106 --signprivate "${FLAGS_working_dir}/kernel_subkey.vbprivk" \ | 168 --signprivate "${FLAGS_working_dir}/kernel_subkey.vbprivk" \ |
107 --flags 15 | 169 --flags 15 |
108 WORK="${WORK} ${FLAGS_working_dir}/kernel.keyblock" | 170 WORK="${WORK} ${FLAGS_working_dir}/kernel.keyblock" |
109 | 171 |
110 # Verify the keyblock. | 172 # Verify the keyblock. |
111 vbutil_keyblock \ | 173 vbutil_keyblock \ |
112 --unpack "${FLAGS_working_dir}/kernel.keyblock" \ | 174 --unpack "${FLAGS_working_dir}/kernel.keyblock" \ |
113 --signpubkey "${FLAGS_working_dir}/kernel_subkey.vbpubk" | 175 --signpubkey "${FLAGS_working_dir}/kernel_subkey.vbpubk" |
114 | 176 |
115 # TODO: We should sign the kernel blob using the recovery root key and recovery | 177 # TODO: We should sign the kernel blob using the recovery root key and |
116 # kernel data key instead (to create the recovery image), and then re-sign it | 178 # recovery kernel data key instead (to create the recovery image), and then |
117 # this way for the install image. But we'll want to keep the install vblock | 179 # re-sign it this way for the install image. But we'll want to keep the |
118 # separate, so we can just copy that part over separately when we install it | 180 # install vblock separate, so we can just copy that part over separately when |
119 # instead of the whole kernel blob. | 181 # we install it instead of the whole kernel blob. |
120 | 182 |
121 # Create and sign the kernel blob | 183 # Create and sign the kernel blob |
122 vbutil_kernel \ | 184 vbutil_kernel \ |
123 --pack "${FLAGS_to}" \ | 185 --pack "${FLAGS_to}" \ |
124 --keyblock "${FLAGS_working_dir}/kernel.keyblock" \ | 186 --keyblock "${FLAGS_working_dir}/kernel.keyblock" \ |
125 --signprivate "${FLAGS_working_dir}/kernel_data_key.vbprivk" \ | 187 --signprivate "${FLAGS_working_dir}/kernel_data_key.vbprivk" \ |
126 --version 1 \ | 188 --version 1 \ |
127 --config "${FLAGS_working_dir}/config.txt" \ | 189 --config "${FLAGS_working_dir}/config.txt" \ |
128 --bootloader /lib64/bootstub/bootstub.efi \ | 190 --bootloader /lib64/bootstub/bootstub.efi \ |
129 --vmlinuz "${FLAGS_vmlinuz}" | 191 --vmlinuz "${FLAGS_vmlinuz}" |
130 | 192 |
131 # And verify it. | 193 # And verify it. |
132 vbutil_kernel \ | 194 vbutil_kernel \ |
133 --verify "${FLAGS_to}" \ | 195 --verify "${FLAGS_to}" \ |
134 --signpubkey "${FLAGS_working_dir}/kernel_subkey.vbpubk" | 196 --signpubkey "${FLAGS_working_dir}/kernel_subkey.vbpubk" |
135 | 197 |
136 else | 198 elif [[ "${FLAGS_arch}" = "arm" ]]; then |
137 # FIXME: For now, ARM just uses the unsigned kernel by itself. | 199 # FIXME: For now, ARM just uses the unsigned kernel by itself. |
138 cp -f "${FLAGS_vmlinuz}" "${FLAGS_to}" | 200 cp -f "${FLAGS_vmlinuz}" "${FLAGS_to}" |
| 201 else |
| 202 error "Unknown arch: ${FLAGS_arch}" |
139 fi | 203 fi |
140 | 204 |
141 set +e # cleanup failure is a-ok | 205 set +e # cleanup failure is a-ok |
142 | 206 |
143 if [[ ${FLAGS_keep_work} -eq ${FLAGS_FALSE} ]]; then | 207 if [[ ${FLAGS_keep_work} -eq ${FLAGS_FALSE} ]]; then |
144 echo "Cleaning up temporary files: ${WORK}" | 208 info "Cleaning up temporary files: ${WORK}" |
145 rm ${WORK} | 209 rm ${WORK} |
146 rmdir ${FLAGS_working_dir} | 210 rmdir ${FLAGS_working_dir} |
147 fi | 211 fi |
148 | 212 |
149 echo "Kernel partition image emitted: ${FLAGS_to}" | 213 info "Kernel partition image emitted: ${FLAGS_to}" |
| 214 |
| 215 if [[ -f ${FLAGS_rootfs_hash} ]]; then |
| 216 info "Root filesystem hash emitted: ${FLAGS_rootfs_hash}" |
| 217 fi |
OLD | NEW |