Index: utility/vbutil_keyblock.c |
diff --git a/utility/vbutil_keyblock.c b/utility/vbutil_keyblock.c |
index dd13eb3df0482ff2866ed9e688ba129dfc26cb1b..c9192213e26e153212b3890bdc569f6479b65a8f 100644 |
--- a/utility/vbutil_keyblock.c |
+++ b/utility/vbutil_keyblock.c |
@@ -6,7 +6,7 @@ |
*/ |
#include <getopt.h> |
-#include <inttypes.h> /* For PRIu64 */ |
+#include <stdint.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
@@ -23,6 +23,9 @@ enum { |
OPT_DATAPUBKEY, |
OPT_SIGNPUBKEY, |
OPT_SIGNPRIVATE, |
+ OPT_SIGNPRIVATE_PEM, |
+ OPT_PEM_ALGORITHM, |
+ OPT_EXTERNAL_SIGNER, |
OPT_FLAGS, |
}; |
@@ -32,6 +35,9 @@ static struct option long_opts[] = { |
{"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} |
}; |
@@ -49,24 +55,34 @@ static int PrintHelp(char *progname) { |
"\n" |
"Optional OPTIONS are:\n" |
" --signprivate <file>" |
- " Signing private key in .vbprivk format. Without this arg,\n" |
- " the keyblock will not be signed.\n" |
+ " 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" |
+ " 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", |
+ " Write the data public key to this file.\n", |
progname); |
return 1; |
} |
- |
/* Pack a .keyblock */ |
static int Pack(const char* outfile, const char* datapubkey, |
- const char* signprivate, uint64_t flags) { |
+ 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; |
@@ -86,15 +102,37 @@ static int Pack(const char* outfile, const char* datapubkey, |
return 1; |
} |
- if (signprivate) { |
- signing_key = PrivateKeyRead(signprivate); |
- if (!signing_key) { |
- fprintf(stderr, "vbutil_keyblock: Error reading signing key.\n"); |
+ 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_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); |
} |
- block = KeyBlockCreate(data_key, signing_key, flags); |
Free(data_key); |
if (signing_key) |
Free(signing_key); |
@@ -107,7 +145,6 @@ static int Pack(const char* outfile, const char* datapubkey, |
return 0; |
} |
- |
static int Unpack(const char* infile, const char* datapubkey, |
const char* signpubkey) { |
VbPublicKey* data_key; |
@@ -181,7 +218,11 @@ int main(int argc, char* argv[]) { |
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; |
@@ -219,22 +260,61 @@ int main(int argc, char* argv[]) { |
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)) { |
- printf("Invalid --flags\n"); |
+ 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, flags); |
+ return Pack(filename, datapubkey, signprivate, |
+ signprivate_pem, pem_algorithm, |
+ flags, |
+ external_signer); |
case OPT_MODE_UNPACK: |
return Unpack(filename, datapubkey, signpubkey); |
default: |