Vboot reference:  A basic user-land verified boot firmware signing and verification utility.

This is a first cut at what I envision as a utility we can use to manage our firmware/kernel signing needs. Currently, it implements firmware signing (given a binary image, create a verified boot header) and verification (given a verified boot image, verify it using the given public root key).

This CL also fixes the ReadFirmwareImage function from firmware_image to make it more consistent and fixes some bugs.

Review URL: http://codereview.chromium.org/652216
diff --git a/utils/Makefile b/utils/Makefile
index c0de74e..5005645 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 CC ?= gcc
+CXX ?= g++
 CFLAGS = -Wall -DNDEBUG
 INCLUDES ?= -I../include/
 TOP ?= ../
@@ -22,8 +23,8 @@
 signature_digest: signature_digest.c
 	$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(FIRMWARELIBS)
 
-firmware_utility: firmware_utility.c firmware_image.o file_keys.c
-	$(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ $(FIRMWARELIBS)
+firmware_utility: firmware_utility.cc firmware_image.o file_keys.o
+	$(CXX) $(CFLAGS) $(INCLUDES) -ggdb $^ -o $@ $(FIRMWARELIBS)
 
 # Used by tests.
 file_keys.o: file_keys.c
@@ -34,5 +35,5 @@
 
 clean:
 	rm -f dumpRSAPublicKey verify_data signature_digest firmware_image.o \
-	file_keys.o
+	file_keys.o firmware_utility
 
diff --git a/utils/file_keys.c b/utils/file_keys.c
index bcba749..2401a15 100644
--- a/utils/file_keys.c
+++ b/utils/file_keys.c
@@ -19,7 +19,7 @@
 #include "rsa_utility.h"
 #include "utility.h"
 
-uint8_t* BufferFromFile(char* input_file, int* len) {
+uint8_t* BufferFromFile(const char* input_file, uint32_t* len) {
   int fd;
   struct stat stat_fd;
   uint8_t* buf = NULL;
@@ -49,15 +49,18 @@
   return buf;
 }
 
-RSAPublicKey* RSAPublicKeyFromFile(char* input_file) {
-  int len;
+RSAPublicKey* RSAPublicKeyFromFile(const char* input_file) {
+  uint32_t len;
+  RSAPublicKey* key;
   uint8_t* buf = BufferFromFile(input_file, &len);
-  RSAPublicKey* key = RSAPublicKeyFromBuf(buf, len);
+  if (buf)
+    key = RSAPublicKeyFromBuf(buf, len);
   Free(buf);
   return key;
 }
 
-uint8_t* SignatureFile(char* input_file, char* key_file, int algorithm) {
+uint8_t* SignatureFile(const char* input_file, const char* key_file,
+                       int algorithm) {
   char* sign_utility = "./sign_data.sh";
   char* cmd;  /* Command line to invoke. */
   int cmd_len;
diff --git a/utils/firmware_image.c b/utils/firmware_image.c
index 07aa8bd..714d5dd 100644
--- a/utils/firmware_image.c
+++ b/utils/firmware_image.c
@@ -25,54 +25,40 @@
 #define FIELD_LEN(field) (sizeof(((FirmwareImage*)0)->field))
 
 FirmwareImage* FirmwareImageNew(void) {
-  FirmwareImage* fw = (FirmwareImage*) Malloc(sizeof(FirmwareImage));
-  return fw;
+  FirmwareImage* image = (FirmwareImage*) Malloc(sizeof(FirmwareImage));
+  if (image) {
+    image->sign_key = NULL;
+    image->preamble_signature = NULL;
+    image->firmware_signature = NULL;
+    image->firmware_data = NULL;
+  }
+  return image;
 }
 
 void FirmwareImageFree(FirmwareImage* image) {
-  Free(image->sign_key);
-  Free(image->key_signature);
-  Free(image->preamble_signature);
-  Free(image->firmware_signature);
-  Free(image->firmware_data);
+  if (image) {
+    Free(image->sign_key);
+    Free(image->preamble_signature);
+    Free(image->firmware_signature);
+    Free(image->firmware_data);
+  }
 }
 
-FirmwareImage* ReadFirmwareImage(const char* input_file,
-                                 FirmwareImage* image) {
-  int fd;
-  struct stat fd_stat;
-
+FirmwareImage* ReadFirmwareImage(const char* input_file) {
+  uint32_t file_size;
   int image_len = 0;  /* Total size of the firmware image. */
   int header_len = 0;
   int sign_key_len;
   int signature_len;
   uint8_t* firmware_buf;
   MemcpyState st;
+  FirmwareImage* image = FirmwareImageNew();
 
   if (!image)
     return NULL;
 
-  if (-1 == (fd = open(input_file, O_RDONLY))) {
-    fprintf(stderr, "Couldn't open file for reading.\n");
-    return NULL;
-  }
-
-  if (-1 == fstat(fd, &fd_stat)) {
-    fprintf(stderr, "Couldn't stat file.\n");
-    close(fd);
-    return NULL;
-  }
-
-  firmware_buf = (uint8_t*) Malloc(fd_stat.st_size);
-  image_len = fd_stat.st_size;
-
-  /* Read entire file into a buffer. */
-  if (image_len != read(fd, firmware_buf, image_len)) {
-    fprintf(stderr, "Couldn't read file data.\n");
-    close(fd);
-    return NULL;
-  }
-  close(fd);
+  firmware_buf = BufferFromFile(input_file, &file_size);
+  image_len = file_size;
 
   st.remaining_len = image_len;
   st.remaining_buf = firmware_buf;
@@ -86,41 +72,43 @@
     goto parse_failure;
   }
 
-  StatefulMemcpy(&st, &image->header_len, sizeof(image->header_len));
-  StatefulMemcpy(&st, &image->sign_algorithm, sizeof(image->sign_algorithm));
+  StatefulMemcpy(&st, &image->header_len, FIELD_LEN(header_len));
+  StatefulMemcpy(&st, &image->sign_algorithm, FIELD_LEN(sign_algorithm));
 
   /* Valid Algorithm? */
-  if (image->sign_algorithm > kNumAlgorithms)
+  if (image->sign_algorithm >= kNumAlgorithms)
     goto parse_failure;
 
   /* Compute size of pre-processed RSA public key and signature. */
-  sign_key_len = (2*siglen_map[image->sign_algorithm]*sizeof(uint32_t)
-                     + sizeof(uint32_t) + sizeof(int));
+  sign_key_len = RSAProcessedKeySize(image->sign_algorithm);
   signature_len = siglen_map[image->sign_algorithm] * sizeof(uint32_t);
 
 
   /* Check whether the header length is correct. */
-  header_len = (sizeof(image->header_len) + sizeof(image->sign_algorithm) +
-                sizeof(image->key_version) +
-                sizeof(image->header_checksum));
+  header_len = (FIELD_LEN(header_len) +
+                FIELD_LEN(sign_algorithm) +
+                sign_key_len +
+                FIELD_LEN(key_version) +
+                FIELD_LEN(header_checksum));
   if (header_len != image->header_len) {
-    fprintf(stderr, "Header length mismatch.");
+    fprintf(stderr, "Header length mismatch. Got: %d Expected: %d\n",
+            image->header_len, header_len);
     goto parse_failure;
   }
 
   /* Read pre-processed public half of the sign key. */
   image->sign_key = (uint8_t*) Malloc(sign_key_len);
   StatefulMemcpy(&st, image->sign_key, sign_key_len);
-  StatefulMemcpy(&st, &image->key_version, sizeof(image->key_version));
-  StatefulMemcpy(&st, image->header_checksum, sizeof(image->header_checksum));
+  StatefulMemcpy(&st, &image->key_version, FIELD_LEN(key_version));
+  StatefulMemcpy(&st, image->header_checksum, FIELD_LEN(header_checksum));
 
   /* Read key signature. */
-  StatefulMemcpy(&st, image->key_signature, sizeof(image->key_signature));
+  StatefulMemcpy(&st, image->key_signature, FIELD_LEN(key_signature));
 
   /* Read the firmware preamble. */
-  StatefulMemcpy(&st,&image->firmware_version, sizeof(image->firmware_version));
-  StatefulMemcpy(&st, &image->firmware_len, sizeof(image->firmware_len));
-  StatefulMemcpy(&st, image->preamble, sizeof(image->preamble));
+  StatefulMemcpy(&st,&image->firmware_version, FIELD_LEN(firmware_version));
+  StatefulMemcpy(&st, &image->firmware_len, FIELD_LEN(firmware_len));
+  StatefulMemcpy(&st, image->preamble, FIELD_LEN(preamble));
 
   /* Read firmware preamble signature. */
   image->preamble_signature = (uint8_t*) Malloc(signature_len);
@@ -145,22 +133,22 @@
 
 void WriteFirmwareHeader(int fd, FirmwareImage* image) {
   int sign_key_len;
-  write(fd, &image->header_len, sizeof(image->header_len));
-  write(fd, &image->sign_algorithm, sizeof(image->header_len));
-  sign_key_len = (image->header_len - sizeof(image->header_len) -
-                     sizeof(image->sign_algorithm) -
-                     sizeof(image->key_version) -
-                     sizeof(image->header_checksum));
+  write(fd, &image->header_len, FIELD_LEN(header_len));
+  write(fd, &image->sign_algorithm, FIELD_LEN(header_len));
+  sign_key_len = (image->header_len - FIELD_LEN(header_len) -
+                  FIELD_LEN(sign_algorithm) -
+                  FIELD_LEN(key_version) -
+                  FIELD_LEN(header_checksum));
   write(fd, image->sign_key, sign_key_len);
-  write(fd, &image->key_version, sizeof(image->key_version));
-  write(fd, &image->header_checksum, sizeof(image->header_checksum));
+  write(fd, &image->key_version, FIELD_LEN(key_version));
+  write(fd, &image->header_checksum, FIELD_LEN(header_checksum));
 }
 
 void WriteFirmwarePreamble(int fd, FirmwareImage* image) {
   write(fd, &image->firmware_version,
-        sizeof(image->firmware_version));
-  write(fd, &image->firmware_len, sizeof(image->firmware_len));
-  write(fd, image->preamble, sizeof(image->preamble));
+        FIELD_LEN(firmware_version));
+  write(fd, &image->firmware_len, FIELD_LEN(firmware_len));
+  write(fd, image->preamble, FIELD_LEN(preamble));
 }
 
 FirmwareImage* WriteFirmwareImage(const char* input_file,
@@ -175,9 +163,9 @@
     return NULL;
   }
 
-  write(fd, image->magic, sizeof(image->magic));
+  write(fd, image->magic, FIELD_LEN(magic));
   WriteFirmwareHeader(fd, image);
-  write(fd, image->key_signature, sizeof(image->key_signature));
+  write(fd, image->key_signature, FIELD_LEN(key_signature));
   signature_len = siglen_map[image->sign_algorithm] * sizeof(uint32_t);
   WriteFirmwarePreamble(fd, image);
   write(fd, image->preamble_signature, signature_len);
@@ -188,7 +176,7 @@
   return image;
 }
 
-void PrintFirmware(const FirmwareImage* image) {
+void PrintFirmwareImage(const FirmwareImage* image) {
   if (!image)
     return;
 
@@ -395,18 +383,18 @@
   if (!dev_mode) {
     DigestInit(&ctx, ROOT_SIGNATURE_ALGORITHM);
     DigestUpdate(&ctx, (uint8_t*) &image->header_len,
-                 sizeof(image->header_len));
+                 FIELD_LEN(header_len));
     DigestUpdate(&ctx, (uint8_t*) &image->sign_algorithm,
-                 sizeof(image->sign_algorithm));
+                 FIELD_LEN(sign_algorithm));
     DigestUpdate(&ctx, image->sign_key,
                  RSAProcessedKeySize(image->sign_algorithm));
     DigestUpdate(&ctx, (uint8_t*) &image->key_version,
-                 sizeof(image->key_version));
+                 FIELD_LEN(key_version));
     DigestUpdate(&ctx, image->header_checksum,
-                 sizeof(image->header_checksum));
+                 FIELD_LEN(header_checksum));
     header_digest = DigestFinal(&ctx);
     if (!RSA_verify(root_key, image->key_signature,
-                    sizeof(image->key_signature),
+                    FIELD_LEN(key_signature),
                     ROOT_SIGNATURE_ALGORITHM,
                     header_digest)) {
       error_code =  VERIFY_FIRMWARE_ROOT_SIGNATURE_FAILED;
@@ -426,11 +414,11 @@
   /* Verify firmware preamble signature. */
   DigestInit(&ctx, image->sign_algorithm);
   DigestUpdate(&ctx, (uint8_t*) &image->firmware_version,
-               sizeof(image->firmware_version));
+               FIELD_LEN(firmware_version));
   DigestUpdate(&ctx, (uint8_t*) &image->firmware_len,
-               sizeof(image->firmware_len));
+               FIELD_LEN(firmware_len));
   DigestUpdate(&ctx, (uint8_t*) &image->preamble,
-               sizeof(image->preamble));
+               FIELD_LEN(preamble));
   preamble_digest = DigestFinal(&ctx);
   if (!RSA_verify(sign_key, image->preamble_signature,
                   signature_size, image->sign_algorithm,
@@ -457,8 +445,11 @@
   return error_code;
 }
 
+const char* VerifyFirmwareErrorString(int error) {
+  return kVerifyFirmwareErrors[error];
+}
 
-int AddKeySignature(FirmwareImage* image, char* root_key_file) {
+int AddFirmwareKeySignature(FirmwareImage* image, const char* root_key_file) {
   int tmp_hdr_fd;
   char* tmp_hdr_file = ".tmpHdrFile";
   uint8_t* signature;
@@ -478,7 +469,7 @@
   return 1;
 }
 
-int AddFirmwareSignature(FirmwareImage* image, char* signing_key_file,
+int AddFirmwareSignature(FirmwareImage* image, const char* signing_key_file,
                          int algorithm) {
   int tmp_preamble_fd;
   char* tmp_preamble_file = ".tmpPreambleFile";
diff --git a/utils/firmware_utility.c b/utils/firmware_utility.c
deleted file mode 100644
index 1d94e21..0000000
--- a/utils/firmware_utility.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Utility for manipulating verified boot firmware images.
- */
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "firmware_image.h"
-#include "rsa_utility.h"
-#include "sha_utility.h"
-#include "utility.h"
-
-int main(int argc, char* argv[]) {
-  /* TODO(gauravsh): TO BE IMPLEMENTED. */
-  return 0;
-}
diff --git a/utils/firmware_utility.cc b/utils/firmware_utility.cc
new file mode 100644
index 0000000..fa207fb
--- /dev/null
+++ b/utils/firmware_utility.cc
@@ -0,0 +1,305 @@
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Utility for manipulating verified boot firmware images.
+//
+
+#include "firmware_utility.h"
+
+#include <errno.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <iostream>
+
+extern "C" {
+#include "file_keys.h"
+#include "firmware_image.h"
+#include "padding.h"
+#include "rsa_utility.h"
+#include "sha_utility.h"
+#include "utility.h"
+}
+
+extern int errno;
+using std::cerr;
+
+namespace vboot_reference {
+
+FirmwareUtility::FirmwareUtility():
+    image_(NULL),
+    root_key_pub_(NULL),
+    firmware_version_(-1),
+    key_version_(-1),
+    sign_algorithm_(-1),
+    is_generate_(false),
+    is_verify_(false) {
+}
+
+FirmwareUtility::~FirmwareUtility() {
+  RSAPublicKeyFree(root_key_pub_);
+  FirmwareImageFree(image_);
+}
+
+void FirmwareUtility::PrintUsage(void) {
+  cerr <<
+      "Utility to generate/verify a verified boot firmware image\n\n"
+      "Usage: firmware_utility <--generate|--verify> [OPTIONS]\n\n"
+      "For \"--verify\",  required OPTIONS are:\n"
+      "--in <infile>\t\t\tVerified boot firmware image to verify.\n"
+      "--root_key_pub <pubkeyfile>\tPre-processed public root key "
+      "to use for verification.\n\n"
+      "For \"--generate\", required OPTIONS are:\n"
+      "--root_key <privkeyfile>\tPrivate root key file\n"
+      "--sign_key <privkeyfile>\tPrivate signing key file\n"
+      "--sign_key_pub <pubkeyfile>\tPre-processed public signing"
+      " key\n"
+      "--sign_algorithm <algoid>\tSigning algorithm to use\n"
+      "--key_version <version#>\tSigning Key Version#\n"
+      "--firmware_version <version#>\tFirmware Version#\n"
+      "--in <infile>\t\t\tFirmware Image to sign\n"
+      "--out <outfile>\t\t\tOutput file for verified boot firmware image\n\n"
+      "<algoid> (for --sign-algorithm) is one of the following:\n";
+  for (int i = 0; i < kNumAlgorithms; i++) {
+    cerr << i << " for " << algo_strings[i] << "\n";
+  }
+  cerr << "\n\n";
+}
+
+bool FirmwareUtility::ParseCmdLineOptions(int argc, char* argv[]) {
+  int option_index;
+  static struct option long_options[] = {
+    {"root_key", 1, 0, 0},
+    {"root_key_pub", 1, 0, 0},
+    {"sign_key", 1, 0, 0},
+    {"sign_key_pub", 1, 0, 0},
+    {"sign_algorithm", 1, 0, 0},
+    {"key_version", 1, 0, 0},
+    {"firmware_version", 1, 0, 0},
+    {"in", 1, 0, 0},
+    {"out", 1, 0, 0},
+    {"generate", 0, 0, 0},
+    {"verify", 0, 0, 0},
+    {NULL, 0, 0, 0}
+  };
+  while (1) {
+    int i = getopt_long(argc, argv, "", long_options, &option_index);
+    if (-1 == i)  // Done with option processing.
+      break;
+    if ('?' == i)  // Invalid option found.
+      return false;
+
+    if (0 == i) {
+      switch(option_index) {
+        case 0:  // root_key
+          root_key_file_ = optarg;
+          break;
+        case 1:  // root_key_pub
+          root_key_pub_file_ = optarg;
+          break;
+        case 2:  // sign_key
+          sign_key_file_ = optarg;
+          break;
+        case 3:  // sign_key_pub
+          sign_key_pub_file_ = optarg;
+          break;
+        case 4:  // sign_algorithm
+          errno = 0;  // strtol() returns an error via errno
+          sign_algorithm_ = strtol(optarg, (char**) NULL, 10);
+          if (errno)
+            return false;
+          break;
+        case 5:  // key_version
+          errno = 0;
+          key_version_ = strtol(optarg, (char**) NULL, 10);
+          if (errno)
+            return false;
+          break;
+        case 6:  // firmware_version
+          errno = 0;
+          firmware_version_ = strtol(optarg, (char**) NULL, 10);
+          if (errno)
+            return false;
+          break;
+        case 7:  // in
+          in_file_ = optarg;
+          break;
+        case 8:  // out
+          out_file_ = optarg;
+          break;
+        case 9:  // generate
+          is_generate_ = true;
+          break;
+        case 10: // verify
+          is_verify_ = true;
+          break;
+      }
+    }
+  }
+  return CheckOptions();
+}
+
+
+void FirmwareUtility::OutputSignedImage(void) {
+  if (image_) {
+    if (!WriteFirmwareImage(out_file_.c_str(), image_)) {
+        cerr << "Couldn't write verified boot image to file "
+                  << out_file_ <<".\n";
+    }
+  }
+}
+
+bool FirmwareUtility::GenerateSignedImage(void) {
+  uint32_t sign_key_pub_len;
+  uint8_t* header_checksum;
+  DigestContext ctx;
+  image_ = FirmwareImageNew();
+
+  Memcpy(image_->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE);
+
+  // Copy pre-processed public signing key.
+  image_->sign_algorithm = (uint16_t) sign_algorithm_;
+  image_->sign_key = BufferFromFile(sign_key_pub_file_.c_str(),
+                                    &sign_key_pub_len);
+  if (!image_->sign_key)
+    return false;
+  image_->key_version = key_version_;
+
+  // Update header length.
+  image_->header_len = (sizeof(image_->header_len) +
+                        sizeof(image_->sign_algorithm) +
+                        sign_key_pub_len +
+                        sizeof(image_->key_version) +
+                        sizeof(image_->header_checksum));
+
+  // Calculate header checksum.
+  DigestInit(&ctx, SHA512_DIGEST_ALGORITHM);
+  DigestUpdate(&ctx, (uint8_t*) &image_->header_len,
+               sizeof(image_->header_len));
+  DigestUpdate(&ctx, (uint8_t*) &image_->sign_algorithm,
+               sizeof(image_->sign_algorithm));
+  DigestUpdate(&ctx, image_->sign_key,
+               RSAProcessedKeySize(image_->sign_algorithm));
+  DigestUpdate(&ctx, (uint8_t*) &image_->key_version,
+               sizeof(image_->key_version));
+  header_checksum = DigestFinal(&ctx);
+  Memcpy(image_->header_checksum, header_checksum, SHA512_DIGEST_SIZE);
+  Free(header_checksum);
+
+  image_->firmware_version = firmware_version_;
+  image_->firmware_len = 0;
+  // TODO(gauravsh): Populate this with the right bytes once we decide
+  // what goes into the preamble.
+  Memset(image_->preamble, 'P', FIRMWARE_PREAMBLE_SIZE);
+  image_->firmware_data = BufferFromFile(in_file_.c_str(),
+                                         &image_->firmware_len);
+  if (!image_)
+    return false;
+  // Generate and add the signatures.
+  if(!AddFirmwareKeySignature(image_, root_key_file_.c_str())) {
+    cerr << "Couldn't write key signature to verified boot image.\n";
+    return false;
+  }
+
+  if(!AddFirmwareSignature(image_, sign_key_file_.c_str(),
+                           image_->sign_algorithm)) {
+    cerr << "Couldn't write firmware signature to verified boot image.\n";
+    return false;
+  }
+  return true;
+}
+
+bool FirmwareUtility::VerifySignedImage(void) {
+  int error;
+  root_key_pub_ = RSAPublicKeyFromFile(root_key_pub_file_.c_str());
+  image_ = ReadFirmwareImage(in_file_.c_str());
+
+  if (!root_key_pub_) {
+    cerr << "Couldn't read pre-processed public root key.\n";
+    return false;
+  }
+
+  if (!image_) {
+    cerr << "Couldn't read firmware image or malformed image.\n";
+    return false;
+  }
+  if(!(error = VerifyFirmwareImage(root_key_pub_, image_, 0)))  // Trusted Mode.
+    return true;
+  cerr << VerifyFirmwareErrorString(error) << "\n";
+  return false;;
+}
+
+bool FirmwareUtility::CheckOptions(void) {
+  if (is_generate_ == is_verify_) {
+    cerr << "One of --generate or --verify must be specified.\n";
+    return false;
+  }
+  // Common required options.
+  if (in_file_.empty()) {
+    cerr << "No input file specified." << "\n";
+    return false;
+  }
+  // Required options for --verify.
+  if (is_verify_ && root_key_pub_file_.empty()) {
+    cerr << "No pre-processed public root key file specified." << "\n";
+    return false;
+  }
+  // Required options for --generate.
+  if (is_generate_) {
+    if (root_key_file_.empty()) {
+      cerr << "No root key file specified." << "\n";
+      return false;
+    }
+    if (firmware_version_ <= 0 || firmware_version_ > 0xFFFF) {
+      cerr << "Invalid or no firmware version specified." << "\n";
+      return false;
+    }
+    if (sign_key_file_.empty()) {
+      cerr << "No signing key file specified." << "\n";
+      return false;
+    }
+    if (sign_key_pub_file_.empty()) {
+      cerr << "No pre-processed public signing key file specified." << "\n";
+      return false;
+    }
+    if (key_version_ <= 0 || key_version_ > 0xFFFF) {
+      cerr << "Invalid or no key version specified." << "\n";
+      return false;
+    }
+    if (sign_algorithm_ < 0 || sign_algorithm_ >= kNumAlgorithms) {
+      cerr << "Invalid or no signing key algorithm specified." << "\n";
+      return false;
+    }
+    if (out_file_.empty()) {
+      cerr <<"No output file specified." << "\n";
+      return false;
+    }
+  }
+  return true;
+}
+
+
+}  // namespace vboot_reference
+
+int main(int argc, char* argv[]) {
+  vboot_reference::FirmwareUtility fu;
+  if (!fu.ParseCmdLineOptions(argc, argv)) {
+    fu.PrintUsage();
+    return -1;
+  }
+  if (fu.is_generate()) {
+    if (!fu.GenerateSignedImage())
+      return -1;
+    fu.OutputSignedImage();
+  }
+  if (fu.is_verify()) {
+    cerr << "Verification ";
+    if(fu.VerifySignedImage())
+      cerr << "SUCCESS.\n";
+    else
+      cerr << "FAILURE.\n";
+  }
+  return 0;
+}