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;