mirror of https://github.com/openssl/openssl.git
APPS: Add OSSL_STORE loader for engine keys
The idea is to be able to have our apps load engine keys using a URI: org.openssl.engine:{engineid}:{keyid} This is legacy, but added for the time being to support keys given to the application like this: -engine {engineid} -key {keyid} -keyform ENGINE This latter form is recognised internally, and rewritten into the URI form. Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com> (Merged from https://github.com/openssl/openssl/pull/13570)
This commit is contained in:
parent
4be35545ae
commit
0b27381fd5
|
@ -36,6 +36,7 @@
|
||||||
# include "opt.h"
|
# include "opt.h"
|
||||||
# include "fmt.h"
|
# include "fmt.h"
|
||||||
# include "platform.h"
|
# include "platform.h"
|
||||||
|
# include "engine_loader.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* quick macro when you need to pass an unsigned char instead of a char.
|
* quick macro when you need to pass an unsigned char instead of a char.
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
#ifndef HEADER_ENGINE_LOADER_H
|
||||||
|
# define HEADER_ENGINE_LOADER_H
|
||||||
|
|
||||||
|
# include <openssl/store.h>
|
||||||
|
|
||||||
|
/* this is a private URI scheme */
|
||||||
|
# define ENGINE_SCHEME "org.openssl.engine"
|
||||||
|
# define ENGINE_SCHEME_COLON (ENGINE_SCHEME ":")
|
||||||
|
|
||||||
|
int setup_engine_loader(void);
|
||||||
|
void destroy_engine_loader(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -39,6 +39,8 @@
|
||||||
#endif
|
#endif
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/store.h>
|
||||||
|
#include "s_apps.h"
|
||||||
#include "apps.h"
|
#include "apps.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
|
@ -10,7 +10,7 @@ ENDIF
|
||||||
# Source for libapps
|
# Source for libapps
|
||||||
$LIBAPPSSRC=apps.c apps_ui.c opt.c fmt.c s_cb.c s_socket.c app_rand.c \
|
$LIBAPPSSRC=apps.c apps_ui.c opt.c fmt.c s_cb.c s_socket.c app_rand.c \
|
||||||
columns.c app_params.c names.c app_provider.c app_x509.c http_server.c \
|
columns.c app_params.c names.c app_provider.c app_x509.c http_server.c \
|
||||||
engine.c
|
engine.c engine_loader.c
|
||||||
|
|
||||||
IF[{- !$disabled{apps} -}]
|
IF[{- !$disabled{apps} -}]
|
||||||
LIBS{noinst}=../libapps.a
|
LIBS{noinst}=../libapps.a
|
||||||
|
|
|
@ -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
|
|
@ -68,6 +68,7 @@ static int apps_startup(void)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
(void)setup_ui_method();
|
(void)setup_ui_method();
|
||||||
|
(void)setup_engine_loader();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: This is an undocumented feature required for testing only.
|
* NOTE: This is an undocumented feature required for testing only.
|
||||||
|
@ -89,6 +90,7 @@ static void apps_shutdown(void)
|
||||||
{
|
{
|
||||||
app_providers_cleanup();
|
app_providers_cleanup();
|
||||||
OSSL_LIB_CTX_free(app_get0_libctx());
|
OSSL_LIB_CTX_free(app_get0_libctx());
|
||||||
|
destroy_engine_loader();
|
||||||
destroy_ui_method();
|
destroy_ui_method();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue