Path: blob/main/crypto/openssl/apps/lib/engine_loader.c
34878 views
/*1* Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89/*10* Here is an STORE loader for ENGINE backed keys. It relies on deprecated11* functions, and therefore need to have deprecation warnings suppressed.12* This file is not compiled at all in a '--api=3 no-deprecated' configuration.13*/14#define OPENSSL_SUPPRESS_DEPRECATED1516#include "internal/e_os.h"17#include "apps.h"1819#ifndef OPENSSL_NO_ENGINE2021# include <stdarg.h>22# include <string.h>23# include <openssl/engine.h>24# include <openssl/store.h>2526/*27* Support for legacy private engine keys via the 'org.openssl.engine:' scheme28*29* org.openssl.engine:{engineid}:{keyid}30*31* Note: we ONLY support ENGINE_load_private_key() and ENGINE_load_public_key()32* Note 2: This scheme has a precedent in code in PKIX-SSH. for exactly33* this sort of purpose.34*/3536/* Local definition of OSSL_STORE_LOADER_CTX */37struct ossl_store_loader_ctx_st {38ENGINE *e; /* Structural reference */39char *keyid;40int expected;41int loaded; /* 0 = key not loaded yet, 1 = key loaded */42};4344static OSSL_STORE_LOADER_CTX *OSSL_STORE_LOADER_CTX_new(ENGINE *e, char *keyid)45{46OSSL_STORE_LOADER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));4748if (ctx != NULL) {49ctx->e = e;50ctx->keyid = keyid;51}52return ctx;53}5455static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx)56{57if (ctx != NULL) {58ENGINE_free(ctx->e);59OPENSSL_free(ctx->keyid);60OPENSSL_free(ctx);61}62}6364static OSSL_STORE_LOADER_CTX *engine_open(const OSSL_STORE_LOADER *loader,65const char *uri,66const UI_METHOD *ui_method,67void *ui_data)68{69const char *p = uri, *q;70ENGINE *e = NULL;71char *keyid = NULL;72OSSL_STORE_LOADER_CTX *ctx = NULL;7374if (!CHECK_AND_SKIP_CASE_PREFIX(p, ENGINE_SCHEME_COLON))75return NULL;7677/* Look for engine ID */78q = strchr(p, ':');79if (q != NULL /* There is both an engine ID and a key ID */80&& p[0] != ':' /* The engine ID is at least one character */81&& q[1] != '\0') { /* The key ID is at least one character */82char engineid[256];83size_t engineid_l = q - p;8485strncpy(engineid, p, engineid_l);86engineid[engineid_l] = '\0';87e = ENGINE_by_id(engineid);8889keyid = OPENSSL_strdup(q + 1);90}9192if (e != NULL && keyid != NULL)93ctx = OSSL_STORE_LOADER_CTX_new(e, keyid);9495if (ctx == NULL) {96OPENSSL_free(keyid);97ENGINE_free(e);98}99100return ctx;101}102103static int engine_expect(OSSL_STORE_LOADER_CTX *ctx, int expected)104{105if (expected == 0106|| expected == OSSL_STORE_INFO_PUBKEY107|| expected == OSSL_STORE_INFO_PKEY) {108ctx->expected = expected;109return 1;110}111return 0;112}113114static OSSL_STORE_INFO *engine_load(OSSL_STORE_LOADER_CTX *ctx,115const UI_METHOD *ui_method, void *ui_data)116{117EVP_PKEY *pkey = NULL, *pubkey = NULL;118OSSL_STORE_INFO *info = NULL;119120if (ctx->loaded == 0) {121if (ENGINE_init(ctx->e)) {122if (ctx->expected == 0123|| ctx->expected == OSSL_STORE_INFO_PKEY)124pkey =125ENGINE_load_private_key(ctx->e, ctx->keyid,126(UI_METHOD *)ui_method, ui_data);127if ((pkey == NULL && ctx->expected == 0)128|| ctx->expected == OSSL_STORE_INFO_PUBKEY)129pubkey =130ENGINE_load_public_key(ctx->e, ctx->keyid,131(UI_METHOD *)ui_method, ui_data);132ENGINE_finish(ctx->e);133}134}135136ctx->loaded = 1;137138if (pubkey != NULL)139info = OSSL_STORE_INFO_new_PUBKEY(pubkey);140else if (pkey != NULL)141info = OSSL_STORE_INFO_new_PKEY(pkey);142if (info == NULL) {143EVP_PKEY_free(pkey);144EVP_PKEY_free(pubkey);145}146return info;147}148149static int engine_eof(OSSL_STORE_LOADER_CTX *ctx)150{151return ctx->loaded != 0;152}153154static int engine_error(OSSL_STORE_LOADER_CTX *ctx)155{156return 0;157}158159static int engine_close(OSSL_STORE_LOADER_CTX *ctx)160{161OSSL_STORE_LOADER_CTX_free(ctx);162return 1;163}164165int setup_engine_loader(void)166{167OSSL_STORE_LOADER *loader = NULL;168169if ((loader = OSSL_STORE_LOADER_new(NULL, ENGINE_SCHEME)) == NULL170|| !OSSL_STORE_LOADER_set_open(loader, engine_open)171|| !OSSL_STORE_LOADER_set_expect(loader, engine_expect)172|| !OSSL_STORE_LOADER_set_load(loader, engine_load)173|| !OSSL_STORE_LOADER_set_eof(loader, engine_eof)174|| !OSSL_STORE_LOADER_set_error(loader, engine_error)175|| !OSSL_STORE_LOADER_set_close(loader, engine_close)176|| !OSSL_STORE_register_loader(loader)) {177OSSL_STORE_LOADER_free(loader);178loader = NULL;179}180181return loader != NULL;182}183184void destroy_engine_loader(void)185{186OSSL_STORE_LOADER *loader = OSSL_STORE_unregister_loader(ENGINE_SCHEME);187OSSL_STORE_LOADER_free(loader);188}189190#else /* !OPENSSL_NO_ENGINE */191192int setup_engine_loader(void)193{194return 0;195}196197void destroy_engine_loader(void)198{199}200201#endif202203204