From efc424c8eea2c398e4371320b4d7266898675ac8 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 28 Oct 2017 14:21:24 +0100 Subject: [PATCH] sbsign, sbvarsign: support engine based private keys Add the ability to specify an engine to read the keyfile. For safety, we don't do the full dynamic engine support, but only use engines configured for use by the platform. Signed-off-by: James Bottomley --- src/fileio.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ src/fileio.h | 1 + src/sbsign.c | 16 +++++++++++++--- src/sbvarsign.c | 15 ++++++++++++--- 4 files changed, 76 insertions(+), 6 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index faab3b7..032eb1e 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,55 @@ #define FLAG_NOERROR (1<<0) +static int ui_read(UI *ui, UI_STRING *uis) +{ + char password[128]; + + if (UI_get_string_type(uis) != UIT_PROMPT) + return 0; + + EVP_read_pw_string(password, sizeof(password), "Enter engine key pass phrase:", 0); + UI_set_result(ui, uis, password); + return 1; +} + +EVP_PKEY *fileio_read_engine_key(const char *engine, const char *filename) +{ + UI_METHOD *ui; + ENGINE *e; + EVP_PKEY *pkey = NULL; + + ENGINE_load_builtin_engines(); + e = ENGINE_by_id(engine); + + if (!e) { + fprintf(stderr, "Failed to load engine: %s\n", engine); + ERR_print_errors_fp(stderr); + return NULL; + } + + ui = UI_create_method("sbsigntools"); + if (!ui) { + fprintf(stderr, "Failed to create UI method\n"); + ERR_print_errors_fp(stderr); + goto out_free; + } + UI_method_set_reader(ui, ui_read); + + if (!ENGINE_init(e)) { + fprintf(stderr, "Failed to initialize engine %s\n", engine); + ERR_print_errors_fp(stderr); + goto out_free; + } + + pkey = ENGINE_load_private_key(e, filename, ui, NULL); + ENGINE_finish(e); + + out_free: + ENGINE_free(e); + return pkey; +} + EVP_PKEY *fileio_read_pkey(const char *filename) { EVP_PKEY *key = NULL; diff --git a/src/fileio.h b/src/fileio.h index 52c3c12..b3ed22c 100644 --- a/src/fileio.h +++ b/src/fileio.h @@ -38,6 +38,7 @@ #include EVP_PKEY *fileio_read_pkey(const char *filename); +EVP_PKEY *fileio_read_engine_key(const char *engine, const char *filename); X509 *fileio_read_cert(const char *filename); int fileio_read_file(void *ctx, const char *filename, diff --git a/src/sbsign.c b/src/sbsign.c index 406472e..ff1fdfd 100644 --- a/src/sbsign.c +++ b/src/sbsign.c @@ -74,6 +74,7 @@ static struct option options[] = { { "verbose", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, + { "engine", required_argument, NULL, 'e'}, { NULL, 0, NULL, 0 }, }; @@ -83,6 +84,7 @@ static void usage(void) "\n" "Sign an EFI boot image for use with secure boot.\n\n" "Options:\n" + "\t--engine use the specified engine to load the key\n" "\t--key signing key (PEM-encoded RSA " "private key)\n" "\t--cert certificate (x509 certificate)\n" @@ -112,19 +114,21 @@ static void set_default_outfilename(struct sign_context *ctx) int main(int argc, char **argv) { - const char *keyfilename, *certfilename; + const char *keyfilename, *certfilename, *engine; struct sign_context *ctx; uint8_t *buf, *tmp; int rc, c, sigsize; + EVP_PKEY *pkey; ctx = talloc_zero(NULL, struct sign_context); keyfilename = NULL; certfilename = NULL; + engine = NULL; for (;;) { int idx; - c = getopt_long(argc, argv, "o:c:k:dvVh", options, &idx); + c = getopt_long(argc, argv, "o:c:k:dvVhe:", options, &idx); if (c == -1) break; @@ -150,6 +154,9 @@ int main(int argc, char **argv) case 'h': usage(); return EXIT_SUCCESS; + case 'e': + engine = optarg; + break; } } @@ -190,7 +197,10 @@ int main(int argc, char **argv) * module isn't present). In either case ignore the errors * (malloc will cause other failures out lower down */ ERR_clear_error(); - EVP_PKEY *pkey = fileio_read_pkey(keyfilename); + if (engine) + pkey = fileio_read_engine_key(engine, keyfilename); + else + pkey = fileio_read_pkey(keyfilename); if (!pkey) return EXIT_FAILURE; diff --git a/src/sbvarsign.c b/src/sbvarsign.c index b45cccb..7dcbe51 100644 --- a/src/sbvarsign.c +++ b/src/sbvarsign.c @@ -398,6 +398,7 @@ static struct option options[] = { { "verbose", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, + { "engine", required_argument, NULL, 'e'}, { NULL, 0, NULL, 0 }, }; @@ -409,6 +410,7 @@ void usage(void) " \n" "Sign a blob of data for use in SetVariable().\n\n" "Options:\n" + "\t--engine use the specified engine to load the key\n" "\t--key signing key (PEM-encoded RSA " "private key)\n" "\t--cert certificate (x509 certificate)\n" @@ -437,7 +439,7 @@ static void version(void) int main(int argc, char **argv) { - const char *guid_str, *attr_str, *varname; + const char *guid_str, *attr_str, *varname, *engine; const char *keyfilename, *certfilename; struct varsign_context *ctx; bool include_attrs; @@ -447,13 +449,14 @@ int main(int argc, char **argv) keyfilename = NULL; certfilename = NULL; + engine = NULL; guid_str = NULL; attr_str= NULL; include_attrs = false; for (;;) { int idx; - c = getopt_long(argc, argv, "o:g:a:k:c:ivVh", options, &idx); + c = getopt_long(argc, argv, "o:g:a:k:c:ivVhe:", options, &idx); if (c == -1) break; @@ -485,6 +488,9 @@ int main(int argc, char **argv) case 'h': usage(); return EXIT_SUCCESS; + case 'e': + engine = optarg; + break; } } @@ -542,7 +548,10 @@ int main(int argc, char **argv) if (fileio_read_file(ctx, ctx->infilename, &ctx->data, &ctx->data_len)) return EXIT_FAILURE; - ctx->key = fileio_read_pkey(keyfilename); + if (engine) + ctx->key = fileio_read_engine_key(engine, keyfilename); + else + ctx->key = fileio_read_pkey(keyfilename); if (!ctx->key) return EXIT_FAILURE;