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 <James.Bottomley@HansenPartnership.com>
This commit is contained in:
parent
62c9352519
commit
efc424c8ee
4 changed files with 76 additions and 6 deletions
50
src/fileio.c
50
src/fileio.c
|
@ -39,6 +39,7 @@
|
||||||
#include <openssl/bio.h>
|
#include <openssl/bio.h>
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/engine.h>
|
||||||
|
|
||||||
#include <ccan/talloc/talloc.h>
|
#include <ccan/talloc/talloc.h>
|
||||||
#include <ccan/read_write_all/read_write_all.h>
|
#include <ccan/read_write_all/read_write_all.h>
|
||||||
|
@ -47,6 +48,55 @@
|
||||||
|
|
||||||
#define FLAG_NOERROR (1<<0)
|
#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 *fileio_read_pkey(const char *filename)
|
||||||
{
|
{
|
||||||
EVP_PKEY *key = NULL;
|
EVP_PKEY *key = NULL;
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
|
|
||||||
EVP_PKEY *fileio_read_pkey(const char *filename);
|
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);
|
X509 *fileio_read_cert(const char *filename);
|
||||||
|
|
||||||
int fileio_read_file(void *ctx, const char *filename,
|
int fileio_read_file(void *ctx, const char *filename,
|
||||||
|
|
16
src/sbsign.c
16
src/sbsign.c
|
@ -74,6 +74,7 @@ static struct option options[] = {
|
||||||
{ "verbose", no_argument, NULL, 'v' },
|
{ "verbose", no_argument, NULL, 'v' },
|
||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
{ "version", no_argument, NULL, 'V' },
|
{ "version", no_argument, NULL, 'V' },
|
||||||
|
{ "engine", required_argument, NULL, 'e'},
|
||||||
{ NULL, 0, NULL, 0 },
|
{ NULL, 0, NULL, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,6 +84,7 @@ static void usage(void)
|
||||||
"<efi-boot-image>\n"
|
"<efi-boot-image>\n"
|
||||||
"Sign an EFI boot image for use with secure boot.\n\n"
|
"Sign an EFI boot image for use with secure boot.\n\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
|
"\t--engine <eng> use the specified engine to load the key\n"
|
||||||
"\t--key <keyfile> signing key (PEM-encoded RSA "
|
"\t--key <keyfile> signing key (PEM-encoded RSA "
|
||||||
"private key)\n"
|
"private key)\n"
|
||||||
"\t--cert <certfile> certificate (x509 certificate)\n"
|
"\t--cert <certfile> certificate (x509 certificate)\n"
|
||||||
|
@ -112,19 +114,21 @@ static void set_default_outfilename(struct sign_context *ctx)
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
const char *keyfilename, *certfilename;
|
const char *keyfilename, *certfilename, *engine;
|
||||||
struct sign_context *ctx;
|
struct sign_context *ctx;
|
||||||
uint8_t *buf, *tmp;
|
uint8_t *buf, *tmp;
|
||||||
int rc, c, sigsize;
|
int rc, c, sigsize;
|
||||||
|
EVP_PKEY *pkey;
|
||||||
|
|
||||||
ctx = talloc_zero(NULL, struct sign_context);
|
ctx = talloc_zero(NULL, struct sign_context);
|
||||||
|
|
||||||
keyfilename = NULL;
|
keyfilename = NULL;
|
||||||
certfilename = NULL;
|
certfilename = NULL;
|
||||||
|
engine = NULL;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int idx;
|
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)
|
if (c == -1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -150,6 +154,9 @@ int main(int argc, char **argv)
|
||||||
case 'h':
|
case 'h':
|
||||||
usage();
|
usage();
|
||||||
return EXIT_SUCCESS;
|
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
|
* module isn't present). In either case ignore the errors
|
||||||
* (malloc will cause other failures out lower down */
|
* (malloc will cause other failures out lower down */
|
||||||
ERR_clear_error();
|
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)
|
if (!pkey)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
|
|
@ -398,6 +398,7 @@ static struct option options[] = {
|
||||||
{ "verbose", no_argument, NULL, 'v' },
|
{ "verbose", no_argument, NULL, 'v' },
|
||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
{ "version", no_argument, NULL, 'V' },
|
{ "version", no_argument, NULL, 'V' },
|
||||||
|
{ "engine", required_argument, NULL, 'e'},
|
||||||
{ NULL, 0, NULL, 0 },
|
{ NULL, 0, NULL, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -409,6 +410,7 @@ void usage(void)
|
||||||
"<var-name> <var-data-file>\n"
|
"<var-name> <var-data-file>\n"
|
||||||
"Sign a blob of data for use in SetVariable().\n\n"
|
"Sign a blob of data for use in SetVariable().\n\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
|
"\t--engine <eng> use the specified engine to load the key\n"
|
||||||
"\t--key <keyfile> signing key (PEM-encoded RSA "
|
"\t--key <keyfile> signing key (PEM-encoded RSA "
|
||||||
"private key)\n"
|
"private key)\n"
|
||||||
"\t--cert <certfile> certificate (x509 certificate)\n"
|
"\t--cert <certfile> certificate (x509 certificate)\n"
|
||||||
|
@ -437,7 +439,7 @@ static void version(void)
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
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;
|
const char *keyfilename, *certfilename;
|
||||||
struct varsign_context *ctx;
|
struct varsign_context *ctx;
|
||||||
bool include_attrs;
|
bool include_attrs;
|
||||||
|
@ -447,13 +449,14 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
keyfilename = NULL;
|
keyfilename = NULL;
|
||||||
certfilename = NULL;
|
certfilename = NULL;
|
||||||
|
engine = NULL;
|
||||||
guid_str = NULL;
|
guid_str = NULL;
|
||||||
attr_str= NULL;
|
attr_str= NULL;
|
||||||
include_attrs = false;
|
include_attrs = false;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int idx;
|
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)
|
if (c == -1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -485,6 +488,9 @@ int main(int argc, char **argv)
|
||||||
case 'h':
|
case 'h':
|
||||||
usage();
|
usage();
|
||||||
return EXIT_SUCCESS;
|
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))
|
if (fileio_read_file(ctx, ctx->infilename, &ctx->data, &ctx->data_len))
|
||||||
return EXIT_FAILURE;
|
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)
|
if (!ctx->key)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue