Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: vboot_firmware/lib/vboot_kernel.c

Issue 2800007: Add load_kernel2_test (Closed) Base URL: ssh://gitrw.chromium.org/vboot_reference.git
Patch Set: Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « vboot_firmware/include/load_kernel_fw.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be 2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file. 3 * found in the LICENSE file.
4 * 4 *
5 * Functions for loading a kernel from disk. 5 * Functions for loading a kernel from disk.
6 * (Firmware portion) 6 * (Firmware portion)
7 */ 7 */
8 8
9 #include "vboot_kernel.h" 9 #include "vboot_kernel.h"
10 10
11 #include <inttypes.h> /* For PRIu64 */
11 #include "boot_device.h" 12 #include "boot_device.h"
12 #include "cgptlib.h" 13 #include "cgptlib.h"
13 #include "load_kernel_fw.h" 14 #include "load_kernel_fw.h"
14 #include "rollback_index.h" 15 #include "rollback_index.h"
15 #include "utility.h" 16 #include "utility.h"
16 #include "vboot_common.h" 17 #include "vboot_common.h"
17 18
18 19
19 #define KBUF_SIZE 65536 /* Bytes to read at start of kernel partition */ 20 #define KBUF_SIZE 65536 /* Bytes to read at start of kernel partition */
20 21
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 /* Clear output params in case we fail */ 129 /* Clear output params in case we fail */
129 params->partition_number = 0; 130 params->partition_number = 0;
130 params->bootloader_address = 0; 131 params->bootloader_address = 0;
131 params->bootloader_size = 0; 132 params->bootloader_size = 0;
132 133
133 if (is_normal) { 134 if (is_normal) {
134 /* Read current kernel key index from TPM. Assumes TPM is already 135 /* Read current kernel key index from TPM. Assumes TPM is already
135 * initialized. */ 136 * initialized. */
136 if (0 != GetStoredVersions(KERNEL_VERSIONS, 137 if (0 != GetStoredVersions(KERNEL_VERSIONS,
137 &tpm_key_version, 138 &tpm_key_version,
138 &tpm_kernel_version)) 139 &tpm_kernel_version)) {
140 debug("Unable to get stored version from TPM\n");
139 return LOAD_KERNEL_RECOVERY; 141 return LOAD_KERNEL_RECOVERY;
142 }
140 } else if (is_dev) { 143 } else if (is_dev) {
141 /* In developer mode, we ignore the kernel subkey, and just use 144 /* In developer mode, we ignore the kernel subkey, and just use
142 * the SHA-512 hash to verify the key block. */ 145 * the SHA-512 hash to verify the key block. */
143 kernel_subkey = NULL; 146 kernel_subkey = NULL;
144 } 147 }
145 148
146 do { 149 do {
147 /* Read GPT data */ 150 /* Read GPT data */
148 gpt.sector_bytes = blba; 151 gpt.sector_bytes = blba;
149 gpt.drive_sectors = params->ending_lba + 1; 152 gpt.drive_sectors = params->ending_lba + 1;
150 if (0 != AllocAndReadGptData(&gpt)) 153 if (0 != AllocAndReadGptData(&gpt)) {
154 debug("Unable to read GPT data\n");
151 break; 155 break;
156 }
152 157
153 /* Initialize GPT library */ 158 /* Initialize GPT library */
154 if (GPT_SUCCESS != GptInit(&gpt)) 159 if (GPT_SUCCESS != GptInit(&gpt)) {
160 debug("Error parsing GPT\n");
155 break; 161 break;
162 }
156 163
157 /* Allocate kernel header buffers */ 164 /* Allocate kernel header buffers */
158 kbuf = (uint8_t*)Malloc(KBUF_SIZE); 165 kbuf = (uint8_t*)Malloc(KBUF_SIZE);
159 if (!kbuf) 166 if (!kbuf)
160 break; 167 break;
161 168
162 /* Loop over candidate kernel partitions */ 169 /* Loop over candidate kernel partitions */
163 while (GPT_SUCCESS == GptNextKernelEntry(&gpt, &part_start, &part_size)) { 170 while (GPT_SUCCESS == GptNextKernelEntry(&gpt, &part_start, &part_size)) {
164 VbKeyBlockHeader* key_block; 171 VbKeyBlockHeader* key_block;
165 VbKernelPreambleHeader* preamble; 172 VbKernelPreambleHeader* preamble;
166 RSAPublicKey* data_key; 173 RSAPublicKey* data_key;
167 uint64_t key_version; 174 uint64_t key_version;
168 uint64_t body_offset; 175 uint64_t body_offset;
169 176
177 debug("Found kernel entry at %" PRIu64 " size %" PRIu64 "\n",
178 part_start, part_size);
179
170 /* Found at least one kernel partition. */ 180 /* Found at least one kernel partition. */
171 found_partitions++; 181 found_partitions++;
172 182
173 /* Read the first part of the kernel partition */ 183 /* Read the first part of the kernel partition */
174 if (part_size < kbuf_sectors) 184 if (part_size < kbuf_sectors)
175 continue; 185 continue;
176 if (0 != BootDeviceReadLBA(part_start, kbuf_sectors, kbuf)) 186 if (0 != BootDeviceReadLBA(part_start, kbuf_sectors, kbuf))
177 continue; 187 continue;
178 188
179 /* Verify the key block */ 189 /* Verify the key block */
180 key_block = (VbKeyBlockHeader*)kbuf; 190 key_block = (VbKeyBlockHeader*)kbuf;
181 if ((0 != KeyBlockVerify(key_block, KBUF_SIZE, kernel_subkey))) 191 if ((0 != KeyBlockVerify(key_block, KBUF_SIZE, kernel_subkey))) {
192 debug("Verifying key block failed.\n");
182 continue; 193 continue;
194 }
183 195
184 /* Check the key block flags against the current boot mode */ 196 /* Check the key block flags against the current boot mode */
185 if (!(key_block->key_block_flags && 197 if (!(key_block->key_block_flags &&
186 ((BOOT_FLAG_DEVELOPER & params->boot_flags) ? 198 ((BOOT_FLAG_DEVELOPER & params->boot_flags) ?
187 KEY_BLOCK_FLAG_DEVELOPER_1 : KEY_BLOCK_FLAG_DEVELOPER_0))) 199 KEY_BLOCK_FLAG_DEVELOPER_1 : KEY_BLOCK_FLAG_DEVELOPER_0))) {
200 debug("Developer flag mismatch.\n");
188 continue; 201 continue;
202 }
189 if (!(key_block->key_block_flags && 203 if (!(key_block->key_block_flags &&
190 ((BOOT_FLAG_RECOVERY & params->boot_flags) ? 204 ((BOOT_FLAG_RECOVERY & params->boot_flags) ?
191 KEY_BLOCK_FLAG_RECOVERY_1 : KEY_BLOCK_FLAG_RECOVERY_0))) 205 KEY_BLOCK_FLAG_RECOVERY_1 : KEY_BLOCK_FLAG_RECOVERY_0))) {
206 debug("Recovery flag mismatch.\n");
192 continue; 207 continue;
208 }
193 209
194 /* Check for rollback of key version. Note this is implicitly 210 /* Check for rollback of key version. Note this is implicitly
195 * skipped in recovery and developer modes because those set 211 * skipped in recovery and developer modes because those set
196 * key_version=0 above. */ 212 * key_version=0 above. */
197 key_version = key_block->data_key.key_version; 213 key_version = key_block->data_key.key_version;
198 if (key_version < tpm_key_version) 214 if (key_version < tpm_key_version) {
215 debug("Key version too old.\n");
199 continue; 216 continue;
217 }
200 218
201 /* Get the key for preamble/data verification from the key block */ 219 /* Get the key for preamble/data verification from the key block */
202 data_key = PublicKeyToRSA(&key_block->data_key); 220 data_key = PublicKeyToRSA(&key_block->data_key);
203 if (!data_key) 221 if (!data_key)
204 continue; 222 continue;
205 223
206 /* Verify the preamble, which follows the key block */ 224 /* Verify the preamble, which follows the key block */
207 preamble = (VbKernelPreambleHeader*)(kbuf + key_block->key_block_size); 225 preamble = (VbKernelPreambleHeader*)(kbuf + key_block->key_block_size);
208 if ((0 != VerifyKernelPreamble2(preamble, 226 if ((0 != VerifyKernelPreamble2(preamble,
209 KBUF_SIZE - key_block->key_block_size, 227 KBUF_SIZE - key_block->key_block_size,
210 data_key))) { 228 data_key))) {
229 debug("Preamble verification failed.\n");
211 RSAPublicKeyFree(data_key); 230 RSAPublicKeyFree(data_key);
212 continue; 231 continue;
213 } 232 }
214 233
215 /* Check for rollback of kernel version. Note this is implicitly 234 /* Check for rollback of kernel version. Note this is implicitly
216 * skipped in recovery and developer modes because those set 235 * skipped in recovery and developer modes because those set
217 * key_version=0 and kernel_version=0 above. */ 236 * key_version=0 and kernel_version=0 above. */
218 if (key_version == tpm_key_version && 237 if (key_version == tpm_key_version &&
219 preamble->kernel_version < tpm_kernel_version) { 238 preamble->kernel_version < tpm_kernel_version) {
239 debug("Kernel version too low.\n");
220 RSAPublicKeyFree(data_key); 240 RSAPublicKeyFree(data_key);
221 continue; 241 continue;
222 } 242 }
223 243
244 debug("Kernel preamble is good.\n");
245
224 /* Check for lowest key version from a valid header. */ 246 /* Check for lowest key version from a valid header. */
225 if (lowest_key_version > key_version) { 247 if (lowest_key_version > key_version) {
226 lowest_key_version = key_version; 248 lowest_key_version = key_version;
227 lowest_kernel_version = preamble->kernel_version; 249 lowest_kernel_version = preamble->kernel_version;
228 } 250 }
229 else if (lowest_key_version == key_version && 251 else if (lowest_key_version == key_version &&
230 lowest_kernel_version > preamble->kernel_version) { 252 lowest_kernel_version > preamble->kernel_version) {
231 lowest_kernel_version = preamble->kernel_version; 253 lowest_kernel_version = preamble->kernel_version;
232 } 254 }
233 255
234 /* If we already have a good kernel, no need to read another 256 /* If we already have a good kernel, no need to read another
235 * one; we only needed to look at the versions to check for 257 * one; we only needed to look at the versions to check for
236 * rollback. */ 258 * rollback. */
237 if (-1 != good_partition) 259 if (-1 != good_partition)
238 continue; 260 continue;
239 261
240 /* Verify body load address matches what we expect */ 262 /* Verify body load address matches what we expect */
241 if (preamble->body_load_address != (size_t)params->kernel_buffer) { 263 if ((preamble->body_load_address != (size_t)params->kernel_buffer) &&
264 !(params->boot_flags & BOOT_FLAG_SKIP_ADDR_CHECK)) {
265 debug("Wrong body load address.\n");
242 RSAPublicKeyFree(data_key); 266 RSAPublicKeyFree(data_key);
243 continue; 267 continue;
244 } 268 }
245 269
246 /* Verify kernel body starts at a multiple of the sector size. */ 270 /* Verify kernel body starts at a multiple of the sector size. */
247 body_offset = key_block->key_block_size + preamble->preamble_size; 271 body_offset = key_block->key_block_size + preamble->preamble_size;
248 if (0 != body_offset % blba) { 272 if (0 != body_offset % blba) {
273 debug("Kernel body not at multiple of sector size.\n");
249 RSAPublicKeyFree(data_key); 274 RSAPublicKeyFree(data_key);
250 continue; 275 continue;
251 } 276 }
252 277
253 /* Verify kernel body fits in the partition */ 278 /* Verify kernel body fits in the partition */
254 if (body_offset + preamble->body_signature.data_size > 279 if (body_offset + preamble->body_signature.data_size >
255 part_size * blba) { 280 part_size * blba) {
281 debug("Kernel body doesn't fit in partition.\n");
256 RSAPublicKeyFree(data_key); 282 RSAPublicKeyFree(data_key);
257 continue; 283 continue;
258 } 284 }
259 285
260 /* Read the kernel data */ 286 /* Read the kernel data */
261 if (0 != BootDeviceReadLBA( 287 if (0 != BootDeviceReadLBA(
262 part_start + (body_offset / blba), 288 part_start + (body_offset / blba),
263 (preamble->body_signature.data_size + blba - 1) / blba, 289 (preamble->body_signature.data_size + blba - 1) / blba,
264 params->kernel_buffer)) { 290 params->kernel_buffer)) {
291 debug("Unable to read kernel data.\n");
265 RSAPublicKeyFree(data_key); 292 RSAPublicKeyFree(data_key);
266 continue; 293 continue;
267 } 294 }
268 295
269 /* Verify kernel data */ 296 /* Verify kernel data */
270 if (0 != VerifyData((const uint8_t*)params->kernel_buffer, 297 if (0 != VerifyData((const uint8_t*)params->kernel_buffer,
271 &preamble->body_signature, data_key)) { 298 &preamble->body_signature, data_key)) {
299 debug("Kernel data verification failed.\n");
272 RSAPublicKeyFree(data_key); 300 RSAPublicKeyFree(data_key);
273 continue; 301 continue;
274 } 302 }
275 303
276 /* Done with the kernel signing key, so can free it now */ 304 /* Done with the kernel signing key, so can free it now */
277 RSAPublicKeyFree(data_key); 305 RSAPublicKeyFree(data_key);
278 306
279 /* If we're still here, the kernel is valid. */ 307 /* If we're still here, the kernel is valid. */
280 /* Save the first good partition we find; that's the one we'll boot */ 308 /* Save the first good partition we find; that's the one we'll boot */
281 if (-1 == good_partition) { 309 debug("Partiton is good.\n");
282 good_partition = gpt.current_kernel; 310 good_partition = gpt.current_kernel;
283 params->partition_number = gpt.current_kernel; 311 params->partition_number = gpt.current_kernel;
284 params->bootloader_address = preamble->bootloader_address; 312 params->bootloader_address = preamble->bootloader_address;
285 params->bootloader_size = preamble->bootloader_size; 313 params->bootloader_size = preamble->bootloader_size;
286 /* If we're in developer or recovery mode, there's no rollback 314 /* If we're in developer or recovery mode, there's no rollback
287 * protection, so we can stop at the first valid kernel. */ 315 * protection, so we can stop at the first valid kernel. */
288 if (!is_normal) 316 if (!is_normal)
289 break; 317 break;
290 318
291 /* Otherwise, we're in normal boot mode, so we do care about 319 /* Otherwise, we're in normal boot mode, so we do care about the
292 * the key index in the TPM. If the good partition's key 320 * key index in the TPM. If the good partition's key version is
293 * version is the same as the tpm, then the TPM doesn't need 321 * the same as the tpm, then the TPM doesn't need updating; we
294 * updating; we can stop now. Otherwise, we'll check all the 322 * can stop now. Otherwise, we'll check all the other headers
295 * other headers to see if they contain a newer key. */ 323 * to see if they contain a newer key. */
296 if (key_version == tpm_key_version && 324 if (key_version == tpm_key_version &&
297 preamble->kernel_version == tpm_kernel_version) 325 preamble->kernel_version == tpm_kernel_version)
298 break; 326 break;
299 }
300 } /* while(GptNextKernelEntry) */ 327 } /* while(GptNextKernelEntry) */
301 } while(0); 328 } while(0);
302 329
303 /* Free kernel buffer */ 330 /* Free kernel buffer */
304 if (kbuf) 331 if (kbuf)
305 Free(kbuf); 332 Free(kbuf);
306 333
307 /* Write and free GPT data */ 334 /* Write and free GPT data */
308 WriteAndFreeGptData(&gpt); 335 WriteAndFreeGptData(&gpt);
309 336
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 /* Success! */ 371 /* Success! */
345 return LOAD_KERNEL_SUCCESS; 372 return LOAD_KERNEL_SUCCESS;
346 } 373 }
347 374
348 // Handle error cases 375 // Handle error cases
349 if (found_partitions) 376 if (found_partitions)
350 return LOAD_KERNEL_INVALID; 377 return LOAD_KERNEL_INVALID;
351 else 378 else
352 return LOAD_KERNEL_NOT_FOUND; 379 return LOAD_KERNEL_NOT_FOUND;
353 } 380 }
OLDNEW
« no previous file with comments | « vboot_firmware/include/load_kernel_fw.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698