Add --minversion option to vbutil_kernel to check for rollback.

BUG=chrome-os-partner:3309
TEST=manual:

1. Extract a kernel partition from an image, for example, using
unpack_partitions.sh.  Or if running this on a device, use /dev/sda2
or /dev/sda4 for the kernel filename.

2. vbutil_kernel --verify part_2

3. Note the data key version and kernel version printed.  For example,

  Data key version:    1
  Kernel version:      3

4. Test specifying the same version.  This should succeed.

   vbutil_kernel --verify part_2 --minversion 0x00010003

5. Test specifying a higher data key version.  This should fail with a
data key version error.

   vbutil_kernel --verify part_2 --minversion 0x00020003

6. Test specifying a higher kernel version.  This should fail with a
kernel version error.

   vbutil_kernel --verify part_2 --minversion 0x00010004

Change-Id: I7b69041cf41527fc59ad29995135f30d9f496fac
Reviewed-on: http://gerrit.chromium.org/gerrit/792
Reviewed-by: Gaurav Shah <gauravsh@chromium.org>
Tested-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
Randall Spangler
2011-05-12 13:27:28 -07:00
parent 4dd03035c2
commit ae87b92cbe

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. /* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -46,6 +46,7 @@ enum {
OPT_VBLOCKONLY, OPT_VBLOCKONLY,
OPT_PAD, OPT_PAD,
OPT_VERBOSE, OPT_VERBOSE,
OPT_MINVERSION,
}; };
enum { enum {
@@ -64,6 +65,7 @@ static struct option long_opts[] = {
{"signpubkey", 1, 0, OPT_SIGNPUBKEY }, {"signpubkey", 1, 0, OPT_SIGNPUBKEY },
{"signprivate", 1, 0, OPT_SIGNPRIVATE }, {"signprivate", 1, 0, OPT_SIGNPRIVATE },
{"version", 1, 0, OPT_VERSION }, {"version", 1, 0, OPT_VERSION },
{"minversion", 1, 0, OPT_MINVERSION },
{"vmlinuz", 1, 0, OPT_VMLINUZ }, {"vmlinuz", 1, 0, OPT_VMLINUZ },
{"bootloader", 1, 0, OPT_BOOTLOADER }, {"bootloader", 1, 0, OPT_BOOTLOADER },
{"config", 1, 0, OPT_CONFIG }, {"config", 1, 0, OPT_CONFIG },
@@ -127,6 +129,8 @@ static int PrintHelp(char *progname) {
" --keyblock <file>" " --keyblock <file>"
" Outputs the verified key block, in .keyblock format\n" " Outputs the verified key block, in .keyblock format\n"
" --kloadaddr <address> Assign kernel body load address\n" " --kloadaddr <address> Assign kernel body load address\n"
" --minversion <number> Minimum combined kernel key version\n"
" and kernel version\n"
"\n", "\n",
progname); progname);
return 1; return 1;
@@ -660,7 +664,7 @@ static int ReplaceConfig(blob_t* bp, const char* config_file,
static int Verify(const char* infile, const char* signpubkey, int verbose, static int Verify(const char* infile, const char* signpubkey, int verbose,
const char* key_block_file, const char* key_block_file,
uint64_t kernel_body_load_address) { uint64_t kernel_body_load_address, uint64_t min_version) {
VbKeyBlockHeader* key_block; VbKeyBlockHeader* key_block;
VbKernelPreambleHeader* preamble; VbKernelPreambleHeader* preamble;
@@ -738,6 +742,12 @@ static int Verify(const char* infile, const char* signpubkey, int verbose,
PrintPubKeySha1Sum(data_key); PrintPubKeySha1Sum(data_key);
printf("\n"); printf("\n");
if (data_key->key_version < (min_version >> 16)) {
error("Data key version %" PRIu64 " is lower than minimum %" PRIu64".\n",
data_key->key_version, (min_version >> 16));
goto verify_exit;
}
rsa = PublicKeyToRSA(&key_block->data_key); rsa = PublicKeyToRSA(&key_block->data_key);
if (!rsa) { if (!rsa) {
error("Error parsing data key.\n"); error("Error parsing data key.\n");
@@ -765,6 +775,12 @@ static int Verify(const char* infile, const char* signpubkey, int verbose,
preamble->bootloader_address); preamble->bootloader_address);
printf(" Bootloader size: 0x%" PRIx64 "\n", preamble->bootloader_size); printf(" Bootloader size: 0x%" PRIx64 "\n", preamble->bootloader_size);
if (preamble->kernel_version < (min_version & 0xFFFF)) {
error("Kernel version %" PRIu64 " is lower than minimum %" PRIu64 ".\n",
preamble->kernel_version, (min_version & 0xFFFF));
goto verify_exit;
}
/* Verify body */ /* Verify body */
if (0 != VerifyData(bp->blob, bp->blob_size, &preamble->body_signature, if (0 != VerifyData(bp->blob, bp->blob_size, &preamble->body_signature,
rsa)) { rsa)) {
@@ -804,6 +820,7 @@ int main(int argc, char* argv[]) {
uint64_t pad = DEFAULT_PADDING; uint64_t pad = DEFAULT_PADDING;
int mode = 0; int mode = 0;
int parse_error = 0; int parse_error = 0;
uint64_t min_version = 0;
char* e; char* e;
int i,r; int i,r;
blob_t *bp; blob_t *bp;
@@ -899,6 +916,14 @@ int main(int argc, char* argv[]) {
} }
break; break;
case OPT_MINVERSION:
min_version = strtoul(optarg, &e, 0);
if (!*optarg || (e && *e)) {
fprintf(stderr, "Invalid --minversion\n");
parse_error = 1;
}
break;
case OPT_PAD: case OPT_PAD:
pad = strtoul(optarg, &e, 0); pad = strtoul(optarg, &e, 0);
if (!*optarg || (e && *e)) { if (!*optarg || (e && *e)) {
@@ -951,7 +976,7 @@ int main(int argc, char* argv[]) {
case OPT_MODE_VERIFY: case OPT_MODE_VERIFY:
return Verify(filename, signpubkey, verbose, key_block_file, return Verify(filename, signpubkey, verbose, key_block_file,
kernel_body_load_address); kernel_body_load_address, min_version);
default: default:
fprintf(stderr, fprintf(stderr,