summaryrefslogtreecommitdiff
path: root/utility/vbutil_ec.c
diff options
context:
space:
mode:
Diffstat (limited to 'utility/vbutil_ec.c')
-rw-r--r--utility/vbutil_ec.c621
1 files changed, 411 insertions, 210 deletions
diff --git a/utility/vbutil_ec.c b/utility/vbutil_ec.c
index 86747c0a..c1b280f6 100644
--- a/utility/vbutil_ec.c
+++ b/utility/vbutil_ec.c
@@ -5,22 +5,28 @@
* Verified boot utility for EC firmware
*/
+#include <errno.h>
+#include <fcntl.h>
#include <getopt.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <unistd.h>
#include "cryptolib.h"
+#include "fmap.h"
#include "host_common.h"
#include "vboot_common.h"
/* Command line options */
enum {
- OPT_MODE_VBLOCK = 1000,
+ OPT_MODE_SIGN = 1000,
OPT_MODE_VERIFY,
OPT_KEYBLOCK,
OPT_SIGNPUBKEY,
@@ -33,13 +39,12 @@ enum {
};
static struct option long_opts[] = {
- {"vblock", 1, 0, OPT_MODE_VBLOCK },
+ {"sign", 1, 0, OPT_MODE_SIGN },
{"verify", 1, 0, OPT_MODE_VERIFY },
{"keyblock", 1, 0, OPT_KEYBLOCK },
{"signpubkey", 1, 0, OPT_SIGNPUBKEY },
{"signprivate", 1, 0, OPT_SIGNPRIVATE },
{"version", 1, 0, OPT_VERSION },
- {"fv", 1, 0, OPT_FV },
{"flags", 1, 0, OPT_FLAGS },
{"name", 1, 0, OPT_NAME },
{NULL, 0, 0, 0}
@@ -51,255 +56,435 @@ static int PrintHelp(void) {
puts("vbutil_ec - Verified boot signing utility for EC firmware\n"
"\n"
- "Usage: vbutil_ec <--vblock|--verify> <file> [OPTIONS]\n"
+ "This will sign, re-sign, or test a complete EC firmware image.\n"
+ "The EC image is initially completely unsigned. To make it bootable\n"
+ "the pubic root key must be installed in the RO section, and each RW\n"
+ "section must be signed with the appropriate private keys.\n"
+ "\n"
+ "To sign an image: vbutil_ec --sign <file> [OPTIONS]\n"
+ "\n"
+ "For signing, these options are required:\n"
"\n"
- "For '--vblock <file>', required OPTIONS are:\n"
" --keyblock <file> Key block in .keyblock format\n"
" --signprivate <file> Signing private key in .vbprivk format\n"
" --version <number> Firmware version\n"
- " --fv <file> Firmware volume to sign\n"
- "optional OPTIONS are:\n"
+ "\n"
+ "If the RO public key has not been installed, you will also need\n"
+ "\n"
+ " --signpubkey <file> Signing public key in .vbpubk format\n"
+ "\n"
+ "Optional args are:\n"
+ "\n"
" --flags <number> Preamble flags (defaults to 0)\n"
" --name <string> Human-readable description\n"
"\n"
- "For '--verify <file>', required OPTIONS are:\n"
- " --fv <file> Firmware volume to verify\n"
- "optional OPTIONS are:\n"
- " --signpubkey <file> Signing public key in .vbpubk format\n"
+ "\n"
+ "To verify an image: vbutil_ec --verify <file>\n"
"\n");
return 1;
}
-/* Create an EC firmware .vblock */
-static int Vblock(const char* outfile, const char* keyblock_file,
- const char* signprivate, uint64_t version,
- const char* fv_file, uint32_t preamble_flags,
- const char* name) {
- VbPrivateKey* signing_key;
- VbSignature* body_digest;
- VbECPreambleHeader* preamble;
- VbKeyBlockHeader* key_block;
- uint64_t key_block_size;
- uint8_t* fv_data;
- uint64_t fv_size;
- FILE* f;
- uint64_t i;
+static int FindInFmap(FmapHeader *fh, const char *name,
+ uint8_t *base, uint64_t base_size,
+ uint8_t **data, uint64_t *size) {
+ const FmapAreaHeader *ah;
+ int i;
+
+ ah = (FmapAreaHeader *)(fh + 1);
+ for (i = 0; i < fh->fmap_nareas; i++)
+ if (!strncmp(ah[i].area_name, name, FMAP_NAMELEN)) {
+ if (ah[i].area_size + ah[i].area_offset > base_size) {
+ printf("FMAP region %s extends off image file\n", name);
+ return 0;
+ }
+ if (data)
+ *data = base + ah[i].area_offset;
+ if (size)
+ *size = ah[i].area_size;
+ return 1;
+ }
+
+ return 0;
+}
+
+static int GoodKey(VbPublicKey *key, uint64_t region_size)
+{
+ uint64_t key_size;
+
+ if (0 != VerifyPublicKeyInside(key, region_size, key))
+ return 0;
- if (!outfile)
- VbExError("Must specify output filename\n");
+ if (key->algorithm >= kNumAlgorithms)
+ return 0;
- if (!keyblock_file || !signprivate)
- VbExError("Must specify all keys\n");
+ /* Currently, TPM only supports 16-bit version */
+ if (key->key_version > 0xFFFF)
+ return 0;
- if (!fv_file)
- VbExError("Must specify firmware volume\n");
+ if (!RSAProcessedKeySize(key->algorithm, &key_size) ||
+ key_size != key->key_size)
+ return 0;
- /* Read the key block and keys */
- key_block = (VbKeyBlockHeader*)ReadFile(keyblock_file, &key_block_size);
- if (!key_block)
- VbExError("Error reading key block.\n");
+ return 1;
+}
- signing_key = PrivateKeyRead(signprivate);
- if (!signing_key)
- VbExError("Error reading signing key.\n");
- /* Read and sign the firmware volume */
- fv_data = ReadFile(fv_file, &fv_size);
- if (!fv_data)
- return 1;
- if (!fv_size)
- VbExError("Empty firmware volume file\n");
+/* We build the image file with a non-FF byte at the end of each RW firmware,
+ * just so we can do this. */
+static uint64_t FindImageEnd(uint8_t *data, uint64_t size)
+{
+ for (size-- ; size && data[size] == 0xff; size--)
+ ;
+ return size;
+}
+
+static void SignImage(const char *filename,
+ VbKeyBlockHeader *key_block, uint64_t key_block_size,
+ VbPrivateKey *privkey, uint64_t version,
+ VbPublicKey *pubkey, uint32_t preamble_flags,
+ const char *name) {
+ struct stat sb;
+ int fd;
+ void *image;
+ uint64_t image_size;
+ FmapHeader* fmap;
+ VbECPreambleHeader *preamble;
+ uint8_t *fv_data = 0;
+ uint8_t *vblock_data = 0;
+ uint64_t fv_size, vblock_size;
+ VbSignature* body_digest;
if (name && strlen(name)+1 > sizeof(preamble->name))
VbExError("Name string is too long\n");
- body_digest = CalculateHash(fv_data, fv_size, signing_key);
+ if (0 != stat(filename, &sb))
+ VbExError("Can't stat %s: %s\n", filename, strerror(errno));
+
+ fd = open(filename, O_RDWR);
+ if (fd < 0)
+ VbExError("Can't open %s: %s\n", filename, strerror(errno));
+
+ image = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (image == (void *)-1)
+ VbExError("Can't mmap %s: %s\n", filename, strerror(errno));
+ close(fd); /* done with this now */
+
+ fmap = (FmapHeader *)FmapFind(image, sb.st_size);
+ if (!fmap)
+ VbExError("File %s doesn't have an FMAP - can't continue.\n");
+
+ if (fmap->fmap_size > sb.st_size)
+ VbExError("FMAP is bigger than file size (%ld vs %ld)\n",
+ fmap->fmap_size, sb.st_size);
+
+ image_size = sb.st_size;
+
+ /* Install pubkey if provided */
+ if (pubkey) {
+ if (!FindInFmap(fmap, "ROOT_KEY", image, image_size,
+ &vblock_data, &vblock_size))
+ VbExError("Can't find ROOT_KEY in %s\n", filename);
+
+ if (pubkey->key_offset + pubkey->key_size > vblock_size)
+ VbExError("ROOT_KEY is too small for pubkey (%d bytes, needs %d)\n",
+ vblock_size, pubkey->key_offset + pubkey->key_size);
+
+ memcpy(vblock_data, pubkey, pubkey->key_offset + pubkey->key_size);
+ }
+
+
+ /* Sign FW A */
+ if (!FindInFmap(fmap, "FW_MAIN_A", image, image_size, &fv_data, &fv_size))
+ VbExError("Can't find FW_MAIN_A in %s\n", filename);
+
+ if (!FindInFmap(fmap, "VBLOCK_A", image, image_size,
+ &vblock_data, &vblock_size))
+ VbExError("Can't find VBLOCK_A in %s\n", filename);
+
+ fv_size = FindImageEnd(fv_data, fv_size);
+
+ body_digest = CalculateHash(fv_data, fv_size, privkey);
if (!body_digest)
VbExError("Error calculating body digest\n");
- free(fv_data);
- /* Create preamble */
- preamble = CreateECPreamble(version, body_digest, signing_key,
+ preamble = CreateECPreamble(version, body_digest, privkey,
preamble_flags, name);
if (!preamble)
VbExError("Error creating preamble.\n");
- /* Write the output file */
- f = fopen(outfile, "wb");
- if (!f)
- VbExError("Can't open output file %s\n", outfile);
-
- i = ((1 != fwrite(key_block, key_block_size, 1, f)) ||
- (1 != fwrite(preamble, preamble->preamble_size, 1, f)));
- fclose(f);
- if (i) {
- unlink(outfile);
- VbExError("Can't write output file %s\n", outfile);
+ if (key_block_size + preamble->preamble_size > vblock_size)
+ VbExError("VBLOCK_A is too small for digest (%d bytes, needs %d)\n",
+ vblock_size, key_block_size + preamble->preamble_size);
+
+ memcpy(vblock_data, key_block, key_block_size);
+ memcpy(vblock_data + key_block_size, preamble, preamble->preamble_size);
+
+ free(body_digest);
+ free(preamble);
+
+
+ /* Sign FW B - skip if there isn't one */
+ if (!FindInFmap(fmap, "FW_MAIN_B", image, image_size, &fv_data, &fv_size) ||
+ !FindInFmap(fmap, "VBLOCK_B", image, image_size,
+ &vblock_data, &vblock_size)) {
+ printf("Image does not contain FW B - ignoring that part\n");
+ } else {
+ fv_size = FindImageEnd(fv_data, fv_size);
+
+ body_digest = CalculateHash(fv_data, fv_size, privkey);
+ if (!body_digest)
+ VbExError("Error calculating body digest\n");
+
+ preamble = CreateECPreamble(version, body_digest, privkey,
+ preamble_flags, name);
+ if (!preamble)
+ VbExError("Error creating preamble.\n");
+
+ if (key_block_size + preamble->preamble_size > vblock_size)
+ VbExError("VBLOCK_B is too small for digest (%d bytes, needs %d)\n",
+ vblock_size, key_block_size + preamble->preamble_size);
+
+ memcpy(vblock_data, key_block, key_block_size);
+ memcpy(vblock_data + key_block_size, preamble, preamble->preamble_size);
+
+ free(body_digest);
+ free(preamble);
}
- /* Success */
- return 0;
+ /* Unmap to write changes to disk. */
+ if (0 != munmap(image, sb.st_size))
+ VbExError("Can't munmap %s: %s\n", filename, strerror(errno));
+
+ printf("Image signing completed\n");
+
}
-static int Verify(const char* infile,
- const char* signpubkey,
- const char* fv_file) {
- VbKeyBlockHeader* key_block;
- VbECPreambleHeader* preamble;
- VbPublicKey* data_key;
- VbPublicKey* sign_key = 0;
- RSAPublicKey* rsa;
- uint8_t* blob;
- uint64_t blob_size;
- uint8_t* fv_data;
+static int Verify(const char *filename) {
+ struct stat sb;
+ int fd;
+ void *image;
+ uint64_t image_size;
+ FmapHeader* fmap;
+ VbECPreambleHeader *preamble;
+ VbPublicKey *pubkey;
+ uint64_t pubkey_size;
+ VbKeyBlockHeader *key_block;
+ uint64_t key_block_size;
+ uint8_t *fv_data = 0;
uint64_t fv_size;
- uint64_t now = 0;
+ VbPublicKey *data_key;
+ RSAPublicKey* rsa;
+ int errorcnt = 0;
+ char buf[80];
+ int i;
- if (!infile || !fv_file) {
- VbExError("Must specify filename and fv\n");
- return 1;
- }
+ if (0 != stat(filename, &sb))
+ VbExError("Can't stat %s: %s\n", filename, strerror(errno));
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ VbExError("Can't open %s: %s\n", filename, strerror(errno));
+
+ image = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (image == (void *)-1)
+ VbExError("Can't mmap %s: %s\n", filename, strerror(errno));
+ close(fd); /* done with this now */
+
+ fmap = (FmapHeader *)FmapFind(image, sb.st_size);
+ if (!fmap)
+ VbExError("File %s doesn't have an FMAP - can't continue.\n");
+
+ if (fmap->fmap_size > sb.st_size)
+ VbExError("FMAP is bigger than file size (%ld vs %ld)\n",
+ fmap->fmap_size, sb.st_size);
+
+ image_size = sb.st_size;
- /* Read public signing key */
- if (signpubkey) {
- sign_key = PublicKeyRead(signpubkey);
- if (!sign_key)
- VbExError("Error reading signpubkey.\n");
+ /* Read pubkey */
+ if (!FindInFmap(fmap, "ROOT_KEY", image, image_size,
+ (uint8_t **)&pubkey, &pubkey_size)) {
+ printf("Can't find ROOT_KEY in %s\n", filename);
+ errorcnt++;
+ } else if (!GoodKey(pubkey, pubkey_size)) {
+ printf("ROOT_KEY is invalid\n");
+ errorcnt++;
} else {
- printf("WARNING: No public key given - signature is not checked\n");
+ printf("ROOT_KEY\n");
+ printf(" Algorithm: %" PRIu64 " %s\n", pubkey->algorithm,
+ (pubkey->algorithm < kNumAlgorithms ?
+ algo_strings[pubkey->algorithm] : "(invalid)"));
+ printf(" Key Version: %" PRIu64 "\n", pubkey->key_version);
+ printf(" Key sha1sum: ");
+ PrintPubKeySha1Sum(pubkey);
+ printf("\n");
}
- /* Read blob */
- blob = ReadFile(infile, &blob_size);
- if (!blob)
- VbExError("Error reading input file\n");
-
- /* Read firmware volume */
- fv_data = ReadFile(fv_file, &fv_size);
- if (!fv_data)
- VbExError("Error reading firmware volume\n");
-
- /* Verify key block */
- key_block = (VbKeyBlockHeader*)blob;
- if (0 != KeyBlockVerify(key_block, blob_size, sign_key, !signpubkey))
- VbExError("Error verifying key block.\n");
-
- if (sign_key)
- free(sign_key);
- now += key_block->key_block_size;
-
- printf("Key block:\n");
- data_key = &key_block->data_key;
- printf(" Size: %" PRIu64 "\n", key_block->key_block_size);
- printf(" Flags: %" PRIu64 " (ignored)\n",
- key_block->key_block_flags);
- printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
- (data_key->algorithm < kNumAlgorithms ?
- algo_strings[data_key->algorithm] : "(invalid)"));
- printf(" Data key version: %" PRIu64 "\n", data_key->key_version);
- printf(" Data key sha1sum: ");
- PrintPubKeySha1Sum(data_key);
- printf("\n");
-
- rsa = PublicKeyToRSA(&key_block->data_key);
- if (!rsa)
- VbExError("Error parsing data key.\n");
-
- /* Verify preamble */
- preamble = (VbECPreambleHeader*)(blob + now);
- if (0 != VerifyECPreamble(preamble, blob_size - now, rsa))
- VbExError("Error verifying preamble.\n");
-
- now += preamble->preamble_size;
-
- printf("Preamble:\n");
- printf(" Size: %" PRIu64 "\n", preamble->preamble_size);
- printf(" Header version: %" PRIu32 ".%" PRIu32"\n",
- preamble->header_version_major, preamble->header_version_minor);
- printf(" Firmware version: %" PRIu64 "\n", preamble->firmware_version);
- printf(" Firmware body size: %" PRIu64 "\n",
- preamble->body_digest.data_size);
- printf(" Preamble flags: %" PRIu32 "\n", preamble->flags);
- printf(" Preamble name: %s\n", preamble->name);
-
- /* TODO: verify body size same as signature size */
-
- /* Verify body */
- if (preamble->flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
- printf("Preamble requests USE_RO_NORMAL; skipping body verification.\n");
- } else {
- if (0 != EqualData(fv_data, fv_size, &preamble->body_digest, rsa))
- VbExError("Error verifying firmware body.\n");
- printf("Body verification succeeded.\n");
+ for (i = 'A'; i <= 'B'; i++) {
+
+ fv_data = 0;
+ key_block = 0;
+ preamble = 0;
+
+ printf("FW %c\n", i);
+ sprintf(buf, "FW_MAIN_%c", i);
+ if (!FindInFmap(fmap, buf, image, image_size, &fv_data, &fv_size)) {
+ printf("Can't find %s in %s\n", buf, filename);
+ errorcnt++;
+ continue;
+ }
+
+ sprintf(buf, "VBLOCK_%c", i);
+ if (!FindInFmap(fmap, buf, image, image_size,
+ (uint8_t **)&key_block, &key_block_size)) {
+ printf("Can't find %s in %s\n", buf, filename);
+ errorcnt++;
+ continue;
+ }
+
+ if (0 != KeyBlockVerify(key_block, key_block_size, pubkey, !pubkey)) {
+ printf("Error verifying key block for %s.\n", buf);
+ errorcnt++;
+ continue;
+ }
+ printf(" Key block:\n");
+ data_key = &key_block->data_key;
+ printf(" Size: %" PRIu64 "\n",
+ key_block->key_block_size);
+ printf(" Flags: %" PRIu64 " (ignored)\n",
+ key_block->key_block_flags);
+ printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
+ (data_key->algorithm < kNumAlgorithms ?
+ algo_strings[data_key->algorithm] : "(invalid)"));
+ printf(" Data key version: %" PRIu64 "\n", data_key->key_version);
+ printf(" Data key sha1sum: ");
+ PrintPubKeySha1Sum(data_key);
+ printf("\n");
+
+ preamble = (VbECPreambleHeader*)
+ ((uint8_t *)key_block + key_block->key_block_size);
+
+ rsa = PublicKeyToRSA(&key_block->data_key);
+ if (!rsa) {
+ printf("Error parsing data key.\n");
+ errorcnt++;
+ }
+ /* Verify preamble */
+ if (0 != VerifyECPreamble(preamble,
+ key_block_size - key_block->key_block_size,
+ rsa)) {
+ printf("Error verifying preamble.\n");
+ errorcnt++;
+ free(rsa);
+ continue;
+ }
+ printf(" Preamble:\n");
+ printf(" Size: %" PRIu64 "\n",
+ preamble->preamble_size);
+ printf(" Header version: %" PRIu32 ".%" PRIu32"\n",
+ preamble->header_version_major,
+ preamble->header_version_minor);
+ printf(" Firmware version: %" PRIu64 "\n",
+ preamble->firmware_version);
+ printf(" Firmware body size: %" PRIu64 "\n",
+ preamble->body_digest.data_size);
+ printf(" Preamble flags: %" PRIu32 "\n", preamble->flags);
+ printf(" Preamble name: %s\n", preamble->name);
+
+ /* TODO: verify body size same as signature size */
+
+ /* Verify body */
+ if (preamble->flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
+ printf("Preamble requests USE_RO_NORMAL; skipping verification.\n");
+ } else {
+ if (0 != EqualData(fv_data, fv_size,
+ &preamble->body_digest, rsa)) {
+ printf("Error verifying firmware body.\n");
+ errorcnt++;
+ }
+ }
+ free(rsa);
}
- return 0;
-}
+ /* Done */
+ if (0 != munmap(image, sb.st_size))
+ VbExError("Can't munmap %s: %s\n", filename, strerror(errno));
+ printf("Done\n");
+ return errorcnt;
+}
int main(int argc, char* argv[]) {
char* filename = NULL;
- char* key_block_file = NULL;
- char* signpubkey = NULL;
- char* signprivate = NULL;
uint64_t version = 0;
int got_version = 0;
- char* fv_file = NULL;
uint32_t preamble_flags = 0;
char *name = NULL;
int mode = 0;
- int parse_error = 0;
+ VbKeyBlockHeader* key_block = 0;
+ VbPrivateKey* privkey = 0;
+ VbPublicKey* pubkey = 0;
+ uint64_t key_block_size;
+ int errorcnt = 0;
char* e;
int i;
while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
switch (i) {
- case '?':
- /* Unhandled option */
- printf("Unknown option\n");
- parse_error = 1;
- break;
-
- case OPT_MODE_VBLOCK:
- case OPT_MODE_VERIFY:
- mode = i;
- filename = optarg;
- break;
-
- case OPT_KEYBLOCK:
- key_block_file = optarg;
- break;
-
- case OPT_SIGNPUBKEY:
- signpubkey = optarg;
- break;
-
- case OPT_SIGNPRIVATE:
- signprivate = optarg;
- break;
-
- case OPT_FV:
- fv_file = optarg;
- break;
-
- case OPT_VERSION:
- version = strtoul(optarg, &e, 0);
- if (!*optarg || (e && *e)) {
- printf("Invalid --version\n");
- parse_error = 1;
- }
- got_version = 1;
- break;
-
- case OPT_FLAGS:
- preamble_flags = strtoul(optarg, &e, 0);
- if (!*optarg || (e && *e)) {
- printf("Invalid --flags\n");
- parse_error = 1;
- }
- break;
+ case '?':
+ /* Unhandled option */
+ printf("Unknown option\n");
+ errorcnt++;
+ break;
+
+ case OPT_MODE_SIGN:
+ case OPT_MODE_VERIFY:
+ mode = i;
+ filename = optarg;
+ break;
+
+ case OPT_KEYBLOCK:
+ /* Read the key block and keys */
+ key_block = (VbKeyBlockHeader*)ReadFile(optarg, &key_block_size);
+ if (!key_block) {
+ printf("Error reading key block from %s\n", optarg);
+ errorcnt++;
+ }
+ break;
+
+ case OPT_SIGNPUBKEY:
+ pubkey = PublicKeyRead(optarg);
+ if (!pubkey) {
+ printf("Error reading public key from %s\n", optarg);
+ errorcnt++;
+ }
+ break;
+
+ case OPT_SIGNPRIVATE:
+ privkey = PrivateKeyRead(optarg);
+ if (!privkey) {
+ printf("Error reading private key from %s\n", optarg);
+ errorcnt++;
+ }
+ break;
+
+ case OPT_VERSION:
+ version = strtoul(optarg, &e, 0);
+ if (!*optarg || (e && *e)) {
+ printf("Invalid --version argument: \"%s\"\n", optarg);
+ errorcnt++;
+ }
+ got_version = 1;
+ break;
+
+ case OPT_FLAGS:
+ preamble_flags = strtoul(optarg, &e, 0);
+ if (!*optarg || (e && *e)) {
+ printf("Invalid --flags argument: \"%s\"\n", optarg);
+ errorcnt++;
+ }
+ break;
case OPT_NAME:
name = optarg;
@@ -307,21 +492,37 @@ int main(int argc, char* argv[]) {
}
}
- if (parse_error)
- return PrintHelp();
-
switch(mode) {
- case OPT_MODE_VBLOCK:
- if (!got_version) {
- printf("Must specify a version\n");
- return PrintHelp();
- }
- return Vblock(filename, key_block_file, signprivate, version,
- fv_file, preamble_flags, name);
- case OPT_MODE_VERIFY:
- return Verify(filename, signpubkey, fv_file);
- default:
- printf("Must specify a mode.\n");
+
+ case OPT_MODE_SIGN:
+ /* Check required args */
+ if (!key_block) {
+ printf("The ----keyblock arg is required when signing\n");
+ errorcnt++;
+ }
+ if (!privkey) {
+ printf("The --signprivate arg is required when signing\n");
+ errorcnt++;
+ }
+ if (!got_version) {
+ printf("The --version arg is required when signing\n");
+ errorcnt++;
+ }
+
+ if (errorcnt)
return PrintHelp();
+
+ /* Sign or die */
+ SignImage(filename, key_block, key_block_size,
+ privkey, version, pubkey, preamble_flags, name);
+
+ /* fall through and verify what we've just done */
+
+ case OPT_MODE_VERIFY:
+ return Verify(filename);
+
+ default:
+ printf("\nMust specify a mode, either --sign or --verify.\n\n");
+ return PrintHelp();
}
}