| OLD | NEW |
| 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 // Utility for manipulating verified boot kernel images. | 5 // Utility for manipulating verified boot kernel images. |
| 6 // | 6 // |
| 7 | 7 |
| 8 #include "kernel_utility.h" | 8 #include "kernel_utility.h" |
| 9 | 9 |
| 10 #include <getopt.h> | 10 #include <getopt.h> |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 OPT_IN, | 107 OPT_IN, |
| 108 OPT_OUT, | 108 OPT_OUT, |
| 109 OPT_GENERATE, | 109 OPT_GENERATE, |
| 110 OPT_VERIFY, | 110 OPT_VERIFY, |
| 111 OPT_DESCRIBE, | 111 OPT_DESCRIBE, |
| 112 OPT_VBLOCK, | 112 OPT_VBLOCK, |
| 113 OPT_BOOTLOADER, | 113 OPT_BOOTLOADER, |
| 114 OPT_VMLINUZ, | 114 OPT_VMLINUZ, |
| 115 OPT_CONFIG, | 115 OPT_CONFIG, |
| 116 OPT_PADDING, | 116 OPT_PADDING, |
| 117 OPT_SUBKEY, | 117 OPT_SUBKEY_OUT, |
| 118 }; | 118 }; |
| 119 static struct option long_options[] = { | 119 static struct option long_options[] = { |
| 120 {"firmware_key", 1, 0, OPT_FIRMWARE_KEY }, | 120 {"firmware_key", 1, 0, OPT_FIRMWARE_KEY }, |
| 121 {"firmware_key_pub", 1, 0, OPT_FIRMWARE_KEY_PUB }, | 121 {"firmware_key_pub", 1, 0, OPT_FIRMWARE_KEY_PUB }, |
| 122 {"kernel_key", 1, 0, OPT_KERNEL_KEY }, | 122 {"kernel_key", 1, 0, OPT_KERNEL_KEY }, |
| 123 {"kernel_key_pub", 1, 0, OPT_KERNEL_KEY_PUB }, | 123 {"kernel_key_pub", 1, 0, OPT_KERNEL_KEY_PUB }, |
| 124 {"subkey_in", 1, 0, OPT_SUBKEY_IN }, | 124 {"subkey_in", 1, 0, OPT_SUBKEY_IN }, |
| 125 {"firmware_sign_algorithm", 1, 0, OPT_FIRMWARE_SIGN_ALGORITHM }, | 125 {"firmware_sign_algorithm", 1, 0, OPT_FIRMWARE_SIGN_ALGORITHM }, |
| 126 {"kernel_sign_algorithm", 1, 0, OPT_KERNEL_SIGN_ALGORITHM }, | 126 {"kernel_sign_algorithm", 1, 0, OPT_KERNEL_SIGN_ALGORITHM }, |
| 127 {"kernel_key_version", 1, 0, OPT_KERNEL_KEY_VERSION }, | 127 {"kernel_key_version", 1, 0, OPT_KERNEL_KEY_VERSION }, |
| 128 {"kernel_version", 1, 0, OPT_KERNEL_VERSION }, | 128 {"kernel_version", 1, 0, OPT_KERNEL_VERSION }, |
| 129 {"in", 1, 0, OPT_IN }, | 129 {"in", 1, 0, OPT_IN }, |
| 130 {"out", 1, 0, OPT_OUT }, | 130 {"out", 1, 0, OPT_OUT }, |
| 131 {"generate", 0, 0, OPT_GENERATE }, | 131 {"generate", 0, 0, OPT_GENERATE }, |
| 132 {"verify", 0, 0, OPT_VERIFY }, | 132 {"verify", 0, 0, OPT_VERIFY }, |
| 133 {"describe", 0, 0, OPT_DESCRIBE }, | 133 {"describe", 0, 0, OPT_DESCRIBE }, |
| 134 {"vblock", 0, 0, OPT_VBLOCK }, | 134 {"vblock", 0, 0, OPT_VBLOCK }, |
| 135 {"bootloader", 1, 0, OPT_BOOTLOADER }, | 135 {"bootloader", 1, 0, OPT_BOOTLOADER }, |
| 136 {"vmlinuz", 1, 0, OPT_VMLINUZ }, | 136 {"vmlinuz", 1, 0, OPT_VMLINUZ }, |
| 137 {"config", 1, 0, OPT_CONFIG }, | 137 {"config", 1, 0, OPT_CONFIG }, |
| 138 {"padding", 1, 0, OPT_PADDING }, | 138 {"padding", 1, 0, OPT_PADDING }, |
| 139 {"subkey_out", 0, 0, OPT_SUBKEY }, | 139 {"subkey_out", 0, 0, OPT_SUBKEY_OUT }, |
| 140 {NULL, 0, 0, 0} | 140 {NULL, 0, 0, 0} |
| 141 }; | 141 }; |
| 142 while ((i = getopt_long(argc, argv, "", long_options, &option_index)) != -1) { | 142 while ((i = getopt_long(argc, argv, "", long_options, &option_index)) != -1) { |
| 143 switch (i) { | 143 switch (i) { |
| 144 case '?': | 144 case '?': |
| 145 return false; | 145 return false; |
| 146 break; | 146 break; |
| 147 case OPT_FIRMWARE_KEY: | 147 case OPT_FIRMWARE_KEY: |
| 148 firmware_key_file_ = optarg; | 148 firmware_key_file_ = optarg; |
| 149 break; | 149 break; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 break; | 224 break; |
| 225 case OPT_PADDING: | 225 case OPT_PADDING: |
| 226 padding_ = strtol(optarg, &e, 0); | 226 padding_ = strtol(optarg, &e, 0); |
| 227 if (!*optarg || (e && *e)) { | 227 if (!*optarg || (e && *e)) { |
| 228 cerr << "Invalid argument to --" | 228 cerr << "Invalid argument to --" |
| 229 << long_options[option_index].name | 229 << long_options[option_index].name |
| 230 << ": " << optarg << "\n"; | 230 << ": " << optarg << "\n"; |
| 231 return false; | 231 return false; |
| 232 } | 232 } |
| 233 break; | 233 break; |
| 234 case OPT_SUBKEY: | 234 case OPT_SUBKEY_OUT: |
| 235 is_subkey_out_ = true; | 235 is_subkey_out_ = true; |
| 236 break; | 236 break; |
| 237 } | 237 } |
| 238 } | 238 } |
| 239 return CheckOptions(); | 239 return CheckOptions(); |
| 240 } | 240 } |
| 241 | 241 |
| 242 void KernelUtility::OutputSignedImage(void) { | 242 void KernelUtility::OutputSignedImage(void) { |
| 243 if (image_) { | 243 if (image_) { |
| 244 if (!WriteKernelImage(out_file_.c_str(), image_, | 244 if (!WriteKernelImage(out_file_.c_str(), image_, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 &kernel_key_pub_len); | 276 &kernel_key_pub_len); |
| 277 if (!image_->kernel_sign_key) | 277 if (!image_->kernel_sign_key) |
| 278 return false; | 278 return false; |
| 279 image_->kernel_key_version = kernel_key_version_; | 279 image_->kernel_key_version = kernel_key_version_; |
| 280 | 280 |
| 281 // Update header length. | 281 // Update header length. |
| 282 image_->header_len = GetKernelHeaderLen(image_); | 282 image_->header_len = GetKernelHeaderLen(image_); |
| 283 // Calculate header checksum. | 283 // Calculate header checksum. |
| 284 CalculateKernelHeaderChecksum(image_, image_->header_checksum); | 284 CalculateKernelHeaderChecksum(image_, image_->header_checksum); |
| 285 | 285 |
| 286 // Generate and add the signatures. | 286 // Generate and add the key signatures. |
| 287 if (!AddKernelKeySignature(image_, firmware_key_file_.c_str())) { | 287 if (!AddKernelKeySignature(image_, firmware_key_file_.c_str())) { |
| 288 cerr << "Couldn't write key signature to verified boot kernel image.\n"; | 288 cerr << "Couldn't write key signature to verified boot kernel image.\n"; |
| 289 return false; | 289 return false; |
| 290 } | 290 } |
| 291 } else { | 291 } else { |
| 292 // Use existing subkey header. | 292 // Use existing subkey header. |
| 293 MemcpyState st; | 293 MemcpyState st; |
| 294 uint8_t* subkey_header_buf = NULL; | 294 uint8_t* subkey_header_buf = NULL; |
| 295 uint64_t subkey_len; | 295 uint64_t subkey_len; |
| 296 int header_len; | 296 int header_len; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 311 // TODO(gauravsh): This is basically the same code as the first half of | 311 // TODO(gauravsh): This is basically the same code as the first half of |
| 312 // of ReadKernelImage(). Refactor to eliminate code duplication. | 312 // of ReadKernelImage(). Refactor to eliminate code duplication. |
| 313 | 313 |
| 314 StatefulMemcpy(&st, &image_->header_version, FIELD_LEN(header_version)); | 314 StatefulMemcpy(&st, &image_->header_version, FIELD_LEN(header_version)); |
| 315 StatefulMemcpy(&st, &image_->header_len, FIELD_LEN(header_len)); | 315 StatefulMemcpy(&st, &image_->header_len, FIELD_LEN(header_len)); |
| 316 StatefulMemcpy(&st, &image_->firmware_sign_algorithm, | 316 StatefulMemcpy(&st, &image_->firmware_sign_algorithm, |
| 317 FIELD_LEN(firmware_sign_algorithm)); | 317 FIELD_LEN(firmware_sign_algorithm)); |
| 318 StatefulMemcpy(&st, &image_->kernel_sign_algorithm, | 318 StatefulMemcpy(&st, &image_->kernel_sign_algorithm, |
| 319 FIELD_LEN(kernel_sign_algorithm)); | 319 FIELD_LEN(kernel_sign_algorithm)); |
| 320 | 320 |
| 321 /* Valid Kernel Key signing algorithm. */ | 321 // Valid Kernel Key signing algorithm. |
| 322 if (image_->firmware_sign_algorithm >= kNumAlgorithms) { | 322 if (image_->firmware_sign_algorithm >= kNumAlgorithms) { |
| 323 Free(subkey_header_buf); | 323 Free(subkey_header_buf); |
| 324 return NULL; | 324 return NULL; |
| 325 } | 325 } |
| 326 | 326 |
| 327 /* Valid Kernel Signing Algorithm? */ | 327 // Valid Kernel Signing Algorithm? |
| 328 if (image_->kernel_sign_algorithm >= kNumAlgorithms) { | 328 if (image_->kernel_sign_algorithm >= kNumAlgorithms) { |
| 329 Free(subkey_header_buf); | 329 Free(subkey_header_buf); |
| 330 return NULL; | 330 return NULL; |
| 331 } | 331 } |
| 332 | 332 |
| 333 /* Compute size of pre-processed RSA public keys and signatures. */ | 333 // Compute size of pre-processed RSA public keys and signatures. |
| 334 kernel_key_signature_len = siglen_map[image_->firmware_sign_algorithm]; | 334 kernel_key_signature_len = siglen_map[image_->firmware_sign_algorithm]; |
| 335 kernel_sign_key_len = RSAProcessedKeySize(image_->kernel_sign_algorithm); | 335 kernel_sign_key_len = RSAProcessedKeySize(image_->kernel_sign_algorithm); |
| 336 | 336 |
| 337 /* Check whether key header length is correct. */ | 337 // Check whether key header length is correct. |
| 338 header_len = GetKernelHeaderLen(image_); | 338 header_len = GetKernelHeaderLen(image_); |
| 339 if (header_len != image_->header_len) { | 339 if (header_len != image_->header_len) { |
| 340 debug("Header length mismatch. Got: %d, Expected: %d\n", | 340 debug("Header length mismatch. Got: %d, Expected: %d\n", |
| 341 image_->header_len, header_len); | 341 image_->header_len, header_len); |
| 342 Free(subkey_header_buf); | 342 Free(subkey_header_buf); |
| 343 return NULL; | 343 return NULL; |
| 344 } | 344 } |
| 345 | 345 |
| 346 /* Read pre-processed public half of the kernel signing key. */ | 346 // Read pre-processed public half of the kernel signing key. |
| 347 StatefulMemcpy(&st, &image_->kernel_key_version, | 347 StatefulMemcpy(&st, &image_->kernel_key_version, |
| 348 FIELD_LEN(kernel_key_version)); | 348 FIELD_LEN(kernel_key_version)); |
| 349 image_->kernel_sign_key = (uint8_t*) Malloc(kernel_sign_key_len); | 349 image_->kernel_sign_key = (uint8_t*) Malloc(kernel_sign_key_len); |
| 350 StatefulMemcpy(&st, image_->kernel_sign_key, kernel_sign_key_len); | 350 StatefulMemcpy(&st, image_->kernel_sign_key, kernel_sign_key_len); |
| 351 StatefulMemcpy(&st, image_->header_checksum, FIELD_LEN(header_checksum)); | 351 StatefulMemcpy(&st, image_->header_checksum, FIELD_LEN(header_checksum)); |
| 352 | 352 |
| 353 /* Check whether the header checksum matches. */ | 353 // Check whether the header checksum matches. |
| 354 CalculateKernelHeaderChecksum(image_, header_checksum); | 354 CalculateKernelHeaderChecksum(image_, header_checksum); |
| 355 if (SafeMemcmp(header_checksum, image_->header_checksum, | 355 if (SafeMemcmp(header_checksum, image_->header_checksum, |
| 356 FIELD_LEN(header_checksum))) { | 356 FIELD_LEN(header_checksum))) { |
| 357 debug("Invalid kernel header checksum!\n"); | 357 debug("Invalid kernel header checksum!\n"); |
| 358 Free(subkey_header_buf); | 358 Free(subkey_header_buf); |
| 359 return NULL; | 359 return NULL; |
| 360 } | 360 } |
| 361 | 361 |
| 362 /* Read key signature. */ | 362 // Read key signature. |
| 363 image_->kernel_key_signature = (uint8_t*) Malloc(kernel_key_signature_len); | 363 image_->kernel_key_signature = (uint8_t*) Malloc(kernel_key_signature_len); |
| 364 StatefulMemcpy(&st, image_->kernel_key_signature, | 364 StatefulMemcpy(&st, image_->kernel_key_signature, |
| 365 kernel_key_signature_len); | 365 kernel_key_signature_len); |
| 366 |
| 366 Free(subkey_header_buf); | 367 Free(subkey_header_buf); |
| 367 if (st.overrun || st.remaining_len != 0) /* Overrun or underrun. */ | 368 if (st.overrun || st.remaining_len != 0) /* Overrun or underrun. */ |
| 368 return false; | 369 return false; |
| 369 return true; | 370 return true; |
| 370 } | 371 } |
| 371 | 372 |
| 372 // Fill up kernel preamble and kernel data. | 373 // Fill up kernel preamble and kernel data. |
| 373 image_->kernel_version = kernel_version_; | 374 image_->kernel_version = kernel_version_; |
| 374 if (padding_) | 375 if (padding_) |
| 375 image_->padded_header_size = padding_; | 376 image_->padded_header_size = padding_; |
| 376 image_->kernel_data = GenerateKernelBlob(vmlinuz_file_.c_str(), | 377 image_->kernel_data = GenerateKernelBlob(vmlinuz_file_.c_str(), |
| 377 config_file_.c_str(), | 378 config_file_.c_str(), |
| 378 bootloader_file_.c_str(), | 379 bootloader_file_.c_str(), |
| 379 &image_->kernel_len, | 380 &image_->kernel_len, |
| 380 &image_->bootloader_offset, | 381 &image_->bootloader_offset, |
| 381 &image_->bootloader_size); | 382 &image_->bootloader_size); |
| 382 if (!image_->kernel_data) | 383 if (!image_->kernel_data) |
| 383 return false; | 384 return false; |
| 384 | 385 |
| 386 // Generate and add the preamble and data signatures. |
| 385 if (!AddKernelSignature(image_, kernel_key_file_.c_str())) { | 387 if (!AddKernelSignature(image_, kernel_key_file_.c_str())) { |
| 386 cerr << "Couldn't write firmware signature to verified boot kernel image.\n"
; | 388 cerr << "Couldn't write firmware signature to verified boot kernel image.\n"
; |
| 387 return false; | 389 return false; |
| 388 } | 390 } |
| 389 return true; | 391 return true; |
| 390 } | 392 } |
| 391 | 393 |
| 392 bool KernelUtility::VerifySignedImage(void) { | 394 bool KernelUtility::VerifySignedImage(void) { |
| 393 int error; | 395 int error; |
| 394 firmware_key_pub_ = RSAPublicKeyFromFile(firmware_key_pub_file_.c_str()); | 396 firmware_key_pub_ = RSAPublicKeyFromFile(firmware_key_pub_file_.c_str()); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 } | 515 } |
| 514 else if (ku.is_verify()) { | 516 else if (ku.is_verify()) { |
| 515 cerr << "Verification "; | 517 cerr << "Verification "; |
| 516 if (ku.VerifySignedImage()) | 518 if (ku.VerifySignedImage()) |
| 517 cerr << "SUCCESS.\n"; | 519 cerr << "SUCCESS.\n"; |
| 518 else | 520 else |
| 519 cerr << "FAILURE.\n"; | 521 cerr << "FAILURE.\n"; |
| 520 } | 522 } |
| 521 return 0; | 523 return 0; |
| 522 } | 524 } |
| OLD | NEW |