|
@@ -0,0 +1,203 @@
|
|
|
+/*
|
|
|
+ * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
|
|
|
+ *
|
|
|
+ * Licensed under the OpenSSL license (the "License"). You may not use
|
|
|
+ * this file except in compliance with the License. You can obtain a copy
|
|
|
+ * in the file LICENSE in the source distribution or at
|
|
|
+ * https://www.openssl.org/source/license.html
|
|
|
+ */
|
|
|
+
|
|
|
+/*
|
|
|
+ * Here is an STORE loader for ENGINE backed keys. It relies on deprecated
|
|
|
+ * functions, and therefore need to have deprecation warnings suppressed.
|
|
|
+ * This file is not compiled at all in a '--api=3 no-deprecated' configuration.
|
|
|
+ */
|
|
|
+#define OPENSSL_SUPPRESS_DEPRECATED
|
|
|
+
|
|
|
+#include "apps.h"
|
|
|
+
|
|
|
+#ifndef OPENSSL_NO_ENGINE
|
|
|
+
|
|
|
+# include <stdarg.h>
|
|
|
+# include <string.h>
|
|
|
+# include <openssl/engine.h>
|
|
|
+# include <openssl/store.h>
|
|
|
+
|
|
|
+/*
|
|
|
+ * Support for legacy private engine keys via the 'org.openssl.engine:' scheme
|
|
|
+ *
|
|
|
+ * org.openssl.engine:{engineid}:{keyid}
|
|
|
+ *
|
|
|
+ * Note: we ONLY support ENGINE_load_private_key() and ENGINE_load_public_key()
|
|
|
+ * Note 2: This scheme has a precedent in code in PKIX-SSH. for exactly
|
|
|
+ * this sort of purpose.
|
|
|
+ */
|
|
|
+
|
|
|
+/* Local definition of OSSL_STORE_LOADER_CTX */
|
|
|
+struct ossl_store_loader_ctx_st {
|
|
|
+ ENGINE *e; /* Structural reference */
|
|
|
+ char *keyid;
|
|
|
+ int expected;
|
|
|
+ int loaded; /* 0 = key not loaded yet, 1 = key loaded */
|
|
|
+};
|
|
|
+
|
|
|
+static OSSL_STORE_LOADER_CTX *OSSL_STORE_LOADER_CTX_new(ENGINE *e, char *keyid)
|
|
|
+{
|
|
|
+ OSSL_STORE_LOADER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
|
|
|
+
|
|
|
+ if (ctx != NULL) {
|
|
|
+ ctx->e = e;
|
|
|
+ ctx->keyid = keyid;
|
|
|
+ }
|
|
|
+ return ctx;
|
|
|
+}
|
|
|
+
|
|
|
+static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx)
|
|
|
+{
|
|
|
+ if (ctx != NULL) {
|
|
|
+ ENGINE_free(ctx->e);
|
|
|
+ OPENSSL_free(ctx->keyid);
|
|
|
+ OPENSSL_free(ctx);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static OSSL_STORE_LOADER_CTX *engine_open(const OSSL_STORE_LOADER *loader,
|
|
|
+ const char *uri,
|
|
|
+ const UI_METHOD *ui_method,
|
|
|
+ void *ui_data)
|
|
|
+{
|
|
|
+ const char *p = uri, *q;
|
|
|
+ ENGINE *e = NULL;
|
|
|
+ char *keyid = NULL;
|
|
|
+ OSSL_STORE_LOADER_CTX *ctx = NULL;
|
|
|
+
|
|
|
+ if (strncasecmp(p, ENGINE_SCHEME_COLON, sizeof(ENGINE_SCHEME_COLON) - 1)
|
|
|
+ != 0)
|
|
|
+ return NULL;
|
|
|
+ p += sizeof(ENGINE_SCHEME_COLON) - 1;
|
|
|
+
|
|
|
+ /* Look for engine ID */
|
|
|
+ q = strchr(p, ':');
|
|
|
+ if (q != NULL /* There is both an engine ID and a key ID */
|
|
|
+ && p[0] != ':' /* The engine ID is at least one character */
|
|
|
+ && q[1] != '\0') { /* The key ID is at least one character */
|
|
|
+ char engineid[256];
|
|
|
+ size_t engineid_l = q - p;
|
|
|
+
|
|
|
+ strncpy(engineid, p, engineid_l);
|
|
|
+ engineid[engineid_l] = '\0';
|
|
|
+ e = ENGINE_by_id(engineid);
|
|
|
+
|
|
|
+ keyid = OPENSSL_strdup(q + 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (e != NULL)
|
|
|
+ ctx = OSSL_STORE_LOADER_CTX_new(e, keyid);
|
|
|
+
|
|
|
+ if (ctx == NULL) {
|
|
|
+ OPENSSL_free(keyid);
|
|
|
+ ENGINE_free(e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ctx;
|
|
|
+}
|
|
|
+
|
|
|
+static int engine_expect(OSSL_STORE_LOADER_CTX *ctx, int expected)
|
|
|
+{
|
|
|
+ if (expected == 0
|
|
|
+ || expected == OSSL_STORE_INFO_PUBKEY
|
|
|
+ || expected == OSSL_STORE_INFO_PKEY) {
|
|
|
+ ctx->expected = expected;
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static OSSL_STORE_INFO *engine_load(OSSL_STORE_LOADER_CTX *ctx,
|
|
|
+ const UI_METHOD *ui_method, void *ui_data)
|
|
|
+{
|
|
|
+ EVP_PKEY *pkey = NULL, *pubkey = NULL;
|
|
|
+ OSSL_STORE_INFO *info = NULL;
|
|
|
+
|
|
|
+ if (ctx->loaded == 0) {
|
|
|
+ if (ENGINE_init(ctx->e)) {
|
|
|
+ if (ctx->expected == 0
|
|
|
+ || ctx->expected == OSSL_STORE_INFO_PKEY)
|
|
|
+ pkey =
|
|
|
+ ENGINE_load_private_key(ctx->e, ctx->keyid,
|
|
|
+ (UI_METHOD *)ui_method, ui_data);
|
|
|
+ if ((pkey == NULL && ctx->expected == 0)
|
|
|
+ || ctx->expected == OSSL_STORE_INFO_PUBKEY)
|
|
|
+ pubkey =
|
|
|
+ ENGINE_load_public_key(ctx->e, ctx->keyid,
|
|
|
+ (UI_METHOD *)ui_method, ui_data);
|
|
|
+ ENGINE_finish(ctx->e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ctx->loaded = 1;
|
|
|
+
|
|
|
+ if (pubkey != NULL)
|
|
|
+ info = OSSL_STORE_INFO_new_PUBKEY(pubkey);
|
|
|
+ else if (pkey != NULL)
|
|
|
+ info = OSSL_STORE_INFO_new_PKEY(pkey);
|
|
|
+ if (info == NULL) {
|
|
|
+ EVP_PKEY_free(pkey);
|
|
|
+ EVP_PKEY_free(pubkey);
|
|
|
+ }
|
|
|
+ return info;
|
|
|
+}
|
|
|
+
|
|
|
+static int engine_eof(OSSL_STORE_LOADER_CTX *ctx)
|
|
|
+{
|
|
|
+ return ctx->loaded != 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int engine_error(OSSL_STORE_LOADER_CTX *ctx)
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int engine_close(OSSL_STORE_LOADER_CTX *ctx)
|
|
|
+{
|
|
|
+ OSSL_STORE_LOADER_CTX_free(ctx);
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+int setup_engine_loader(void)
|
|
|
+{
|
|
|
+ OSSL_STORE_LOADER *loader = NULL;
|
|
|
+
|
|
|
+ if ((loader = OSSL_STORE_LOADER_new(NULL, ENGINE_SCHEME)) == NULL
|
|
|
+ || !OSSL_STORE_LOADER_set_open(loader, engine_open)
|
|
|
+ || !OSSL_STORE_LOADER_set_expect(loader, engine_expect)
|
|
|
+ || !OSSL_STORE_LOADER_set_load(loader, engine_load)
|
|
|
+ || !OSSL_STORE_LOADER_set_eof(loader, engine_eof)
|
|
|
+ || !OSSL_STORE_LOADER_set_error(loader, engine_error)
|
|
|
+ || !OSSL_STORE_LOADER_set_close(loader, engine_close)
|
|
|
+ || !OSSL_STORE_register_loader(loader)) {
|
|
|
+ OSSL_STORE_LOADER_free(loader);
|
|
|
+ loader = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return loader != NULL;
|
|
|
+}
|
|
|
+
|
|
|
+void destroy_engine_loader(void)
|
|
|
+{
|
|
|
+ OSSL_STORE_LOADER *loader = OSSL_STORE_unregister_loader(ENGINE_SCHEME);
|
|
|
+ OSSL_STORE_LOADER_free(loader);
|
|
|
+}
|
|
|
+
|
|
|
+#else /* !OPENSSL_NO_ENGINE */
|
|
|
+
|
|
|
+int setup_engine_loader(void)
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+void destroy_engine_loader(void)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|