diff options
author | James Bottomley <James.Bottomley@HansenPartnership.com> | 2019-01-05 13:44:13 -0800 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2019-01-05 13:44:13 -0800 |
commit | 7c4991f1b7eea98f2b5137f274a2f23af63ac174 (patch) | |
tree | bdb33d1aa58e8103f17ca53704bdb8a6eb173ccf | |
parent | 0844b10e7681a10caa42fb728838974f76bf7c96 (diff) | |
download | efitools-7c4991f1b7eea98f2b5137f274a2f23af63ac174.tar.gz |
support engine based keys
Add additional arguments to specify an openssl engine (-e for
sign-efi-sig-list and --engine for efi-update). If an engine is
specified, pass the keyfile to the engine load routines.
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r-- | efi-updatevar.c | 9 | ||||
-rw-r--r-- | include/openssl_sign.h | 4 | ||||
-rw-r--r-- | lib/openssl_sign.c | 93 | ||||
-rw-r--r-- | sign-efi-sig-list.c | 9 |
4 files changed, 107 insertions, 8 deletions
diff --git a/efi-updatevar.c b/efi-updatevar.c index ffbbe99..4247105 100644 --- a/efi-updatevar.c +++ b/efi-updatevar.c @@ -52,6 +52,7 @@ help(const char *progname) "\t-g <guid>\tOptional <guid> for the X509 Certificate\n" "\t-k <key>\tSecret key file for authorising User Mode updates\n" "\t-d <list>[-<entry>]\tDelete the signature list <list> (or just a single <entry> within the list)\n" + "\t--engine <eng>\tUse engine <eng> for private key\n" ); } @@ -60,6 +61,7 @@ main(int argc, char *argv[]) { char *variables[] = { "PK", "KEK", "db", "dbx" }; char *signedby[] = { "PK", "PK", "KEK", "KEK" }; + char *engine = NULL; EFI_GUID *owners[] = { &GV_GUID, &GV_GUID, &SIG_DB, &SIG_DB }; EFI_GUID *owner, guid = MOK_OWNER; int i, esl_mode = 0, fd, ret, delsig = -1, delentry = -1; @@ -114,6 +116,10 @@ main(int argc, char *argv[]) sscanf(argv[2], "%d-%d", &delsig, &delentry); argv += 2; argc -= 2; + } else if (strcmp(argv[1], "--engine") == 0) { + engine = argv[2]; + argv += 2; + argc -= 2; } else { /* unrecognised option */ break; @@ -280,8 +286,7 @@ main(int argc, char *argv[]) fprintf(stderr, "Can't update variable%s without a key\n", variable_is_setupmode() ? "" : " in User Mode"); exit(1); } - BIO *key = BIO_new_file(key_file, "r"); - EVP_PKEY *pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL); + EVP_PKEY *pkey = read_private_key(engine, key_file); if (!pkey) { fprintf(stderr, "error reading private key %s\n", key_file); exit(1); diff --git a/include/openssl_sign.h b/include/openssl_sign.h index 7c58539..136ad75 100644 --- a/include/openssl_sign.h +++ b/include/openssl_sign.h @@ -2,7 +2,9 @@ int sign_efi_var(char *payload, int payload_size, char *keyfile, char *certfile, - unsigned char **sig, int *sigsize); + unsigned char **sig, int *sigsize, char *engine); int sign_efi_var_ssl(char *payload, int payload_size, EVP_PKEY *pkey, X509 *cert, unsigned char **sig, int *sigsize); +EVP_PKEY * +read_private_key(char *engine, char *keyfile); diff --git a/lib/openssl_sign.c b/lib/openssl_sign.c index 90e319e..a187040 100644 --- a/lib/openssl_sign.c +++ b/lib/openssl_sign.c @@ -7,6 +7,7 @@ #include <openssl/pem.h> #include <openssl/err.h> #include <openssl/sha.h> +#include <openssl/engine.h> #include <openssl_sign.h> @@ -32,7 +33,7 @@ sign_efi_var_ssl(char *payload, int payload_size, EVP_PKEY *pkey, X509 *cert, int sign_efi_var(char *payload, int payload_size, char *keyfile, char *certfile, - unsigned char **sig, int *sigsize) + unsigned char **sig, int *sigsize, char *engine) { int ret; @@ -46,15 +47,20 @@ sign_efi_var(char *payload, int payload_size, char *keyfile, char *certfile, ERR_clear_error(); BIO *cert_bio = BIO_new_file(certfile, "r"); + if (!cert_bio) { + ERR_print_errors_fp(stdout); + fprintf(stderr, "error reading certificate %s\n", certfile); + return 1; + } X509 *cert = PEM_read_bio_X509(cert_bio, NULL, NULL, NULL); + BIO_free(cert_bio); if (!cert) { ERR_print_errors_fp(stdout); fprintf(stderr, "error reading certificate %s\n", certfile); return 1; } - BIO *privkey_bio = BIO_new_file(keyfile, "r"); - EVP_PKEY *pkey = PEM_read_bio_PrivateKey(privkey_bio, NULL, NULL, NULL); + EVP_PKEY *pkey = read_private_key(engine, keyfile); if (!pkey) { ERR_print_errors_fp(stdout); fprintf(stderr, "error reading private key %s\n", keyfile); @@ -67,3 +73,84 @@ sign_efi_var(char *payload, int payload_size, char *keyfile, char *certfile, return ret; } + +static EVP_PKEY * +read_pem_private_key(char *keyfile) +{ + BIO *key = BIO_new_file(keyfile, "r"); + EVP_PKEY *pkey; + + if (!key) { + ERR_print_errors_fp(stdout); + fprintf(stderr, "error reading private key file %s\n", keyfile); + return NULL; + } + pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL); + BIO_free(key); + + if (!pkey) { + ERR_print_errors_fp(stdout); + fprintf(stderr, "error processing private key file %s\n", keyfile); + return NULL; + } + return pkey; +} + +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; +} + +static EVP_PKEY * +read_engine_private_key(char *engine, char *keyfile) +{ + 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, keyfile, ui, NULL); + ENGINE_finish(e); + + out_free: + ENGINE_free(e); + return pkey; +} + +EVP_PKEY * +read_private_key(char *engine, char *keyfile) +{ + if (engine) + return read_engine_private_key(engine, keyfile); + else + return read_pem_private_key(keyfile); +} diff --git a/sign-efi-sig-list.c b/sign-efi-sig-list.c index cce8926..2657acd 100644 --- a/sign-efi-sig-list.c +++ b/sign-efi-sig-list.c @@ -31,7 +31,7 @@ static void usage(const char *progname) { - printf("Usage: %s [-r] [-m] [-a] [-g <guid>] [-o] [-t <timestamp>] [-i <infile>] [-c <crt file>] [-k <key file>] <var> <efi sig list file> <output file>\n", progname); + printf("Usage: %s [-r] [-m] [-a] [-g <guid>] [-o] [-t <timestamp>] [-i <infile>] [-c <crt file>] [-k <key file>] [-e <engine>] <var> <efi sig list file> <output file>\n", progname); } static void @@ -66,6 +66,7 @@ main(int argc, char *argv[]) *str, *signedinput = NULL, *timestampstr = NULL; void *out; const char *progname = argv[0]; + char *engine = NULL; unsigned char *sigbuf; int rsasig = 0, monotonic = 0, varlen, i, outputforsign = 0, outlen, sigsize; @@ -124,6 +125,10 @@ main(int argc, char *argv[]) certfile = argv[2]; argv += 2; argc -= 2; + } else if (strcmp("-e", argv[1]) == 0) { + engine = argv[2]; + argv += 2; + argc -= 2; } else { break; } @@ -243,7 +248,7 @@ main(int argc, char *argv[]) exit(1); } if (sign_efi_var(signbuf, signbuflen, keyfile, certfile, - &sigbuf, &sigsize)) + &sigbuf, &sigsize, engine)) exit(1); } printf("Signature of size %d\n", sigsize); |