1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* 11e1051a39Sopenharmony_ci * Here is an STORE loader for ENGINE backed keys. It relies on deprecated 12e1051a39Sopenharmony_ci * functions, and therefore need to have deprecation warnings suppressed. 13e1051a39Sopenharmony_ci * This file is not compiled at all in a '--api=3 no-deprecated' configuration. 14e1051a39Sopenharmony_ci */ 15e1051a39Sopenharmony_ci#define OPENSSL_SUPPRESS_DEPRECATED 16e1051a39Sopenharmony_ci 17e1051a39Sopenharmony_ci#include "apps.h" 18e1051a39Sopenharmony_ci 19e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE 20e1051a39Sopenharmony_ci 21e1051a39Sopenharmony_ci# include <stdarg.h> 22e1051a39Sopenharmony_ci# include <string.h> 23e1051a39Sopenharmony_ci# include <openssl/engine.h> 24e1051a39Sopenharmony_ci# include <openssl/store.h> 25e1051a39Sopenharmony_ci 26e1051a39Sopenharmony_ci/* 27e1051a39Sopenharmony_ci * Support for legacy private engine keys via the 'org.openssl.engine:' scheme 28e1051a39Sopenharmony_ci * 29e1051a39Sopenharmony_ci * org.openssl.engine:{engineid}:{keyid} 30e1051a39Sopenharmony_ci * 31e1051a39Sopenharmony_ci * Note: we ONLY support ENGINE_load_private_key() and ENGINE_load_public_key() 32e1051a39Sopenharmony_ci * Note 2: This scheme has a precedent in code in PKIX-SSH. for exactly 33e1051a39Sopenharmony_ci * this sort of purpose. 34e1051a39Sopenharmony_ci */ 35e1051a39Sopenharmony_ci 36e1051a39Sopenharmony_ci/* Local definition of OSSL_STORE_LOADER_CTX */ 37e1051a39Sopenharmony_cistruct ossl_store_loader_ctx_st { 38e1051a39Sopenharmony_ci ENGINE *e; /* Structural reference */ 39e1051a39Sopenharmony_ci char *keyid; 40e1051a39Sopenharmony_ci int expected; 41e1051a39Sopenharmony_ci int loaded; /* 0 = key not loaded yet, 1 = key loaded */ 42e1051a39Sopenharmony_ci}; 43e1051a39Sopenharmony_ci 44e1051a39Sopenharmony_cistatic OSSL_STORE_LOADER_CTX *OSSL_STORE_LOADER_CTX_new(ENGINE *e, char *keyid) 45e1051a39Sopenharmony_ci{ 46e1051a39Sopenharmony_ci OSSL_STORE_LOADER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_ci if (ctx != NULL) { 49e1051a39Sopenharmony_ci ctx->e = e; 50e1051a39Sopenharmony_ci ctx->keyid = keyid; 51e1051a39Sopenharmony_ci } 52e1051a39Sopenharmony_ci return ctx; 53e1051a39Sopenharmony_ci} 54e1051a39Sopenharmony_ci 55e1051a39Sopenharmony_cistatic void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx) 56e1051a39Sopenharmony_ci{ 57e1051a39Sopenharmony_ci if (ctx != NULL) { 58e1051a39Sopenharmony_ci ENGINE_free(ctx->e); 59e1051a39Sopenharmony_ci OPENSSL_free(ctx->keyid); 60e1051a39Sopenharmony_ci OPENSSL_free(ctx); 61e1051a39Sopenharmony_ci } 62e1051a39Sopenharmony_ci} 63e1051a39Sopenharmony_ci 64e1051a39Sopenharmony_cistatic OSSL_STORE_LOADER_CTX *engine_open(const OSSL_STORE_LOADER *loader, 65e1051a39Sopenharmony_ci const char *uri, 66e1051a39Sopenharmony_ci const UI_METHOD *ui_method, 67e1051a39Sopenharmony_ci void *ui_data) 68e1051a39Sopenharmony_ci{ 69e1051a39Sopenharmony_ci const char *p = uri, *q; 70e1051a39Sopenharmony_ci ENGINE *e = NULL; 71e1051a39Sopenharmony_ci char *keyid = NULL; 72e1051a39Sopenharmony_ci OSSL_STORE_LOADER_CTX *ctx = NULL; 73e1051a39Sopenharmony_ci 74e1051a39Sopenharmony_ci if (OPENSSL_strncasecmp(p, ENGINE_SCHEME_COLON, sizeof(ENGINE_SCHEME_COLON) - 1) 75e1051a39Sopenharmony_ci != 0) 76e1051a39Sopenharmony_ci return NULL; 77e1051a39Sopenharmony_ci p += sizeof(ENGINE_SCHEME_COLON) - 1; 78e1051a39Sopenharmony_ci 79e1051a39Sopenharmony_ci /* Look for engine ID */ 80e1051a39Sopenharmony_ci q = strchr(p, ':'); 81e1051a39Sopenharmony_ci if (q != NULL /* There is both an engine ID and a key ID */ 82e1051a39Sopenharmony_ci && p[0] != ':' /* The engine ID is at least one character */ 83e1051a39Sopenharmony_ci && q[1] != '\0') { /* The key ID is at least one character */ 84e1051a39Sopenharmony_ci char engineid[256]; 85e1051a39Sopenharmony_ci size_t engineid_l = q - p; 86e1051a39Sopenharmony_ci 87e1051a39Sopenharmony_ci strncpy(engineid, p, engineid_l); 88e1051a39Sopenharmony_ci engineid[engineid_l] = '\0'; 89e1051a39Sopenharmony_ci e = ENGINE_by_id(engineid); 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_ci keyid = OPENSSL_strdup(q + 1); 92e1051a39Sopenharmony_ci } 93e1051a39Sopenharmony_ci 94e1051a39Sopenharmony_ci if (e != NULL && keyid != NULL) 95e1051a39Sopenharmony_ci ctx = OSSL_STORE_LOADER_CTX_new(e, keyid); 96e1051a39Sopenharmony_ci 97e1051a39Sopenharmony_ci if (ctx == NULL) { 98e1051a39Sopenharmony_ci OPENSSL_free(keyid); 99e1051a39Sopenharmony_ci ENGINE_free(e); 100e1051a39Sopenharmony_ci } 101e1051a39Sopenharmony_ci 102e1051a39Sopenharmony_ci return ctx; 103e1051a39Sopenharmony_ci} 104e1051a39Sopenharmony_ci 105e1051a39Sopenharmony_cistatic int engine_expect(OSSL_STORE_LOADER_CTX *ctx, int expected) 106e1051a39Sopenharmony_ci{ 107e1051a39Sopenharmony_ci if (expected == 0 108e1051a39Sopenharmony_ci || expected == OSSL_STORE_INFO_PUBKEY 109e1051a39Sopenharmony_ci || expected == OSSL_STORE_INFO_PKEY) { 110e1051a39Sopenharmony_ci ctx->expected = expected; 111e1051a39Sopenharmony_ci return 1; 112e1051a39Sopenharmony_ci } 113e1051a39Sopenharmony_ci return 0; 114e1051a39Sopenharmony_ci} 115e1051a39Sopenharmony_ci 116e1051a39Sopenharmony_cistatic OSSL_STORE_INFO *engine_load(OSSL_STORE_LOADER_CTX *ctx, 117e1051a39Sopenharmony_ci const UI_METHOD *ui_method, void *ui_data) 118e1051a39Sopenharmony_ci{ 119e1051a39Sopenharmony_ci EVP_PKEY *pkey = NULL, *pubkey = NULL; 120e1051a39Sopenharmony_ci OSSL_STORE_INFO *info = NULL; 121e1051a39Sopenharmony_ci 122e1051a39Sopenharmony_ci if (ctx->loaded == 0) { 123e1051a39Sopenharmony_ci if (ENGINE_init(ctx->e)) { 124e1051a39Sopenharmony_ci if (ctx->expected == 0 125e1051a39Sopenharmony_ci || ctx->expected == OSSL_STORE_INFO_PKEY) 126e1051a39Sopenharmony_ci pkey = 127e1051a39Sopenharmony_ci ENGINE_load_private_key(ctx->e, ctx->keyid, 128e1051a39Sopenharmony_ci (UI_METHOD *)ui_method, ui_data); 129e1051a39Sopenharmony_ci if ((pkey == NULL && ctx->expected == 0) 130e1051a39Sopenharmony_ci || ctx->expected == OSSL_STORE_INFO_PUBKEY) 131e1051a39Sopenharmony_ci pubkey = 132e1051a39Sopenharmony_ci ENGINE_load_public_key(ctx->e, ctx->keyid, 133e1051a39Sopenharmony_ci (UI_METHOD *)ui_method, ui_data); 134e1051a39Sopenharmony_ci ENGINE_finish(ctx->e); 135e1051a39Sopenharmony_ci } 136e1051a39Sopenharmony_ci } 137e1051a39Sopenharmony_ci 138e1051a39Sopenharmony_ci ctx->loaded = 1; 139e1051a39Sopenharmony_ci 140e1051a39Sopenharmony_ci if (pubkey != NULL) 141e1051a39Sopenharmony_ci info = OSSL_STORE_INFO_new_PUBKEY(pubkey); 142e1051a39Sopenharmony_ci else if (pkey != NULL) 143e1051a39Sopenharmony_ci info = OSSL_STORE_INFO_new_PKEY(pkey); 144e1051a39Sopenharmony_ci if (info == NULL) { 145e1051a39Sopenharmony_ci EVP_PKEY_free(pkey); 146e1051a39Sopenharmony_ci EVP_PKEY_free(pubkey); 147e1051a39Sopenharmony_ci } 148e1051a39Sopenharmony_ci return info; 149e1051a39Sopenharmony_ci} 150e1051a39Sopenharmony_ci 151e1051a39Sopenharmony_cistatic int engine_eof(OSSL_STORE_LOADER_CTX *ctx) 152e1051a39Sopenharmony_ci{ 153e1051a39Sopenharmony_ci return ctx->loaded != 0; 154e1051a39Sopenharmony_ci} 155e1051a39Sopenharmony_ci 156e1051a39Sopenharmony_cistatic int engine_error(OSSL_STORE_LOADER_CTX *ctx) 157e1051a39Sopenharmony_ci{ 158e1051a39Sopenharmony_ci return 0; 159e1051a39Sopenharmony_ci} 160e1051a39Sopenharmony_ci 161e1051a39Sopenharmony_cistatic int engine_close(OSSL_STORE_LOADER_CTX *ctx) 162e1051a39Sopenharmony_ci{ 163e1051a39Sopenharmony_ci OSSL_STORE_LOADER_CTX_free(ctx); 164e1051a39Sopenharmony_ci return 1; 165e1051a39Sopenharmony_ci} 166e1051a39Sopenharmony_ci 167e1051a39Sopenharmony_ciint setup_engine_loader(void) 168e1051a39Sopenharmony_ci{ 169e1051a39Sopenharmony_ci OSSL_STORE_LOADER *loader = NULL; 170e1051a39Sopenharmony_ci 171e1051a39Sopenharmony_ci if ((loader = OSSL_STORE_LOADER_new(NULL, ENGINE_SCHEME)) == NULL 172e1051a39Sopenharmony_ci || !OSSL_STORE_LOADER_set_open(loader, engine_open) 173e1051a39Sopenharmony_ci || !OSSL_STORE_LOADER_set_expect(loader, engine_expect) 174e1051a39Sopenharmony_ci || !OSSL_STORE_LOADER_set_load(loader, engine_load) 175e1051a39Sopenharmony_ci || !OSSL_STORE_LOADER_set_eof(loader, engine_eof) 176e1051a39Sopenharmony_ci || !OSSL_STORE_LOADER_set_error(loader, engine_error) 177e1051a39Sopenharmony_ci || !OSSL_STORE_LOADER_set_close(loader, engine_close) 178e1051a39Sopenharmony_ci || !OSSL_STORE_register_loader(loader)) { 179e1051a39Sopenharmony_ci OSSL_STORE_LOADER_free(loader); 180e1051a39Sopenharmony_ci loader = NULL; 181e1051a39Sopenharmony_ci } 182e1051a39Sopenharmony_ci 183e1051a39Sopenharmony_ci return loader != NULL; 184e1051a39Sopenharmony_ci} 185e1051a39Sopenharmony_ci 186e1051a39Sopenharmony_civoid destroy_engine_loader(void) 187e1051a39Sopenharmony_ci{ 188e1051a39Sopenharmony_ci OSSL_STORE_LOADER *loader = OSSL_STORE_unregister_loader(ENGINE_SCHEME); 189e1051a39Sopenharmony_ci OSSL_STORE_LOADER_free(loader); 190e1051a39Sopenharmony_ci} 191e1051a39Sopenharmony_ci 192e1051a39Sopenharmony_ci#else /* !OPENSSL_NO_ENGINE */ 193e1051a39Sopenharmony_ci 194e1051a39Sopenharmony_ciint setup_engine_loader(void) 195e1051a39Sopenharmony_ci{ 196e1051a39Sopenharmony_ci return 0; 197e1051a39Sopenharmony_ci} 198e1051a39Sopenharmony_ci 199e1051a39Sopenharmony_civoid destroy_engine_loader(void) 200e1051a39Sopenharmony_ci{ 201e1051a39Sopenharmony_ci} 202e1051a39Sopenharmony_ci 203e1051a39Sopenharmony_ci#endif 204