132a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
27d6898dbaa8d530dd534d4680e274f7059e4a389Randall Spangler * Use of this source code is governed by a BSD-style license that can be
37d6898dbaa8d530dd534d4680e274f7059e4a389Randall Spangler * found in the LICENSE file.
47d6898dbaa8d530dd534d4680e274f7059e4a389Randall Spangler *
57d6898dbaa8d530dd534d4680e274f7059e4a389Randall Spangler * Verified boot key block utility
67d6898dbaa8d530dd534d4680e274f7059e4a389Randall Spangler */
77d6898dbaa8d530dd534d4680e274f7059e4a389Randall Spangler
86a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler#include <getopt.h>
9068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah#include <stdint.h>
106a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler#include <stdio.h>
116a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler#include <stdlib.h>
12abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson#include <string.h>
136a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler
146a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler#include "cryptolib.h"
15884a5f10c1a0c7a37848aef7669e1c735b779cc7Bill Richardson#include "futility.h"
166a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler#include "host_common.h"
17782990277ac7d6730db4c43c2b5632de93396921Bill Richardson#include "util_misc.h"
186a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler#include "vboot_common.h"
196a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler
206a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler/* Command line options */
216a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spanglerenum {
2231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	OPT_MODE_PACK = 1000,
2331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	OPT_MODE_UNPACK,
2431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	OPT_DATAPUBKEY,
2531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	OPT_SIGNPUBKEY,
2631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	OPT_SIGNPRIVATE,
2731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	OPT_SIGNPRIVATE_PEM,
2831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	OPT_PEM_ALGORITHM,
2931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	OPT_EXTERNAL_SIGNER,
3031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	OPT_FLAGS,
316a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler};
326a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler
337351ed7a3cf2759ac043d341d94f16e0ecd139f0Mike Frysingerstatic const struct option long_opts[] = {
3431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	{"pack", 1, 0, OPT_MODE_PACK},
3531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	{"unpack", 1, 0, OPT_MODE_UNPACK},
3631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	{"datapubkey", 1, 0, OPT_DATAPUBKEY},
3731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	{"signpubkey", 1, 0, OPT_SIGNPUBKEY},
3831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	{"signprivate", 1, 0, OPT_SIGNPRIVATE},
3931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	{"signprivate_pem", 1, 0, OPT_SIGNPRIVATE_PEM},
4031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	{"pem_algorithm", 1, 0, OPT_PEM_ALGORITHM},
4131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	{"externalsigner", 1, 0, OPT_EXTERNAL_SIGNER},
4231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	{"flags", 1, 0, OPT_FLAGS},
4331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	{NULL, 0, 0, 0}
446a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler};
456a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler
4631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardsonstatic const char usage[] =
4731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"\n"
48779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"Usage:  " MYNAME " %s <--pack|--unpack> <file> [OPTIONS]\n"
4931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"\n"
5031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"For '--pack <file>', required OPTIONS are:\n"
5131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"  --datapubkey <file>         Data public key in .vbpubk format\n"
5231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"\n"
5331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"Optional OPTIONS are:\n"
5431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"  --signprivate <file>"
5531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"        Signing private key in .vbprivk format.\n"
5631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"OR\n"
5731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"  --signprivate_pem <file>\n"
5831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"  --pem_algorithm <algo>\n"
5931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"        Signing private key in .pem format and algorithm id.\n"
6031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"(If one of the above arguments is not specified, the keyblock will\n"
6131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"not be signed.)\n"
6231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"\n"
6331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"  --flags <number>            Specifies allowed use conditions.\n"
6431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"  --externalsigner \"cmd\""
6531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"        Use an external program cmd to calculate the signatures.\n"
6631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"\n"
6731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"For '--unpack <file>', optional OPTIONS are:\n"
6831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"  --signpubkey <file>"
6931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"        Signing public key in .vbpubk format. This is required to\n"
7031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"                                verify a signed keyblock.\n"
7131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	"  --datapubkey <file>"
72779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"        Write the data public key to this file.\n\n";
736a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler
74779796f57e1e0236ea502248ede2cbea986fca21Bill Richardsonstatic void print_help(const char *progname)
7531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson{
76779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	printf(usage, progname);
776a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler}
786a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler
796a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler/* Pack a .keyblock */
8031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardsonstatic int Pack(const char *outfile, const char *datapubkey,
8131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		const char *signprivate,
8231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		const char *signprivate_pem, uint64_t pem_algorithm,
8331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		uint64_t flags, const char *external_signer)
8431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson{
8531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	VbPublicKey *data_key;
8631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	VbPrivateKey *signing_key = NULL;
8731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	VbKeyBlockHeader *block;
8831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
8931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (!outfile) {
9031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		fprintf(stderr,
9131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			"vbutil_keyblock: Must specify output filename.\n");
9231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		return 1;
9331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	}
9431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (!datapubkey) {
9531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		fprintf(stderr,
9631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			"vbutil_keyblock: Must specify data public key.\n");
9731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		return 1;
9831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	}
9931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
10031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	data_key = PublicKeyRead(datapubkey);
10131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (!data_key) {
10231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		fprintf(stderr, "vbutil_keyblock: Error reading data key.\n");
10331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		return 1;
10431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	}
10531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
10631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (signprivate_pem) {
10731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		if (pem_algorithm >= kNumAlgorithms) {
10831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			fprintf(stderr,
10931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson				"vbutil_keyblock: Invalid --pem_algorithm %"
11031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson				PRIu64 "\n", pem_algorithm);
11131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			return 1;
11231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		}
11331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		if (external_signer) {
11431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			/* External signing uses the PEM file directly. */
11531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			block = KeyBlockCreate_external(data_key,
11631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson							signprivate_pem,
11731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson							pem_algorithm, flags,
11831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson							external_signer);
11931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		} else {
12031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			signing_key =
12131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			    PrivateKeyReadPem(signprivate_pem, pem_algorithm);
12231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			if (!signing_key) {
12331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson				fprintf(stderr, "vbutil_keyblock:"
12431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson					" Error reading signing key.\n");
12531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson				return 1;
12631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			}
12731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			block = KeyBlockCreate(data_key, signing_key, flags);
12831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		}
12931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	} else {
13031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		if (signprivate) {
13131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			signing_key = PrivateKeyRead(signprivate);
13231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			if (!signing_key) {
13331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson				fprintf(stderr, "vbutil_keyblock:"
13431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson					" Error reading signing key.\n");
13531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson				return 1;
13631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			}
13731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		}
13831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		block = KeyBlockCreate(data_key, signing_key, flags);
13931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	}
14031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
14131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	free(data_key);
14231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (signing_key)
14331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		free(signing_key);
14431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
14531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (0 != KeyBlockWrite(outfile, block)) {
14631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		fprintf(stderr, "vbutil_keyblock: Error writing key block.\n");
14731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		return 1;
14831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	}
14931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	free(block);
15031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	return 0;
1516a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler}
1526a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler
15331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardsonstatic int Unpack(const char *infile, const char *datapubkey,
15431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		  const char *signpubkey)
15531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson{
15631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	VbPublicKey *data_key;
15731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	VbPublicKey *sign_key = NULL;
15831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	VbKeyBlockHeader *block;
15931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
16031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (!infile) {
16131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		fprintf(stderr, "vbutil_keyblock: Must specify filename\n");
16231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		return 1;
16331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	}
16431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
16531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	block = KeyBlockRead(infile);
16631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (!block) {
16731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		fprintf(stderr, "vbutil_keyblock: Error reading key block.\n");
16831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		return 1;
16931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	}
17031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
17131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	/* If the block is signed, then verify it with the signing public key,
17231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	 * since KeyBlockRead() only verified the hash. */
17331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (block->key_block_signature.sig_size && signpubkey) {
17431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		sign_key = PublicKeyRead(signpubkey);
17531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		if (!sign_key) {
17631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			fprintf(stderr,
17731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson				"vbutil_keyblock: Error reading signpubkey.\n");
17831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			return 1;
17931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		}
18031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		if (0 !=
18131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		    KeyBlockVerify(block, block->key_block_size, sign_key, 0)) {
18231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			fprintf(stderr, "vbutil_keyblock:"
18331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson				" Error verifying key block.\n");
18431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			return 1;
18531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		}
18631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		free(sign_key);
18731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	}
18831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
18931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	printf("Key block file:       %s\n", infile);
19031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	printf("Signature             %s\n", sign_key ? "valid" : "ignored");
19131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	printf("Flags:                %" PRIu64 " ", block->key_block_flags);
19231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0)
19331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		printf(" !DEV");
19431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1)
19531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		printf(" DEV");
19631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0)
19731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		printf(" !REC");
19831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1)
19931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		printf(" REC");
20031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	printf("\n");
20131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
20231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	data_key = &block->data_key;
20331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	printf("Data key algorithm:   %" PRIu64 " %s\n", data_key->algorithm,
20431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	       (data_key->algorithm < kNumAlgorithms ?
20531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		algo_strings[data_key->algorithm] : "(invalid)"));
20631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	printf("Data key version:     %" PRIu64 "\n", data_key->key_version);
20731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	printf("Data key sha1sum:     ");
20831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	PrintPubKeySha1Sum(data_key);
20931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	printf("\n");
21031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
21131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (datapubkey) {
21231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		if (0 != PublicKeyWrite(datapubkey, data_key)) {
21331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			fprintf(stderr, "vbutil_keyblock:"
21431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson				" unable to write public key\n");
21531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			return 1;
21631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		}
21731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	}
21831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
21931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	free(block);
22031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	return 0;
2216a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler}
2226a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler
22331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardsonstatic int do_vbutil_keyblock(int argc, char *argv[])
22431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson{
22531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
22631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	char *filename = NULL;
22731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	char *datapubkey = NULL;
22831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	char *signpubkey = NULL;
22931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	char *signprivate = NULL;
23031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	char *signprivate_pem = NULL;
23131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	char *external_signer = NULL;
23231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	uint64_t flags = 0;
23331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	uint64_t pem_algorithm = 0;
23431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	int is_pem_algorithm = 0;
23531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	int mode = 0;
23631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	int parse_error = 0;
23731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	char *e;
23831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	int i;
23931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
24031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
24131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		switch (i) {
24231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		case '?':
24331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			/* Unhandled option */
24431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			printf("Unknown option\n");
24531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			parse_error = 1;
24631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			break;
24731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
24831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		case OPT_MODE_PACK:
24931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		case OPT_MODE_UNPACK:
25031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			mode = i;
25131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			filename = optarg;
25231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			break;
25331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
25431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		case OPT_DATAPUBKEY:
25531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			datapubkey = optarg;
25631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			break;
25731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
25831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		case OPT_SIGNPUBKEY:
25931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			signpubkey = optarg;
26031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			break;
26131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
26231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		case OPT_SIGNPRIVATE:
26331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			signprivate = optarg;
26431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			break;
26531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
26631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		case OPT_SIGNPRIVATE_PEM:
26731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			signprivate_pem = optarg;
26831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			break;
26931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
27031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		case OPT_PEM_ALGORITHM:
27131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			pem_algorithm = strtoul(optarg, &e, 0);
27231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			if (!*optarg || (e && *e)) {
27331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson				fprintf(stderr, "Invalid --pem_algorithm\n");
27431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson				parse_error = 1;
27531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			} else {
27631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson				is_pem_algorithm = 1;
27731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			}
27831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			break;
27931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
28031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		case OPT_EXTERNAL_SIGNER:
28131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			external_signer = optarg;
28231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			break;
28331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
28431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		case OPT_FLAGS:
28531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			flags = strtoul(optarg, &e, 0);
28631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			if (!*optarg || (e && *e)) {
28731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson				fprintf(stderr, "Invalid --flags\n");
28831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson				parse_error = 1;
28931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			}
29031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			break;
29131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		}
29231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	}
29331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
29431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	/* Check if the right combination of options was provided. */
29531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (signprivate && signprivate_pem) {
29631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		fprintf(stderr,
29731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			"Only one of --signprivate or --signprivate_pem must"
29831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			" be specified\n");
29931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		parse_error = 1;
30031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	}
30131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
30231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (signprivate_pem && !is_pem_algorithm) {
30331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		fprintf(stderr, "--pem_algorithm must be used with"
30431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			" --signprivate_pem\n");
30531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		parse_error = 1;
30631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	}
30731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
30831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	if (external_signer && !signprivate_pem) {
30931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		fprintf(stderr,
31031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			"--externalsigner must be used with --signprivate_pem"
31131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			"\n");
31231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		parse_error = 1;
31331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	}
31431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
315779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	if (parse_error) {
316779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		print_help(argv[0]);
317779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		return 1;
318779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	}
31931d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson
32031d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	switch (mode) {
32131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	case OPT_MODE_PACK:
32231d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		return Pack(filename, datapubkey, signprivate,
32331d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			    signprivate_pem, pem_algorithm,
32431d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson			    flags, external_signer);
32531d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	case OPT_MODE_UNPACK:
32631d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		return Unpack(filename, datapubkey, signpubkey);
32731d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	default:
32831d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson		printf("Must specify a mode.\n");
329779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		print_help(argv[0]);
330779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		return 1;
33131d95c2386df8d3d5ec619a077960645d052fa38Bill Richardson	}
3326a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler}
333884a5f10c1a0c7a37848aef7669e1c735b779cc7Bill Richardson
334884a5f10c1a0c7a37848aef7669e1c735b779cc7Bill RichardsonDECLARE_FUTIL_COMMAND(vbutil_keyblock, do_vbutil_keyblock,
3351eae873b6194db25781233d7a4aaee6a34160eecBill Richardson		      VBOOT_VERSION_1_0,
336779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		      "Creates, signs, and verifies a keyblock",
337779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		      print_help);
338