aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2019-01-05 13:44:13 -0800
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2019-01-05 13:44:13 -0800
commit7c4991f1b7eea98f2b5137f274a2f23af63ac174 (patch)
treebdb33d1aa58e8103f17ca53704bdb8a6eb173ccf
parent0844b10e7681a10caa42fb728838974f76bf7c96 (diff)
downloadefitools-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.c9
-rw-r--r--include/openssl_sign.h4
-rw-r--r--lib/openssl_sign.c93
-rw-r--r--sign-efi-sig-list.c9
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);