diff options
Diffstat (limited to 'futility/cmd_vbutil_keyblock.c')
-rw-r--r-- | futility/cmd_vbutil_keyblock.c | 592 |
1 files changed, 302 insertions, 290 deletions
diff --git a/futility/cmd_vbutil_keyblock.c b/futility/cmd_vbutil_keyblock.c index 687537d8..58d89c1a 100644 --- a/futility/cmd_vbutil_keyblock.c +++ b/futility/cmd_vbutil_keyblock.c @@ -17,312 +17,324 @@ #include "util_misc.h" #include "vboot_common.h" - /* Command line options */ enum { - OPT_MODE_PACK = 1000, - OPT_MODE_UNPACK, - OPT_DATAPUBKEY, - OPT_SIGNPUBKEY, - OPT_SIGNPRIVATE, - OPT_SIGNPRIVATE_PEM, - OPT_PEM_ALGORITHM, - OPT_EXTERNAL_SIGNER, - OPT_FLAGS, + OPT_MODE_PACK = 1000, + OPT_MODE_UNPACK, + OPT_DATAPUBKEY, + OPT_SIGNPUBKEY, + OPT_SIGNPRIVATE, + OPT_SIGNPRIVATE_PEM, + OPT_PEM_ALGORITHM, + OPT_EXTERNAL_SIGNER, + OPT_FLAGS, }; static const struct option long_opts[] = { - {"pack", 1, 0, OPT_MODE_PACK }, - {"unpack", 1, 0, OPT_MODE_UNPACK }, - {"datapubkey", 1, 0, OPT_DATAPUBKEY }, - {"signpubkey", 1, 0, OPT_SIGNPUBKEY }, - {"signprivate", 1, 0, OPT_SIGNPRIVATE }, - {"signprivate_pem", 1, 0, OPT_SIGNPRIVATE_PEM }, - {"pem_algorithm", 1, 0, OPT_PEM_ALGORITHM }, - {"externalsigner", 1, 0, OPT_EXTERNAL_SIGNER }, - {"flags", 1, 0, OPT_FLAGS }, - {NULL, 0, 0, 0} + {"pack", 1, 0, OPT_MODE_PACK}, + {"unpack", 1, 0, OPT_MODE_UNPACK}, + {"datapubkey", 1, 0, OPT_DATAPUBKEY}, + {"signpubkey", 1, 0, OPT_SIGNPUBKEY}, + {"signprivate", 1, 0, OPT_SIGNPRIVATE}, + {"signprivate_pem", 1, 0, OPT_SIGNPRIVATE_PEM}, + {"pem_algorithm", 1, 0, OPT_PEM_ALGORITHM}, + {"externalsigner", 1, 0, OPT_EXTERNAL_SIGNER}, + {"flags", 1, 0, OPT_FLAGS}, + {NULL, 0, 0, 0} }; +static const char usage[] = + "Verified boot key block utility\n" + "\n" + "Usage: %s <--pack|--unpack> <file> [OPTIONS]\n" + "\n" + "For '--pack <file>', required OPTIONS are:\n" + " --datapubkey <file> Data public key in .vbpubk format\n" + "\n" + "Optional OPTIONS are:\n" + " --signprivate <file>" + " Signing private key in .vbprivk format.\n" + "OR\n" + " --signprivate_pem <file>\n" + " --pem_algorithm <algo>\n" + " Signing private key in .pem format and algorithm id.\n" + "(If one of the above arguments is not specified, the keyblock will\n" + "not be signed.)\n" + "\n" + " --flags <number> Specifies allowed use conditions.\n" + " --externalsigner \"cmd\"" + " Use an external program cmd to calculate the signatures.\n" + "\n" + "For '--unpack <file>', optional OPTIONS are:\n" + " --signpubkey <file>" + " Signing public key in .vbpubk format. This is required to\n" + " verify a signed keyblock.\n" + " --datapubkey <file>" + " Write the data public key to this file.\n"; /* Print help and return error */ -static int PrintHelp(char *progname) { - fprintf(stderr, - "Verified boot key block utility\n" - "\n" - "Usage: %s <--pack|--unpack> <file> [OPTIONS]\n" - "\n" - "For '--pack <file>', required OPTIONS are:\n" - " --datapubkey <file> Data public key in .vbpubk format\n" - "\n" - "Optional OPTIONS are:\n" - " --signprivate <file>" - " Signing private key in .vbprivk format.\n" - "OR\n" - " --signprivate_pem <file>\n" - " --pem_algorithm <algo>\n" - " Signing private key in .pem format and algorithm id.\n" - "(If one of the above arguments is not specified, the keyblock will\n" - "not be signed.)\n" - "\n" - " --flags <number> Specifies allowed use conditions.\n" - " --externalsigner \"cmd\"" - " Use an external program cmd to calculate the signatures.\n" - "\n" - "For '--unpack <file>', optional OPTIONS are:\n" - " --signpubkey <file>" - " Signing public key in .vbpubk format. This is required to\n" - " verify a signed keyblock.\n" - " --datapubkey <file>" - " Write the data public key to this file.\n", - progname); - return 1; +static int PrintHelp(char *progname) +{ + fprintf(stderr, usage, progname); + return 1; } /* Pack a .keyblock */ -static int Pack(const char* outfile, const char* datapubkey, - const char* signprivate, - const char* signprivate_pem, uint64_t pem_algorithm, - uint64_t flags, - const char* external_signer) { - VbPublicKey* data_key; - VbPrivateKey* signing_key = NULL; - VbKeyBlockHeader* block; - - if (!outfile) { - fprintf(stderr, "vbutil_keyblock: Must specify output filename.\n"); - return 1; - } - if (!datapubkey) { - fprintf(stderr, "vbutil_keyblock: Must specify data public key.\n"); - return 1; - } - - data_key = PublicKeyRead(datapubkey); - if (!data_key) { - fprintf(stderr, "vbutil_keyblock: Error reading data key.\n"); - return 1; - } - - if (signprivate_pem) { - if (pem_algorithm >= kNumAlgorithms) { - fprintf(stderr, "vbutil_keyblock: Invalid --pem_algorithm %" PRIu64 "\n", - pem_algorithm); - return 1; - } - if (external_signer) { - /* External signing uses the PEM file directly. */ - block = KeyBlockCreate_external(data_key, - signprivate_pem, pem_algorithm, - flags, - external_signer); - } else { - signing_key = PrivateKeyReadPem(signprivate_pem, pem_algorithm); - if (!signing_key) { - fprintf(stderr, "vbutil_keyblock: Error reading signing key.\n"); - return 1; - } - block = KeyBlockCreate(data_key, signing_key, flags); - } - } else { - if (signprivate) { - signing_key = PrivateKeyRead(signprivate); - if (!signing_key) { - fprintf(stderr, "vbutil_keyblock: Error reading signing key.\n"); - return 1; - } - } - block = KeyBlockCreate(data_key, signing_key, flags); - } - - free(data_key); - if (signing_key) - free(signing_key); - - if (0 != KeyBlockWrite(outfile, block)) { - fprintf(stderr, "vbutil_keyblock: Error writing key block.\n"); - return 1; - } - free(block); - return 0; +static int Pack(const char *outfile, const char *datapubkey, + const char *signprivate, + const char *signprivate_pem, uint64_t pem_algorithm, + uint64_t flags, const char *external_signer) +{ + VbPublicKey *data_key; + VbPrivateKey *signing_key = NULL; + VbKeyBlockHeader *block; + + if (!outfile) { + fprintf(stderr, + "vbutil_keyblock: Must specify output filename.\n"); + return 1; + } + if (!datapubkey) { + fprintf(stderr, + "vbutil_keyblock: Must specify data public key.\n"); + return 1; + } + + data_key = PublicKeyRead(datapubkey); + if (!data_key) { + fprintf(stderr, "vbutil_keyblock: Error reading data key.\n"); + return 1; + } + + if (signprivate_pem) { + if (pem_algorithm >= kNumAlgorithms) { + fprintf(stderr, + "vbutil_keyblock: Invalid --pem_algorithm %" + PRIu64 "\n", pem_algorithm); + return 1; + } + if (external_signer) { + /* External signing uses the PEM file directly. */ + block = KeyBlockCreate_external(data_key, + signprivate_pem, + pem_algorithm, flags, + external_signer); + } else { + signing_key = + PrivateKeyReadPem(signprivate_pem, pem_algorithm); + if (!signing_key) { + fprintf(stderr, "vbutil_keyblock:" + " Error reading signing key.\n"); + return 1; + } + block = KeyBlockCreate(data_key, signing_key, flags); + } + } else { + if (signprivate) { + signing_key = PrivateKeyRead(signprivate); + if (!signing_key) { + fprintf(stderr, "vbutil_keyblock:" + " Error reading signing key.\n"); + return 1; + } + } + block = KeyBlockCreate(data_key, signing_key, flags); + } + + free(data_key); + if (signing_key) + free(signing_key); + + if (0 != KeyBlockWrite(outfile, block)) { + fprintf(stderr, "vbutil_keyblock: Error writing key block.\n"); + return 1; + } + free(block); + return 0; } -static int Unpack(const char* infile, const char* datapubkey, - const char* signpubkey) { - VbPublicKey* data_key; - VbPublicKey* sign_key = NULL; - VbKeyBlockHeader* block; - - if (!infile) { - fprintf(stderr, "vbutil_keyblock: Must specify filename\n"); - return 1; - } - - block = KeyBlockRead(infile); - if (!block) { - fprintf(stderr, "vbutil_keyblock: Error reading key block.\n"); - return 1; - } - - /* If the block is signed, then verify it with the signing public key, since - KeyBlockRead() only verified the hash. */ - if (block->key_block_signature.sig_size && signpubkey) { - sign_key = PublicKeyRead(signpubkey); - if (!sign_key) { - fprintf(stderr, "vbutil_keyblock: Error reading signpubkey.\n"); - return 1; - } - if (0 != KeyBlockVerify(block, block->key_block_size, sign_key, 0)) { - fprintf(stderr, "vbutil_keyblock: Error verifying key block.\n"); - return 1; - } - free(sign_key); - } - - printf("Key block file: %s\n", infile); - printf("Signature %s\n", sign_key ? "valid" : "ignored"); - printf("Flags: %" PRIu64 " ", block->key_block_flags); - if (block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0) - printf(" !DEV"); - if (block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1) - printf(" DEV"); - if (block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0) - printf(" !REC"); - if (block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1) - printf(" REC"); - printf("\n"); - - data_key = &block->data_key; - 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"); - - if (datapubkey) { - if (0 != PublicKeyWrite(datapubkey, data_key)) { - fprintf(stderr, - "vbutil_keyblock: unable to write public key\n"); - return 1; - } - } - - free(block); - return 0; +static int Unpack(const char *infile, const char *datapubkey, + const char *signpubkey) +{ + VbPublicKey *data_key; + VbPublicKey *sign_key = NULL; + VbKeyBlockHeader *block; + + if (!infile) { + fprintf(stderr, "vbutil_keyblock: Must specify filename\n"); + return 1; + } + + block = KeyBlockRead(infile); + if (!block) { + fprintf(stderr, "vbutil_keyblock: Error reading key block.\n"); + return 1; + } + + /* If the block is signed, then verify it with the signing public key, + * since KeyBlockRead() only verified the hash. */ + if (block->key_block_signature.sig_size && signpubkey) { + sign_key = PublicKeyRead(signpubkey); + if (!sign_key) { + fprintf(stderr, + "vbutil_keyblock: Error reading signpubkey.\n"); + return 1; + } + if (0 != + KeyBlockVerify(block, block->key_block_size, sign_key, 0)) { + fprintf(stderr, "vbutil_keyblock:" + " Error verifying key block.\n"); + return 1; + } + free(sign_key); + } + + printf("Key block file: %s\n", infile); + printf("Signature %s\n", sign_key ? "valid" : "ignored"); + printf("Flags: %" PRIu64 " ", block->key_block_flags); + if (block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0) + printf(" !DEV"); + if (block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1) + printf(" DEV"); + if (block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0) + printf(" !REC"); + if (block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1) + printf(" REC"); + printf("\n"); + + data_key = &block->data_key; + 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"); + + if (datapubkey) { + if (0 != PublicKeyWrite(datapubkey, data_key)) { + fprintf(stderr, "vbutil_keyblock:" + " unable to write public key\n"); + return 1; + } + } + + free(block); + return 0; } - -static int do_vbutil_keyblock(int argc, char* argv[]) { - - char* filename = NULL; - char* datapubkey = NULL; - char* signpubkey = NULL; - char* signprivate = NULL; - char* signprivate_pem = NULL; - char* external_signer = NULL; - uint64_t flags = 0; - uint64_t pem_algorithm = 0; - int is_pem_algorithm = 0; - int mode = 0; - int parse_error = 0; - char* e; - int i; - - char *progname = strrchr(argv[0], '/'); - if (progname) - progname++; - else - progname = argv[0]; - - 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_PACK: - case OPT_MODE_UNPACK: - mode = i; - filename = optarg; - break; - - case OPT_DATAPUBKEY: - datapubkey = optarg; - break; - - case OPT_SIGNPUBKEY: - signpubkey = optarg; - break; - - case OPT_SIGNPRIVATE: - signprivate = optarg; - break; - - case OPT_SIGNPRIVATE_PEM: - signprivate_pem = optarg; - break; - - case OPT_PEM_ALGORITHM: - pem_algorithm = strtoul(optarg, &e, 0); - if (!*optarg || (e && *e)) { - fprintf(stderr, "Invalid --pem_algorithm\n"); - parse_error = 1; - } else { - is_pem_algorithm = 1; - } - break; - - case OPT_EXTERNAL_SIGNER: - external_signer = optarg; - break; - - case OPT_FLAGS: - flags = strtoul(optarg, &e, 0); - if (!*optarg || (e && *e)) { - fprintf(stderr, "Invalid --flags\n"); - parse_error = 1; - } - break; - } - } - - /* Check if the right combination of options was provided. */ - if (signprivate && signprivate_pem) { - fprintf(stderr, "Only one of --signprivate or --signprivate_pem must" - " be specified\n"); - parse_error = 1; - } - - if (signprivate_pem && !is_pem_algorithm) { - fprintf(stderr, "--pem_algorithm must be used with --signprivate_pem\n"); - parse_error = 1; - } - - if (external_signer && !signprivate_pem) { - fprintf(stderr, "--externalsigner must be used with --signprivate_pem" - "\n"); - parse_error = 1; - } - - if (parse_error) - return PrintHelp(progname); - - switch(mode) { - case OPT_MODE_PACK: - return Pack(filename, datapubkey, signprivate, - signprivate_pem, pem_algorithm, - flags, - external_signer); - case OPT_MODE_UNPACK: - return Unpack(filename, datapubkey, signpubkey); - default: - printf("Must specify a mode.\n"); - return PrintHelp(progname); - } +static int do_vbutil_keyblock(int argc, char *argv[]) +{ + + char *filename = NULL; + char *datapubkey = NULL; + char *signpubkey = NULL; + char *signprivate = NULL; + char *signprivate_pem = NULL; + char *external_signer = NULL; + uint64_t flags = 0; + uint64_t pem_algorithm = 0; + int is_pem_algorithm = 0; + int mode = 0; + int parse_error = 0; + char *e; + int i; + + char *progname = strrchr(argv[0], '/'); + if (progname) + progname++; + else + progname = argv[0]; + + 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_PACK: + case OPT_MODE_UNPACK: + mode = i; + filename = optarg; + break; + + case OPT_DATAPUBKEY: + datapubkey = optarg; + break; + + case OPT_SIGNPUBKEY: + signpubkey = optarg; + break; + + case OPT_SIGNPRIVATE: + signprivate = optarg; + break; + + case OPT_SIGNPRIVATE_PEM: + signprivate_pem = optarg; + break; + + case OPT_PEM_ALGORITHM: + pem_algorithm = strtoul(optarg, &e, 0); + if (!*optarg || (e && *e)) { + fprintf(stderr, "Invalid --pem_algorithm\n"); + parse_error = 1; + } else { + is_pem_algorithm = 1; + } + break; + + case OPT_EXTERNAL_SIGNER: + external_signer = optarg; + break; + + case OPT_FLAGS: + flags = strtoul(optarg, &e, 0); + if (!*optarg || (e && *e)) { + fprintf(stderr, "Invalid --flags\n"); + parse_error = 1; + } + break; + } + } + + /* Check if the right combination of options was provided. */ + if (signprivate && signprivate_pem) { + fprintf(stderr, + "Only one of --signprivate or --signprivate_pem must" + " be specified\n"); + parse_error = 1; + } + + if (signprivate_pem && !is_pem_algorithm) { + fprintf(stderr, "--pem_algorithm must be used with" + " --signprivate_pem\n"); + parse_error = 1; + } + + if (external_signer && !signprivate_pem) { + fprintf(stderr, + "--externalsigner must be used with --signprivate_pem" + "\n"); + parse_error = 1; + } + + if (parse_error) + return PrintHelp(progname); + + switch (mode) { + case OPT_MODE_PACK: + return Pack(filename, datapubkey, signprivate, + signprivate_pem, pem_algorithm, + flags, external_signer); + case OPT_MODE_UNPACK: + return Unpack(filename, datapubkey, signpubkey); + default: + printf("Must specify a mode.\n"); + return PrintHelp(progname); + } } DECLARE_FUTIL_COMMAND(vbutil_keyblock, do_vbutil_keyblock, |