summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/encode_decode/decoder_lib.c85
-rw-r--r--crypto/encode_decode/decoder_meth.c15
-rw-r--r--crypto/encode_decode/decoder_pkey.c41
-rw-r--r--crypto/err/openssl.txt4
-rw-r--r--crypto/provider_core.c1
-rw-r--r--include/crypto/decoder.h40
-rw-r--r--include/openssl/core_dispatch.h3
-rw-r--r--include/openssl/err.h5
-rw-r--r--providers/baseprov.c11
-rw-r--r--providers/common/bio_prov.c16
-rw-r--r--providers/common/include/prov/bio.h1
-rw-r--r--providers/common/include/prov/providercommonerr.h3
-rw-r--r--providers/common/provider_err.c6
-rw-r--r--providers/defltprov.c11
-rw-r--r--providers/implementations/build.info2
-rw-r--r--providers/implementations/include/prov/implementations.h2
-rw-r--r--providers/implementations/storemgmt/build.info6
-rw-r--r--providers/implementations/storemgmt/file_store.c920
-rw-r--r--providers/implementations/storemgmt/file_store_der2obj.c119
-rw-r--r--providers/implementations/storemgmt/file_store_local.h11
-rw-r--r--providers/stores.inc14
21 files changed, 1266 insertions, 50 deletions
diff --git a/crypto/encode_decode/decoder_lib.c b/crypto/encode_decode/decoder_lib.c
index 17dca0fc22..9eeff20f7c 100644
--- a/crypto/encode_decode/decoder_lib.c
+++ b/crypto/encode_decode/decoder_lib.c
@@ -12,6 +12,7 @@
#include <openssl/params.h>
#include <openssl/provider.h>
#include "internal/passphrase.h"
+#include "crypto/decoder.h"
#include "encoder_local.h"
#include "e_os.h"
@@ -89,14 +90,13 @@ int OSSL_DECODER_CTX_set_input_type(OSSL_DECODER_CTX *ctx,
return 1;
}
-int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder)
+OSSL_DECODER_INSTANCE *ossl_decoder_instance_new(OSSL_DECODER *decoder,
+ void *decoderctx)
{
OSSL_DECODER_INSTANCE *decoder_inst = NULL;
- const OSSL_PROVIDER *prov = NULL;
OSSL_PARAM params[2];
- void *provctx = NULL;
- if (!ossl_assert(ctx != NULL) || !ossl_assert(decoder != NULL)) {
+ if (!ossl_assert(decoder != NULL)) {
ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
@@ -107,12 +107,6 @@ int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder)
return 0;
}
- if (ctx->decoder_insts == NULL
- && (ctx->decoder_insts =
- sk_OSSL_DECODER_INSTANCE_new_null()) == NULL) {
- ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
- return 0;
- }
if ((decoder_inst = OPENSSL_zalloc(sizeof(*decoder_inst))) == NULL) {
ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
return 0;
@@ -121,10 +115,6 @@ int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder)
ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR);
goto err;
}
- decoder_inst->decoder = decoder;
-
- prov = OSSL_DECODER_provider(decoder_inst->decoder);
- provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
/* Cache the input type for this encoder */
params[0] =
@@ -132,25 +122,74 @@ int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder)
(char **)&decoder_inst->input_type, 0);
params[1] = OSSL_PARAM_construct_end();
- if (!decoder_inst->decoder->get_params(params)
+ if (!decoder->get_params(params)
|| !OSSL_PARAM_modified(&params[0]))
goto err;
- if ((decoder_inst->decoderctx = decoder_inst->decoder->newctx(provctx))
- == NULL)
- goto err;
-
- if (sk_OSSL_DECODER_INSTANCE_push(ctx->decoder_insts, decoder_inst) <= 0)
- goto err;
-
- return 1;
+ decoder_inst->decoder = decoder;
+ decoder_inst->decoderctx = decoderctx;
+ return decoder_inst;
err:
+ ossl_decoder_instance_free(decoder_inst);
+ return NULL;
+}
+
+void ossl_decoder_instance_free(OSSL_DECODER_INSTANCE *decoder_inst)
+{
if (decoder_inst != NULL) {
if (decoder_inst->decoder != NULL)
decoder_inst->decoder->freectx(decoder_inst->decoderctx);
+ decoder_inst->decoderctx = NULL;
OSSL_DECODER_free(decoder_inst->decoder);
+ decoder_inst->decoder = NULL;
OPENSSL_free(decoder_inst);
}
+}
+
+int ossl_decoder_ctx_add_decoder_inst(OSSL_DECODER_CTX *ctx,
+ OSSL_DECODER_INSTANCE *di)
+{
+ if (ctx->decoder_insts == NULL
+ && (ctx->decoder_insts =
+ sk_OSSL_DECODER_INSTANCE_new_null()) == NULL) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ return (sk_OSSL_DECODER_INSTANCE_push(ctx->decoder_insts, di) > 0);
+}
+
+int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx,
+ OSSL_DECODER *decoder)
+{
+ OSSL_DECODER_INSTANCE *decoder_inst = NULL;
+ const OSSL_PROVIDER *prov = NULL;
+ void *decoderctx = NULL;
+ void *provctx = NULL;
+
+ if (!ossl_assert(ctx != NULL) || !ossl_assert(decoder != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ prov = OSSL_DECODER_provider(decoder);
+ provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
+
+ if ((decoderctx = decoder->newctx(provctx)) == NULL
+ || (decoder_inst =
+ ossl_decoder_instance_new(decoder, decoderctx)) == NULL)
+ goto err;
+ /* Avoid double free of decoderctx on further errors */
+ decoderctx = NULL;
+
+ if (!ossl_decoder_ctx_add_decoder_inst(ctx, decoder_inst))
+ goto err;
+
+ return 1;
+ err:
+ ossl_decoder_instance_free(decoder_inst);
+ if (decoderctx != NULL)
+ decoder->freectx(decoderctx);
return 0;
}
diff --git a/crypto/encode_decode/decoder_meth.c b/crypto/encode_decode/decoder_meth.c
index 21cd53e32b..235899b6ce 100644
--- a/crypto/encode_decode/decoder_meth.c
+++ b/crypto/encode_decode/decoder_meth.c
@@ -15,11 +15,9 @@
#include "internal/namemap.h"
#include "internal/property.h"
#include "internal/provider.h"
-#include "crypto/encoder.h"
+#include "crypto/decoder.h"
#include "encoder_local.h"
-static void OSSL_DECODER_INSTANCE_free(OSSL_DECODER_INSTANCE *instance);
-
/*
* Decoder can have multiple names, separated with colons in a name string
*/
@@ -159,8 +157,8 @@ static int put_decoder_in_store(OPENSSL_CTX *libctx, void *store,
}
/* Create and populate a decoder method */
-static void *decoder_from_dispatch(int id, const OSSL_ALGORITHM *algodef,
- OSSL_PROVIDER *prov)
+void *ossl_decoder_from_dispatch(int id, const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
{
OSSL_DECODER *decoder = NULL;
const OSSL_DISPATCH *fns = algodef->implementation;
@@ -236,7 +234,7 @@ static void *decoder_from_dispatch(int id, const OSSL_ALGORITHM *algodef,
/*
* The core fetching functionality passes the names of the implementation.
* This function is responsible to getting an identity number for them,
- * then call decoder_from_dispatch() with that identity number.
+ * then call ossl_decoder_from_dispatch() with that identity number.
*/
static void *construct_decoder(const OSSL_ALGORITHM *algodef,
OSSL_PROVIDER *prov, void *unused)
@@ -254,7 +252,7 @@ static void *construct_decoder(const OSSL_ALGORITHM *algodef,
void *method = NULL;
if (id != 0)
- method = decoder_from_dispatch(id, algodef, prov);
+ method = ossl_decoder_from_dispatch(id, algodef, prov);
return method;
}
@@ -407,8 +405,7 @@ static void decoder_do_one(OSSL_PROVIDER *provider,
void *method = NULL;
if (id != 0)
- method =
- decoder_from_dispatch(id, algodef, provider);
+ method = ossl_decoder_from_dispatch(id, algodef, provider);
if (method != NULL) {
data->user_fn(method, data->user_arg);
diff --git a/crypto/encode_decode/decoder_pkey.c b/crypto/encode_decode/decoder_pkey.c
index 11b087203b..64ea4e2c3f 100644
--- a/crypto/encode_decode/decoder_pkey.c
+++ b/crypto/encode_decode/decoder_pkey.c
@@ -14,6 +14,7 @@
#include <openssl/decoder.h>
#include <openssl/safestack.h>
#include "crypto/evp.h"
+#include "crypto/decoder.h"
#include "encoder_local.h"
int OSSL_DECODER_CTX_set_passphrase(OSSL_DECODER_CTX *ctx,
@@ -254,17 +255,16 @@ static void collect_decoder(OSSL_DECODER *decoder, void *arg)
data->error_occured = 0; /* All is good now */
}
-OSSL_DECODER_CTX *OSSL_DECODER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey,
- const char *input_type,
- OPENSSL_CTX *libctx,
- const char *propquery)
+int ossl_decoder_ctx_setup_for_EVP_PKEY(OSSL_DECODER_CTX *ctx,
+ EVP_PKEY **pkey,
+ OPENSSL_CTX *libctx,
+ const char *propquery)
{
- OSSL_DECODER_CTX *ctx = NULL;
struct collected_data_st *data = NULL;
size_t i, end_i;
+ int ok = 0;
- if ((ctx = OSSL_DECODER_CTX_new()) == NULL
- || (data = OPENSSL_zalloc(sizeof(*data))) == NULL
+ if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL
|| (data->process_data =
OPENSSL_zalloc(sizeof(*data->process_data))) == NULL
|| (data->process_data->keymgmts
@@ -275,7 +275,6 @@ OSSL_DECODER_CTX *OSSL_DECODER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey,
}
data->process_data->object = (void **)pkey;
data->ctx = ctx;
- OSSL_DECODER_CTX_set_input_type(ctx, input_type);
/* First, find all keymgmts to form goals */
EVP_KEYMGMT_do_all_provided(libctx, collect_keymgmt, data);
@@ -308,9 +307,6 @@ OSSL_DECODER_CTX *OSSL_DECODER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey,
if (OSSL_DECODER_CTX_num_decoders(ctx) == 0)
goto err;
- /* Finally, collect extra decoders based on what we already have */
- (void)OSSL_DECODER_CTX_add_extra(ctx, libctx, propquery);
-
if (!OSSL_DECODER_CTX_set_construct(ctx, decoder_construct_EVP_PKEY)
|| !OSSL_DECODER_CTX_set_construct_data(ctx, data->process_data)
|| !OSSL_DECODER_CTX_set_cleanup(ctx,
@@ -318,11 +314,32 @@ OSSL_DECODER_CTX *OSSL_DECODER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey,
goto err;
data->process_data = NULL;
+ ok = 1;
err:
if (data != NULL) {
decoder_clean_EVP_PKEY_construct_arg(data->process_data);
sk_OPENSSL_CSTRING_free(data->names);
OPENSSL_free(data);
}
- return ctx;
+ return ok;
+}
+
+OSSL_DECODER_CTX *OSSL_DECODER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey,
+ const char *input_type,
+ OPENSSL_CTX *libctx,
+ const char *propquery)
+{
+ OSSL_DECODER_CTX *ctx = NULL;
+
+ if ((ctx = OSSL_DECODER_CTX_new()) == NULL) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ if (OSSL_DECODER_CTX_set_input_type(ctx, input_type)
+ && ossl_decoder_ctx_setup_for_EVP_PKEY(ctx, pkey, libctx, propquery)
+ && OSSL_DECODER_CTX_add_extra(ctx, libctx, propquery))
+ return ctx;
+
+ OSSL_DECODER_CTX_free(ctx);
+ return NULL;
}
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 643bf6b278..592fb6b50a 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -2936,12 +2936,15 @@ PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:178:\
PROV_R_OUTPUT_BUFFER_TOO_SMALL:106:output buffer too small
PROV_R_PARENT_LOCKING_NOT_ENABLED:182:parent locking not enabled
PROV_R_PARENT_STRENGTH_TOO_WEAK:194:parent strength too weak
+PROV_R_PATH_MUST_BE_ABSOLUTE:219:path must be absolute
PROV_R_PERSONALISATION_STRING_TOO_LONG:195:personalisation string too long
PROV_R_PSS_SALTLEN_TOO_SMALL:172:pss saltlen too small
PROV_R_READ_KEY:159:read key
PROV_R_REQUEST_TOO_LARGE_FOR_DRBG:196:request too large for drbg
PROV_R_REQUIRE_CTR_MODE_CIPHER:206:require ctr mode cipher
PROV_R_RESEED_ERROR:197:reseed error
+PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES:222:\
+ search only supported for directories
PROV_R_SELF_TEST_KAT_FAILURE:215:self test kat failure
PROV_R_SELF_TEST_POST_FAILURE:216:self test post failure
PROV_R_TAG_NOTSET:119:tag notset
@@ -2963,6 +2966,7 @@ PROV_R_UNSUPPORTED_CEK_ALG:145:unsupported cek alg
PROV_R_UNSUPPORTED_KEY_SIZE:153:unsupported key size
PROV_R_UNSUPPORTED_MAC_TYPE:137:unsupported mac type
PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS:152:unsupported number of rounds
+PROV_R_URI_AUTHORITY_UNSUPPORTED:223:uri authority unsupported
PROV_R_VALUE_ERROR:138:value error
PROV_R_WRONG_FINAL_BLOCK_LENGTH:107:wrong final block length
PROV_R_WRONG_OUTPUT_BUFFER_SIZE:139:wrong output buffer size
diff --git a/crypto/provider_core.c b/crypto/provider_core.c
index f282071e2d..754f6df1a4 100644
--- a/crypto/provider_core.c
+++ b/crypto/provider_core.c
@@ -1094,6 +1094,7 @@ static const OSSL_DISPATCH core_dispatch_[] = {
{ OSSL_FUNC_BIO_WRITE_EX, (void (*)(void))BIO_write_ex },
{ OSSL_FUNC_BIO_GETS, (void (*)(void))BIO_gets },
{ OSSL_FUNC_BIO_PUTS, (void (*)(void))BIO_puts },
+ { OSSL_FUNC_BIO_CTRL, (void (*)(void))BIO_ctrl },
{ OSSL_FUNC_BIO_FREE, (void (*)(void))BIO_free },
{ OSSL_FUNC_BIO_VPRINTF, (void (*)(void))BIO_vprintf },
{ OSSL_FUNC_BIO_VSNPRINTF, (void (*)(void))BIO_vsnprintf },
diff --git a/include/crypto/decoder.h b/include/crypto/decoder.h
new file mode 100644
index 0000000000..b465752971
--- /dev/null
+++ b/include/crypto/decoder.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 OSSL_CRYPTO_DECODER_H
+# define OSSL_CRYPTO_DECODER_H
+
+# include <openssl/decoder.h>
+
+OSSL_DECODER *ossl_decoder_fetch_by_number(OPENSSL_CTX *libctx,
+ int id,
+ const char *properties);
+
+/*
+ * These are specially made for the 'file:' provider-native loader, which
+ * uses this to install a DER to anything decoder, which doesn't do much
+ * except read a DER blob and pass it on as a provider object abstraction
+ * (provider-object(7)).
+ */
+void *ossl_decoder_from_dispatch(int id, const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov);
+
+OSSL_DECODER_INSTANCE *
+ossl_decoder_instance_new(OSSL_DECODER *decoder, void *decoderctx);
+void ossl_decoder_instance_free(OSSL_DECODER_INSTANCE *decoder_inst);
+int ossl_decoder_ctx_add_decoder_inst(OSSL_DECODER_CTX *ctx,
+ OSSL_DECODER_INSTANCE *di);
+
+int ossl_decoder_ctx_setup_for_EVP_PKEY(OSSL_DECODER_CTX *ctx,
+ EVP_PKEY **pkey,
+ OPENSSL_CTX *libctx,
+ const char *propquery);
+
+#endif
+
diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h
index b21fe559f7..ac83f88cc4 100644
--- a/include/openssl/core_dispatch.h
+++ b/include/openssl/core_dispatch.h
@@ -137,6 +137,7 @@ OSSL_CORE_MAKE_FUNC(void,
#define OSSL_FUNC_BIO_VSNPRINTF 46
#define OSSL_FUNC_BIO_PUTS 47
#define OSSL_FUNC_BIO_GETS 48
+#define OSSL_FUNC_BIO_CTRL 49
OSSL_CORE_MAKE_FUNC(OSSL_CORE_BIO *, BIO_new_file, (const char *filename,
@@ -153,6 +154,8 @@ OSSL_CORE_MAKE_FUNC(int, BIO_vprintf, (OSSL_CORE_BIO *bio, const char *format,
va_list args))
OSSL_CORE_MAKE_FUNC(int, BIO_vsnprintf,
(char *buf, size_t n, const char *fmt, va_list args))
+OSSL_CORE_MAKE_FUNC(int, BIO_ctrl, (OSSL_CORE_BIO *bio,
+ int cmd, long num, void *ptr))
#define OSSL_FUNC_SELF_TEST_CB 100
OSSL_CORE_MAKE_FUNC(void, self_test_cb, (OPENSSL_CORE_CTX *ctx, OSSL_CALLBACK **cb,
diff --git a/include/openssl/err.h b/include/openssl/err.h
index 497436d2c5..3e3b64b158 100644
--- a/include/openssl/err.h
+++ b/include/openssl/err.h
@@ -113,8 +113,8 @@ struct err_state_st {
# define ERR_LIB_CRMF 56
# define ERR_LIB_PROV 57
# define ERR_LIB_CMP 58
-# define ERR_LIB_OSSL_ENCODER 59
-# define ERR_LIB_OSSL_DECODER 60
+# define ERR_LIB_OSSL_ENCODER 59
+# define ERR_LIB_OSSL_DECODER 60
# define ERR_LIB_HTTP 61
# define ERR_LIB_USER 128
@@ -304,6 +304,7 @@ static ossl_inline int ERR_FATAL_ERROR(unsigned long errcode)
# define ERR_R_UI_LIB ERR_LIB_UI/* 40 */
# define ERR_R_ECDSA_LIB ERR_LIB_ECDSA/* 42 */
# define ERR_R_OSSL_STORE_LIB ERR_LIB_OSSL_STORE/* 44 */
+# define ERR_R_OSSL_DECODER_LIB ERR_LIB_OSSL_DECODER/* 60 */
/*
* global reason codes, range 64..99 (sub-system specific codes start at 100)
diff --git a/providers/baseprov.c b/providers/baseprov.c
index dcea2ad93e..38d9090bb3 100644
--- a/providers/baseprov.c
+++ b/providers/baseprov.c
@@ -86,6 +86,15 @@ static const OSSL_ALGORITHM base_decoder[] = {
};
#undef DECODER
+static const OSSL_ALGORITHM base_store[] = {
+#define STORE(name, fips, func_table) \
+ { name, "provider=base,fips=" fips, (func_table) },
+
+#include "stores.inc"
+ { NULL, NULL, NULL }
+#undef STORE
+};
+
static const OSSL_ALGORITHM *base_query(void *provctx, int operation_id,
int *no_cache)
{
@@ -95,6 +104,8 @@ static const OSSL_ALGORITHM *base_query(void *provctx, int operation_id,
return base_encoder;
case OSSL_OP_DECODER:
return base_decoder;
+ case OSSL_OP_STORE:
+ return base_store;
}
return NULL;
}
diff --git a/providers/common/bio_prov.c b/providers/common/bio_prov.c
index fc1f8b2b26..c049795cd1 100644
--- a/providers/common/bio_prov.c
+++ b/providers/common/bio_prov.c
@@ -18,6 +18,7 @@ static OSSL_FUNC_BIO_read_ex_fn *c_bio_read_ex = NULL;
static OSSL_FUNC_BIO_write_ex_fn *c_bio_write_ex = NULL;
static OSSL_FUNC_BIO_gets_fn *c_bio_gets = NULL;
static OSSL_FUNC_BIO_puts_fn *c_bio_puts = NULL;
+static OSSL_FUNC_BIO_ctrl_fn *c_bio_ctrl = NULL;
static OSSL_FUNC_BIO_free_fn *c_bio_free = NULL;
static OSSL_FUNC_BIO_vprintf_fn *c_bio_vprintf = NULL;
@@ -49,6 +50,10 @@ int ossl_prov_bio_from_dispatch(const OSSL_DISPATCH *fns)
if (c_bio_puts == NULL)
c_bio_puts = OSSL_FUNC_BIO_puts(fns);
break;
+ case OSSL_FUNC_BIO_CTRL:
+ if (c_bio_ctrl == NULL)
+ c_bio_ctrl = OSSL_FUNC_BIO_ctrl(fns);
+ break;
case OSSL_FUNC_BIO_FREE:
if (c_bio_free == NULL)
c_bio_free = OSSL_FUNC_BIO_free(fns);
@@ -107,6 +112,13 @@ int ossl_prov_bio_puts(OSSL_CORE_BIO *bio, const char *str)
return c_bio_puts(bio, str);
}
+int ossl_prov_bio_ctrl(OSSL_CORE_BIO *bio, int cmd, long num, void *ptr)
+{
+ if (c_bio_ctrl == NULL)
+ return -1;
+ return c_bio_ctrl(bio, cmd, num, ptr);
+}
+
int ossl_prov_bio_free(OSSL_CORE_BIO *bio)
{
if (c_bio_free == NULL)
@@ -151,9 +163,7 @@ static int bio_core_write_ex(BIO *bio, const char *data, size_t data_len,
static long bio_core_ctrl(BIO *bio, int cmd, long num, void *ptr)
{
- /* We don't support this */
- assert(0);
- return 0;
+ return ossl_prov_bio_ctrl(BIO_get_data(bio), cmd, num, ptr);
}
static int bio_core_gets(BIO *bio, char *buf, int size)
diff --git a/providers/common/include/prov/bio.h b/providers/common/include/prov/bio.h
index 3cef89ce18..9dd9f44bad 100644
--- a/providers/common/include/prov/bio.h
+++ b/providers/common/include/prov/bio.h
@@ -22,6 +22,7 @@ int ossl_prov_bio_write_ex(OSSL_CORE_BIO *bio, const void *data, size_t data_len
size_t *written);
int ossl_prov_bio_gets(OSSL_CORE_BIO *bio, char *buf, int size);
int ossl_prov_bio_puts(OSSL_CORE_BIO *bio, const char *str);
+int ossl_prov_bio_ctrl(OSSL_CORE_BIO *bio, int cmd, long num, void *ptr);
int ossl_prov_bio_free(OSSL_CORE_BIO *bio);
int ossl_prov_bio_vprintf(OSSL_CORE_BIO *bio, const char *format, va_list ap);
int ossl_prov_bio_printf(OSSL_CORE_BIO *bio, const char *format, ...);
diff --git a/providers/common/include/prov/providercommonerr.h b/providers/common/include/prov/providercommonerr.h
index 4c356fc5c6..82eea21049 100644
--- a/providers/common/include/prov/providercommonerr.h
+++ b/providers/common/include/prov/providercommonerr.h
@@ -139,12 +139,14 @@ int ERR_load_PROV_strings(void);
# define PROV_R_OUTPUT_BUFFER_TOO_SMALL 106
# define PROV_R_PARENT_LOCKING_NOT_ENABLED 182
# define PROV_R_PARENT_STRENGTH_TOO_WEAK 194
+# define PROV_R_PATH_MUST_BE_ABSOLUTE 219
# define PROV_R_PERSONALISATION_STRING_TOO_LONG 195
# define PROV_R_PSS_SALTLEN_TOO_SMALL 172
# define PROV_R_READ_KEY 159
# define PROV_R_REQUEST_TOO_LARGE_FOR_DRBG 196
# define PROV_R_REQUIRE_CTR_MODE_CIPHER 206
# define PROV_R_RESEED_ERROR 197
+# define PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES 222
# define PROV_R_SELF_TEST_KAT_FAILURE 215
# define PROV_R_SELF_TEST_POST_FAILURE 216
# define PROV_R_TAG_NOTSET 119
@@ -165,6 +167,7 @@ int ERR_load_PROV_strings(void);
# define PROV_R_UNSUPPORTED_KEY_SIZE 153
# define PROV_R_UNSUPPORTED_MAC_TYPE 137
# define PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS 152
+# define PROV_R_URI_AUTHORITY_UNSUPPORTED 223
# define PROV_R_VALUE_ERROR 138
# define PROV_R_WRONG_FINAL_BLOCK_LENGTH 107
# define PROV_R_WRONG_OUTPUT_BUFFER_SIZE 139
diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c
index 3ea41f3c25..6d6a254dd6 100644
--- a/providers/common/provider_err.c
+++ b/providers/common/provider_err.c
@@ -149,6 +149,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
"parent locking not enabled"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PARENT_STRENGTH_TOO_WEAK),
"parent strength too weak"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PATH_MUST_BE_ABSOLUTE),
+ "path must be absolute"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PERSONALISATION_STRING_TOO_LONG),
"personalisation string too long"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PSS_SALTLEN_TOO_SMALL),
@@ -159,6 +161,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_REQUIRE_CTR_MODE_CIPHER),
"require ctr mode cipher"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_RESEED_ERROR), "reseed error"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES),
+ "search only supported for directories"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_SELF_TEST_KAT_FAILURE),
"self test kat failure"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_SELF_TEST_POST_FAILURE),
@@ -196,6 +200,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
"unsupported mac type"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS),
"unsupported number of rounds"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_URI_AUTHORITY_UNSUPPORTED),
+ "uri authority unsupported"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_VALUE_ERROR), "value error"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_WRONG_FINAL_BLOCK_LENGTH),
"wrong final block length"},
diff --git a/providers/defltprov.c b/providers/defltprov.c
index 855497be06..beaf60bb1e 100644
--- a/providers/defltprov.c
+++ b/providers/defltprov.c
@@ -433,6 +433,15 @@ static const OSSL_ALGORITHM deflt_decoder[] = {
};
#undef DECODER
+static const OSSL_ALGORITHM deflt_store[] = {
+#define STORE(name, fips, func_table) \
+ { name, "provider=default,fips=" fips, (func_table) },
+
+#include "stores.inc"
+ { NULL, NULL, NULL }
+#undef STORE
+};
+
static const OSSL_ALGORITHM *deflt_query(void *provctx, int operation_id,
int *no_cache)
{
@@ -461,6 +470,8 @@ static const OSSL_ALGORITHM *deflt_query(void *provctx, int operation_id,
return deflt_encoder;
case OSSL_OP_DECODER:
return deflt_decoder;
+ case OSSL_OP_STORE:
+ return deflt_store;
}
return NULL;
}
diff --git a/providers/implementations/build.info b/providers/implementations/build.info
index 54392cf68b..fe67e59401 100644
--- a/providers/implementations/build.info
+++ b/providers/implementations/build.info
@@ -1,2 +1,2 @@
SUBDIRS=digests ciphers rands macs kdfs exchange keymgmt signature asymciphers \
- encode_decode
+ encode_decode storemgmt
diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h
index 1b8642415f..7060a4b839 100644
--- a/providers/implementations/include/prov/implementations.h
+++ b/providers/implementations/include/prov/implementations.h
@@ -385,3 +385,5 @@ extern const OSSL_DISPATCH der_to_rsapss_decoder_functions[];
extern const OSSL_DISPATCH msblob_to_rsa_decoder_functions[];
extern const OSSL_DISPATCH pvk_to_rsa_decoder_functions[];
extern const OSSL_DISPATCH pem_to_der_decoder_functions[];
+
+extern const OSSL_DISPATCH file_store_functions[];
diff --git a/providers/implementations/storemgmt/build.info b/providers/implementations/storemgmt/build.info
new file mode 100644
index 0000000000..89939cce54
--- /dev/null
+++ b/providers/implementations/storemgmt/build.info
@@ -0,0 +1,6 @@
+# We make separate GOAL variables for each algorithm, to make it easy to
+# switch each to the Legacy provider when needed.
+
+$STORE_GOAL=../../libimplementations.a
+
+SOURCE[$STORE_GOAL]=file_store.c file_store_der2obj.c
diff --git a/providers/implementations/storemgmt/file_store.c b/providers/implementations/storemgmt/file_store.c
new file mode 100644
index 0000000000..70dbac600b
--- /dev/null
+++ b/providers/implementations/storemgmt/file_store.c
@@ -0,0 +1,920 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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
+ */
+
+#include "e_os.h" /* To get strncasecmp() on Windows */
+#include <string.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/core_object.h>
+#include <openssl/crypto.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/buffer.h>
+#include <openssl/params.h>
+#include <openssl/decoder.h>
+#include <openssl/store.h> /* The OSSL_STORE_INFO type numbers */
+#include "internal/o_dir.h"
+#include "internal/pem.h" /* For PVK and "blob" PEM headers */
+#include "crypto/decoder.h"
+#include "prov/implementations.h"
+#include "prov/bio.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommonerr.h"
+#include "file_store_local.h"
+
+DEFINE_STACK_OF(X509)
+DEFINE_STACK_OF(OSSL_STORE_INFO)
+
+#ifdef _WIN32
+# define stat _stat
+#endif
+
+#ifndef S_ISDIR
+# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
+#endif
+
+static OSSL_FUNC_store_open_fn file_open;
+static OSSL_FUNC_store_attach_fn file_attach;
+static OSSL_FUNC_store_settable_ctx_params_fn file_settable_ctx_params;
+static OSSL_FUNC_store_set_ctx_params_fn file_set_ctx_params;
+static OSSL_FUNC_store_load_fn file_load;
+static OSSL_FUNC_store_eof_fn file_eof;
+static OSSL_FUNC_store_close_fn file_close;
+
+/*
+ * This implementation makes full use of OSSL_DECODER, and then some.
+ * It uses its own internal decoder implementation that reads DER and
+ * passes that on to the data callback; this decoder is created with
+ * internal OpenSSL functions, thereby bypassing the need for a surrounding
+ * provider. This is ok, since this is a local decoder, not meant for
+ * public consumption. It also uses the libcrypto internal decoder
+ * setup function ossl_decoder_ctx_setup_for_EVP_PKEY(), to allow the
+ * last resort decoder to be added first (and thereby be executed last).
+ * Finally, it sets up its own construct and cleanup functions.
+ *
+ * Essentially, that makes this implementation a kind of glorified decoder.
+ */
+
+struct file_ctx_st {
+ void *provctx;
+ char *uri; /* The URI we currently try to load */
+ enum {
+ IS_FILE = 0, /* Read file and pass results */
+ IS_DIR /* Pass directory entry names */
+ } type;
+
+ /* Flag bits */
+ unsigned int flag_attached:1;
+ unsigned int flag_buffered:1;
+
+ union {
+ /* Used with |IS_FILE| */
+ struct {
+ BIO *file;
+
+ OSSL_DECODER_CTX *decoderctx;
+ char *input_type;
+ char *propq; /* The properties we got as a parameter */
+ } file;
+
+ /* Used with |IS_DIR| */
+ struct {
+ OPENSSL_DIR_CTX *ctx;
+ int end_reached;
+
+ /*
+ * When a search expression is given, these are filled in.
+ * |search_name| contains the file basename to look for.
+ * The string is exactly 8 characters long.
+ */
+ char search_name[9];
+
+ /*
+ * The directory reading utility we have combines opening with
+ * reading the first name. To make sure we can detect the end
+ * at the right time, we read early and cache the name.
+ */
+ const char *last_entry;
+ int last_errno;
+ } dir;
+ } _;
+
+ /* Expected object type. May be unspecified */
+ int expected_type;
+};
+
+static void free_file_ctx(struct file_ctx_st *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ OPENSSL_free(ctx->uri);
+ if (ctx->type != IS_DIR) {
+ OSSL_DECODER_CTX_free(ctx->_.file.decoderctx);
+ OPENSSL_free(ctx->_.file.propq);
+ OPENSSL_free(ctx->_.file.input_type);
+ }
+ OPENSSL_free(ctx);
+}