md2 md4 md5 sha mdc2 hmac ripemd whrlpool poly1305 \
siphash sm3 des aes rc2 rc4 rc5 idea aria bf cast camellia \
seed sm4 chacha modes bn ec rsa dsa dh sm2 dso engine \
- err comp ocsp cms ts srp cmac ct async ess crmf cmp
+ err comp ocsp cms ts srp cmac ct async ess crmf cmp serializer
LIBS=../libcrypto
{ERR_PACK(ERR_LIB_SM2, 0, 0), "SM2 routines"},
{ERR_PACK(ERR_LIB_ESS, 0, 0), "ESS routines"},
{ERR_PACK(ERR_LIB_PROV, 0, 0), "Provider routines"},
+ {ERR_PACK(ERR_LIB_OSSL_SERIALIZER, 0, 0), "SERIALIZER routines"},
{0, NULL},
};
{ERR_R_DISABLED, "called a function that was disabled at compile-time"},
{ERR_R_INIT_FAIL, "init fail"},
{ERR_R_OPERATION_FAIL, "operation fail"},
+ {ERR_R_INVALID_PROVIDER_FUNCTIONS, "invalid provider functions"},
{0, NULL},
};
L ESS include/openssl/ess.h crypto/ess/ess_err.c
L PROP include/internal/property.h crypto/property/property_err.c
L PROV providers/common/include/prov/providercommon.h providers/common/provider_err.c
+L OSSL_SERIALIZER include/openssl/serializer.h crypto/serializer/serializer_err.c
# additional header files to be scanned for function names
L NONE include/openssl/x509_vfy.h NONE
"version", /* Version number of this provider */
"fips", /* FIPS supporting provider */
"engine", /* An old style engine masquerading as a provider */
+ "format", /* output format for serializers */
+ "type", /* output type for serializers */
};
size_t i;
--- /dev/null
+SOURCE[../../libcrypto]=serializer_meth.c
--- /dev/null
+/*
+ * Copyright 2019 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 <openssl/core_numbers.h>
+#include <openssl/types.h>
+#include "internal/cryptlib.h"
+#include "internal/refcount.h"
+
+struct ossl_serializer_st {
+ OSSL_PROVIDER *prov;
+ int id;
+ const char *propdef;
+
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+
+ OSSL_OP_serializer_newctx_fn *newctx;
+ OSSL_OP_serializer_freectx_fn *freectx;
+ OSSL_OP_serializer_set_ctx_params_fn *set_ctx_params;
+ OSSL_OP_serializer_settable_ctx_params_fn *settable_ctx_params;
+ OSSL_OP_serializer_serialize_data_fn *serialize_data;
+ OSSL_OP_serializer_serialize_object_fn *serialize_object;
+};
+
+struct ossl_serializer_ctx_st {
+ OSSL_SERIALIZER *ser;
+ void *serctx;
+};
--- /dev/null
+/*
+ * Copyright 2019 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 <openssl/core.h>
+#include <openssl/core_numbers.h>
+#include <openssl/serializer.h>
+#include "internal/core.h"
+#include "internal/namemap.h"
+#include "internal/property.h"
+#include "internal/provider.h"
+#include "crypto/serializer.h"
+#include "serializer_local.h"
+
+/*
+ * Serializer can have multiple names, separated with colons in a name string
+ */
+#define NAME_SEPARATOR ':'
+
+/* Simple method structure constructor and destructor */
+static OSSL_SERIALIZER *ossl_serializer_new(void)
+{
+ OSSL_SERIALIZER *ser = NULL;
+
+ if ((ser = OPENSSL_zalloc(sizeof(*ser))) == NULL
+ || (ser->lock = CRYPTO_THREAD_lock_new()) == NULL) {
+ OSSL_SERIALIZER_free(ser);
+ ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ ser->refcnt = 1;
+
+ return ser;
+}
+
+int OSSL_SERIALIZER_up_ref(OSSL_SERIALIZER *ser)
+{
+ int ref = 0;
+
+ CRYPTO_UP_REF(&ser->refcnt, &ref, ser->lock);
+ return 1;
+}
+
+void OSSL_SERIALIZER_free(OSSL_SERIALIZER *ser)
+{
+ int ref = 0;
+
+ if (ser == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&ser->refcnt, &ref, ser->lock);
+ if (ref > 0)
+ return;
+ ossl_provider_free(ser->prov);
+ CRYPTO_THREAD_lock_free(ser->lock);
+ OPENSSL_free(ser);
+}
+
+/* Permanent serializer method store, constructor and destructor */
+static void serializer_store_free(void *vstore)
+{
+ ossl_method_store_free(vstore);
+}
+
+static void *serializer_store_new(OPENSSL_CTX *ctx)
+{
+ return ossl_method_store_new(ctx);
+}
+
+
+static const OPENSSL_CTX_METHOD serializer_store_method = {
+ serializer_store_new,
+ serializer_store_free,
+};
+
+/* Data to be passed through ossl_method_construct() */
+struct serializer_data_st {
+ OPENSSL_CTX *libctx;
+ OSSL_METHOD_CONSTRUCT_METHOD *mcm;
+ int id; /* For get_serializer_from_store() */
+ const char *names; /* For get_serializer_from_store() */
+ const char *propquery; /* For get_serializer_from_store() */
+};
+
+/*
+ * Generic routines to fetch / create SERIALIZER methods with
+ * ossl_method_construct()
+ */
+
+/* Temporary serializer method store, constructor and destructor */
+static void *alloc_tmp_serializer_store(OPENSSL_CTX *ctx)
+{
+ return ossl_method_store_new(ctx);
+}
+
+ static void dealloc_tmp_serializer_store(void *store)
+{
+ if (store != NULL)
+ ossl_method_store_free(store);
+}
+
+/* Get the permanent serializer store */
+static OSSL_METHOD_STORE *get_serializer_store(OPENSSL_CTX *libctx)
+{
+ return openssl_ctx_get_data(libctx, OPENSSL_CTX_SERIALIZER_STORE_INDEX,
+ &serializer_store_method);
+}
+
+/* Get serializer methods from a store, or put one in */
+static void *get_serializer_from_store(OPENSSL_CTX *libctx, void *store,
+ void *data)
+{
+ struct serializer_data_st *methdata = data;
+ void *method = NULL;
+ int id;
+
+ if ((id = methdata->id) == 0) {
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+
+ id = ossl_namemap_name2num(namemap, methdata->names);
+ }
+
+ if (store == NULL
+ && (store = get_serializer_store(libctx)) == NULL)
+ return NULL;
+
+ if (!ossl_method_store_fetch(store, id, methdata->propquery, &method))
+ return NULL;
+ return method;
+}
+
+static int put_serializer_in_store(OPENSSL_CTX *libctx, void *store,
+ void *method, const OSSL_PROVIDER *prov,
+ int operation_id, const char *names,
+ const char *propdef, void *unused)
+{
+ OSSL_NAMEMAP *namemap;
+ int id;
+
+ if ((namemap = ossl_namemap_stored(libctx)) == NULL
+ || (id = ossl_namemap_name2num(namemap, names)) == 0)
+ return 0;
+
+ if (store == NULL && (store = get_serializer_store(libctx)) == NULL)
+ return 0;
+
+ return ossl_method_store_add(store, prov, id, propdef, method,
+ (int (*)(void *))OSSL_SERIALIZER_up_ref,
+ (void (*)(void *))OSSL_SERIALIZER_free);
+}
+
+/* Create and populate a serializer method */
+static void *serializer_from_dispatch(int id, const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
+{
+ OSSL_SERIALIZER *ser = NULL;
+ const OSSL_DISPATCH *fns = algodef->implementation;
+
+ if ((ser = ossl_serializer_new()) == NULL)
+ return NULL;
+ ser->id = id;
+ ser->propdef = algodef->property_definition;
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_SERIALIZER_NEWCTX:
+ if (ser->newctx == NULL)
+ ser->newctx =
+ OSSL_get_OP_serializer_newctx(fns);
+ break;
+ case OSSL_FUNC_SERIALIZER_FREECTX:
+ if (ser->freectx == NULL)
+ ser->freectx =
+ OSSL_get_OP_serializer_freectx(fns);
+ break;
+ case OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS:
+ if (ser->set_ctx_params == NULL)
+ ser->set_ctx_params =
+ OSSL_get_OP_serializer_set_ctx_params(fns);
+ break;
+ case OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS:
+ if (ser->settable_ctx_params == NULL)
+ ser->settable_ctx_params =
+ OSSL_get_OP_serializer_settable_ctx_params(fns);
+ break;
+ case OSSL_FUNC_SERIALIZER_SERIALIZE_DATA:
+ if (ser->serialize_data == NULL)
+ ser->serialize_data =
+ OSSL_get_OP_serializer_serialize_data(fns);
+ break;
+ case OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT:
+ if (ser->serialize_object == NULL)
+ ser->serialize_object =
+ OSSL_get_OP_serializer_serialize_object(fns);
+ break;
+ }
+ }
+ /*
+ * Try to check that the method is sensible.
+ * If you have a constructor, you must have a destructor and vice versa.
+ * You must have at least one of the serializing driver functions.
+ */
+ if (!((ser->newctx == NULL && ser->freectx == NULL)
+ || (ser->newctx != NULL && ser->freectx != NULL))
+ || (ser->serialize_data == NULL && ser->serialize_object == NULL)) {
+ OSSL_SERIALIZER_free(ser);
+ ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_INVALID_PROVIDER_FUNCTIONS);
+ return NULL;
+ }
+
+ if (prov != NULL && !ossl_provider_up_ref(prov)) {
+ OSSL_SERIALIZER_free(ser);
+ return NULL;
+ }
+
+ ser->prov = prov;
+ return ser;
+}
+
+
+/*
+ * The core fetching functionality passes the names of the implementation.
+ * This function is responsible to getting an identity number for them,
+ * then call serializer_from_dispatch() with that identity number.
+ */
+static void *construct_serializer(const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov, void *unused)
+{
+ /*
+ * This function is only called if get_serializer_from_store() returned
+ * NULL, so it's safe to say that of all the spots to create a new
+ * namemap entry, this is it. Should the name already exist there, we
+ * know that ossl_namemap_add() will return its corresponding number.
+ */
+ OPENSSL_CTX *libctx = ossl_provider_library_context(prov);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+ const char *names = algodef->algorithm_names;
+ int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR);
+ void *method = NULL;
+
+ if (id != 0)
+ method = serializer_from_dispatch(id, algodef, prov);
+
+ return method;
+}
+
+/* Intermediary function to avoid ugly casts, used below */
+static void destruct_serializer(void *method, void *data)
+{
+ OSSL_SERIALIZER_free(method);
+}
+
+static int up_ref_serializer(void *method)
+{
+ return OSSL_SERIALIZER_up_ref(method);
+}
+
+static void free_serializer(void *method)
+{
+ OSSL_SERIALIZER_free(method);
+}
+
+/* Fetching support. Can fetch by numeric identity or by name */
+static OSSL_SERIALIZER *inner_ossl_serializer_fetch(OPENSSL_CTX *libctx,
+ int id, const char *name,
+ const char *properties)
+{
+ OSSL_METHOD_STORE *store = get_serializer_store(libctx);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+ void *method = NULL;
+
+ if (store == NULL || namemap == NULL)
+ return NULL;
+
+ /*
+ * If we have been passed neither a name_id or a name, we have an
+ * internal programming error.
+ */
+ if (!ossl_assert(id != 0 || name != NULL))
+ return NULL;
+
+ if (id == 0)
+ id = ossl_namemap_name2num(namemap, name);
+
+ if (id == 0
+ || !ossl_method_store_cache_get(store, id, properties, &method)) {
+ OSSL_METHOD_CONSTRUCT_METHOD mcm = {
+ alloc_tmp_serializer_store,
+ dealloc_tmp_serializer_store,
+ get_serializer_from_store,
+ put_serializer_in_store,
+ construct_serializer,
+ destruct_serializer
+ };
+ struct serializer_data_st mcmdata;
+
+ mcmdata.libctx = libctx;
+ mcmdata.mcm = &mcm;
+ mcmdata.id = id;
+ mcmdata.names = name;
+ mcmdata.propquery = properties;
+ if ((method = ossl_method_construct(libctx, OSSL_OP_SERIALIZER,
+ 0 /* !force_cache */,
+ &mcm, &mcmdata)) != NULL) {
+ /*
+ * If construction did create a method for us, we know that
+ * there is a correct name_id and meth_id, since those have
+ * already been calculated in get_serializer_from_store() and
+ * put_serializer_in_store() above.
+ */
+ if (id == 0)
+ id = ossl_namemap_name2num(namemap, name);
+ ossl_method_store_cache_set(store, id, properties, method,
+ up_ref_serializer, free_serializer);
+ }
+ }
+
+ return method;
+}
+
+OSSL_SERIALIZER *OSSL_SERIALIZER_fetch(OPENSSL_CTX *libctx, const char *name,
+ const char *properties)
+{
+ return inner_ossl_serializer_fetch(libctx, 0, name, properties);
+}
+
+OSSL_SERIALIZER *ossl_serializer_fetch_by_number(OPENSSL_CTX *libctx, int id,
+ const char *properties)
+{
+ return inner_ossl_serializer_fetch(libctx, id, NULL, properties);
+}
+
+/*
+ * Library of basic method functions
+ */
+
+const OSSL_PROVIDER *OSSL_SERIALIZER_provider(const OSSL_SERIALIZER *ser)
+{
+ if (!ossl_assert(ser != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ return ser->prov;
+}
+
+const char *OSSL_SERIALIZER_properties(const OSSL_SERIALIZER *ser)
+{
+ if (!ossl_assert(ser != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ return ser->propdef;
+}
+
+int OSSL_SERIALIZER_number(const OSSL_SERIALIZER *ser)
+{
+ if (!ossl_assert(ser != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ return ser->id;
+}
+
+int OSSL_SERIALIZER_is_a(const OSSL_SERIALIZER *ser, const char *name)
+{
+ if (ser->prov != NULL) {
+ OPENSSL_CTX *libctx = ossl_provider_library_context(ser->prov);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+
+ return ossl_namemap_name2num(namemap, name) == ser->id;
+ }
+ return 0;
+}
+
+struct serializer_do_all_data_st {
+ void (*user_fn)(void *method, void *arg);
+ void *user_arg;
+};
+
+static void serializer_do_one(OSSL_PROVIDER *provider,
+ const OSSL_ALGORITHM *algodef,
+ int no_store, void *vdata)
+{
+ struct serializer_do_all_data_st *data = vdata;
+ OPENSSL_CTX *libctx = ossl_provider_library_context(provider);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+ const char *names = algodef->algorithm_names;
+ int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR);
+ void *method = NULL;
+
+ if (id != 0)
+ method =
+ serializer_from_dispatch(id, algodef, provider);
+
+ if (method != NULL) {
+ data->user_fn(method, data->user_arg);
+ OSSL_SERIALIZER_free(method);
+ }
+}
+
+void OSSL_SERIALIZER_do_all_provided(OPENSSL_CTX *libctx,
+ void (*fn)(OSSL_SERIALIZER *ser,
+ void *arg),
+ void *arg)
+{
+ struct serializer_do_all_data_st data;
+
+ data.user_fn = (void (*)(void *, void *))fn;
+ data.user_arg = arg;
+ ossl_algorithm_do_all(libctx, OSSL_OP_SERIALIZER, NULL,
+ serializer_do_one, &data);
+}
+
+void OSSL_SERIALIZER_names_do_all(const OSSL_SERIALIZER *ser,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (ser == NULL)
+ return;
+
+ if (ser->prov != NULL) {
+ OPENSSL_CTX *libctx = ossl_provider_library_context(ser->prov);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+
+ ossl_namemap_doall_names(namemap, ser->id, fn, data);
+ }
+}
+
+const OSSL_PARAM *OSSL_SERIALIZER_settable_ctx_params(OSSL_SERIALIZER *ser)
+{
+ if (ser != NULL && ser->settable_ctx_params != NULL)
+ return ser->settable_ctx_params();
+ return NULL;
+}
+
+/*
+ * Serializer context support
+ */
+
+/*
+ * |ser| value NULL is valid, and signifies that there is no serializer.
+ * This is useful to provide fallback mechanisms.
+ * Funtions that want to verify if there is a serializer can do so with
+ * OSSL_SERIALIZER_CTX_get_serializer()
+ */
+OSSL_SERIALIZER_CTX *OSSL_SERIALIZER_CTX_new(OSSL_SERIALIZER *ser)
+{
+ OSSL_SERIALIZER_CTX *ctx;
+
+ if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
+ ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ ctx->ser = ser;
+ if (ser != NULL && ser->newctx != NULL) {
+ const OSSL_PROVIDER *prov = OSSL_SERIALIZER_provider(ser);
+ void *provctx = ossl_provider_ctx(prov);
+
+ if (OSSL_SERIALIZER_up_ref(ser)) {
+ ctx->serctx = ser->newctx(provctx);
+ } else {
+ OSSL_SERIALIZER_free(ser);
+ OPENSSL_free(ctx);
+ ctx = NULL;
+ }
+ }
+
+ return ctx;
+}
+
+const OSSL_SERIALIZER *
+OSSL_SERIALIZER_CTX_get_serializer(OSSL_SERIALIZER_CTX *ctx)
+{
+ if (!ossl_assert(ctx != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ return ctx->ser;
+}
+
+
+int OSSL_SERIALIZER_CTX_set_params(OSSL_SERIALIZER_CTX *ctx,
+ const OSSL_PARAM params[])
+{
+ if (!ossl_assert(ctx != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (ctx->ser != NULL && ctx->ser->set_ctx_params != NULL)
+ return ctx->ser->set_ctx_params(ctx->serctx, params);
+ return 0;
+}
+
+void OSSL_SERIALIZER_CTX_free(OSSL_SERIALIZER_CTX *ctx)
+{
+ if (ctx != NULL) {
+ if (ctx->ser != NULL && ctx->ser->freectx != NULL)
+ ctx->ser->freectx(ctx->serctx);
+ OSSL_SERIALIZER_free(ctx->ser);
+ OPENSSL_free(ctx);
+ }
+}
--- /dev/null
+=pod
+
+=head1 NAME
+
+OSSL_SERIALIZER,
+OSSL_SERIALIZER_fetch,
+OSSL_SERIALIZER_up_ref,
+OSSL_SERIALIZER_free,
+OSSL_SERIALIZER_provider,
+OSSL_SERIALIZER_properties,
+OSSL_SERIALIZER_is_a,
+OSSL_SERIALIZER_number,
+OSSL_SERIALIZER_do_all_provided,
+OSSL_SERIALIZER_names_do_all
+- Serializer method routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/serializer.h>
+
+ typedef struct ossl_serializer_st OSSL_SERIALIZER;
+
+ OSSL_SERIALIZER *OSSL_SERIALIZER_fetch(OPENSSL_CTX *ctx, const char *name,
+ const char *properties);
+ int OSSL_SERIALIZER_up_ref(OSSL_SERIALIZER *serializer);
+ void OSSL_SERIALIZER_free(OSSL_SERIALIZER *serializer);
+ const OSSL_PROVIDER *OSSL_SERIALIZER_provider(const OSSL_SERIALIZER
+ *serializer);
+ const char *OSSL_SERIALIZER_properties(const OSSL_SERIALIZER *ser);
+ int OSSL_SERIALIZER_is_a(const OSSL_SERIALIZER *serializer,
+ const char *name);
+ int OSSL_SERIALIZER_number(const OSSL_SERIALIZER *serializer);
+ void OSSL_SERIALIZER_do_all_provided(OPENSSL_CTX *libctx,
+ void (*fn)(OSSL_SERIALIZER *serializer,
+ void *arg),
+ void *arg);
+ void OSSL_SERIALIZER_names_do_all(const OSSL_SERIALIZER *serializer,
+ void (*fn)(const char *name, void *data),
+ void *data);
+
+=head1 DESCRIPTION
+
+=for comment Future development should also talk about deserialization
+
+B<OSSL_SERIALIZER> is a method for serializers, which know how to
+serialize an object of some kind to a serialized form, such as PEM,
+DER, or even human readable text.
+
+OSSL_SERIALIZER_fetch() looks for an algorithm within the provider that
+has been loaded into the B<OPENSSL_CTX> given by I<ctx>, having the
+name given by I<name> and the properties given by I<properties>.
+The I<name> determines what type of object the fetched serializer
+method is expected to be able to serialize, and the properties are
+used to determine the expected output type.
+For known properties and the values they may have, please have a look
+in L<provider-serializer(7)/Names and properties>.
+
+OSSL_SERIALIZER_up_ref() increments the reference count for the given
+I<serializer>.
+
+OSSL_SERIALIZER_free() decrements the reference count for the given
+I<serializer>, and when the count reaches zero, frees it.
+
+OSSL_SERIALIZER_provider() returns the provider of the given
+I<serializer>.
+
+OSSL_SERIALIZER_provider() returns the property definition associated
+with the given I<serializer>.
+
+OSSL_SERIALIZER_is_a() checks if I<serializer> is an implementation of an
+algorithm that's identifiable with I<name>.
+
+OSSL_SERIALIZER_number() returns the internal dynamic number assigned to
+the given I<serializer>.
+
+OSSL_SERIALIZER_names_do_all() traverses all names for the given
+I<serializer>, and calls I<fn> with each name and I<data>.
+
+OSSL_SERIALIZER_do_all_provided() traverses all serializer
+implementations by all activated providers in the library context
+I<libctx>, and for each of the implementations, calls I<fn> with the
+implementation method and I<data> as arguments.
+
+=head1 NOTES
+
+OSSL_SERIALIZER_fetch() may be called implicitly by other fetching
+functions, using the same library context and properties.
+Any other API that uses keys will typically do this.
+
+=head1 RETURN VALUES
+
+OSSL_SERIALIZER_fetch() returns a pointer to the key management
+implementation represented by an OSSL_SERIALIZER object, or NULL on
+error.
+
+OSSL_SERIALIZER_up_ref() returns 1 on success, or 0 on error.
+
+OSSL_SERIALIZER_free() doesn't return any value.
+
+OSSL_SERIALIZER_provider() returns a pointer to a provider object, or
+NULL on error.
+
+OSSL_SERIALIZER_properties() returns a pointer to a property
+definition string, or NULL on error.
+
+OSSL_SERIALIZER_is_a() returns 1 of I<serializer> was identifiable,
+otherwise 0.
+
+OSSL_SERIALIZER_number() returns an integer.
+
+=head1 SEE ALSO
+
+L<provider(7)>, L<OSSL_SERIALIZER_CTX(3)>, L<OPENSSL_CTX(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019 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
+L<https://www.openssl.org/source/license.html>.
+
+=cut
--- /dev/null
+=pod
+
+=head1 NAME
+
+OSSL_SERIALIZER_CTX,
+OSSL_SERIALIZER_CTX_new,
+OSSL_SERIALIZER_CTX_get_serializer,
+OSSL_SERIALIZER_settable_ctx_params,
+OSSL_SERIALIZER_CTX_set_params,
+OSSL_SERIALIZER_CTX_free
+- Serializer context routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/serializer.h>
+
+ typedef struct ossl_serializer_ctx_st OSSL_SERIALIZER_CTX;
+
+ OSSL_SERIALIZER_CTX *OSSL_SERIALIZER_CTX_new(OSSL_SERIALIZER *ser);
+ const OSSL_SERIALIZER *
+ OSSL_SERIALIZER_CTX_get_serializer(OSSL_SERIALIZER_CTX *ctx);
+ const OSSL_PARAM *OSSL_SERIALIZER_settable_ctx_params(OSSL_SERIALIZER *ser);
+ int OSSL_SERIALIZER_CTX_set_params(OSSL_SERIALIZER_CTX *ctx,
+ const OSSL_PARAM params[]);
+ void OSSL_SERIALIZER_CTX_free(OSSL_SERIALIZER_CTX *ctx);
+
+=head1 DESCRIPTION
+
+B<OSSL_SERIALIZER_CTX> is a context with which B<OSSL_SERIALIZER>
+operations are performed. The context typically holds values, both
+internal and supplied by the application, which are useful for the
+implementations supplied by providers.
+
+OSSL_SERIALIZER_CTX_new() creates a B<OSSL_SERIALIZER_CTX> associated
+with the serializer I<ser>. NULL is a valid I<ser>, the context will
+be created anyway, it's just not very useful. This is intentional, to
+distinguish between errors in allocating the context or assigning it
+values on one hand, and the lack of serializer support on the other.
+
+=begin comment
+
+The above distinction makes it possible for other routines to sense if
+they need to report an error or fall back on other methods to
+serialize.
+
+=end comment
+
+OSSL_SERIALIZER_CTX_get_serializer() gets the serializer method
+currently associated with the context I<ctx>.
+
+OSSL_SERIALIZER_settable_ctx_params() returns an L<OSSL_PARAM(3)>
+array of parameter descriptors.
+
+OSSL_SERIALIZER_CTX_set_params() attempts to set parameters specified
+with an L<OSSL_PARAM(3)> array I<params>. Parameters that the
+implementation doesn't recognise should be ignored.
+
+OSSL_SERIALIZER_CTX_free() frees the given context I<ctx>.
+
+=head1 RETURN VALUES
+
+OSSL_SERIALIZER_CTX_new() returns a pointer to a
+B<OSSL_SERIALIZER_CTX>, or NULL if the context structure couldn't be
+allocated.
+
+OSSL_SERIALIZER_CTX_get_serializer() returns a pointer to the
+serializer method associated with I<ctx>. NULL is a valid return
+value and signifies that there is no associated serializer method.
+
+OSSL_SERIALIZER_settable_ctx_params() returns an L<OSSL_PARAM(3)>
+array, or NULL if none is available.
+
+OSSL_SERIALIZER_CTX_set_params() returns 1 if all recognised
+parameters were valid, or 0 if one of them was invalid or caused some
+other failure in the implementation.
+
+=head1 SEE ALSO
+
+L<provider(7)>, L<OSSL_SERIALIZER(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019 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
+L<https://www.openssl.org/source/license.html>.
+
+=cut
=item B<OSSL_CALLBACK>
-This is a function type for a generic callback function:
+This is a function type for a generic feedback callback function:
typedef int (OSSL_CALLBACK)(const OSSL_PARAM params[], void *arg);
expected to pass back, and pass that as I<params>, as well as
the caller data pointer it received, as I<arg>.
+=item B<OSSL_PASSPHRASE_CALLBACK>
+
+This is a function type for a generic pass phrase callback function:
+
+ typedef int (OSSL_PASSPHRASE_CALLBACK)(char *pass, size_t pass_size,
+ size_t *pass_len,
+ const OSSL_PARAM params[],
+ void *arg);
+
+This callback can be used to prompt the user for a passphrase. When
+calling it, a buffer to store the pass phrase needs to be given with
+I<pass>, and its size with I<pass_size>. The length of the prompted
+pass phrase will be given back in I<*pass_len>.
+
+Additional parameters can be passed with the B<OSSL_PARAM> array
+I<params>.
+
+A function that takes a pointer of this type should also take a
+pointer to caller data, which should be passed as I<arg> to this
+callback.
+
=back
=head1 SEE ALSO
--- /dev/null
+=pod
+
+=head1 NAME
+
+provider-serializer - The SERIALIZER library E<lt>-E<gt> provider functions
+
+=head1 SYNOPSIS
+
+=begin comment
+
+Future development will also include deserializing functions.
+
+=end comment
+
+ #include <openssl/core_numbers.h>
+
+ /*
+ * None of these are actual functions, but are displayed like this for
+ * the function signatures for functions that are offered as function
+ * pointers in OSSL_DISPATCH arrays.
+ */
+
+ /* Functions to construct / destruct / manipulate the serializer context */
+ void *OP_serializer_newctx(void *provctx);
+ void OP_serializer_freectx(void *ctx);
+ int OP_serializer_set_ctx_params(void *ctx, const OSSL_PARAM params[]);
+ const OSSL_PARAM *OP_serializer_settable_ctx_params(void)
+
+ /* Functions to serialize object data */
+ int OP_serializer_serialize_data(void *ctx, const OSSL_PARAM *data,
+ BIO *out,
+ OSSL_PASSPHRASE_CALLBACK *cb,
+ void *cbarg);
+ int OP_serializer_serialize_object(void *ctx, void *obj, BIO *out,
+ OSSL_PASSPHRASE_CALLBACK *cb,
+ void *cbarg);
+
+=head1 DESCRIPTION
+
+The SERIALIZER is a generic method to serialize any set of object data
+in L<OSSL_PARAM(3)> array form, or any provider side object into
+serialized form, and write it to the given BIO. If the caller wants
+to get the serialized stream to memory, it should provide a
+L<BIO_s_membuf(3)>.
+
+The serializer doesn't need to know more about the B<BIO> pointer than
+being able to pass it to the appropriate BIO upcalls (see
+L<provider-base(7)/Core functions>).
+
+The serialization using the L<OSSL_PARAM(3)> array form allows a
+serializer to be used for data that's been exported from another
+provider, and thereby allow them to exist independently of each
+other.
+
+The serialization using a provider side object can only be safely used
+with provider data coming from the same provider, for example keys
+with the L<KEYMGMT|provider-keymgmt(7)> provider.
+
+All "functions" mentioned here are passed as function pointers between
+F<libcrypto> and the provider in B<OSSL_DISPATCH> arrays via
+B<OSSL_ALGORITHM> arrays that are returned by the provider's
+provider_query_operation() function
+(see L<provider-base(7)/Provider Functions>).
+
+All these "functions" have a corresponding function type definition
+named B<OSSL_{name}_fn>, and a helper function to retrieve the
+function pointer from a B<OSSL_DISPATCH> element named
+B<OSSL_get_{name}>.
+For example, the "function" OP_serializer_serialize_data() has these:
+
+ typedef int
+ (OSSL_OP_serializer_serialize_data_fn)(void *provctx,
+ const OSSL_PARAM params[],
+ BIO *out);
+ static ossl_inline OSSL_OP_serializer_serialize_data_fn
+ OSSL_get_OP_serializer_serialize_data(const OSSL_DISPATCH *opf);
+
+B<OSSL_DISPATCH> arrays are indexed by numbers that are provided as
+macros in L<openssl-core_numbers.h(7)>, as follows:
+
+ OP_serializer_newctx OSSL_FUNC_SERIALIZER_NEWCTX
+ OP_serializer_freectx OSSL_FUNC_SERIALIZER_FREECTX
+ OP_serializer_set_ctx_params OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS
+ OP_serializer_settable_ctx_params OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS
+
+ OP_serializer_serialize_data OSSL_FUNC_SERIALIZER_SERIALIZE_DATA
+ OP_serializer_serialize_object OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT
+
+=head2 Names and properties
+
+The name of an implementation should match the type of object it
+handles. For example, an implementation that serializes an RSA key
+should be named accordingly.
+
+To be able to specify exactly what serialization format and what type
+of data a serializer implementation is expected to handle, two
+additional properties may be given:
+
+=over 4
+
+=item format
+
+This property is used to specify what kind of output format the
+implementation produces. Currently known formats are:
+
+=over 4
+
+=item text
+
+An implementation with that format property value outputs human
+readable text, making that implementation suitable for C<-text> output
+in diverse L<openssl(1)> commands.
+
+=item pem
+
+An implementation with that format property value outputs PEM
+formatted data.
+
+=item der
+
+An implementation with that format property value outputs DER
+formatted data.
+
+=back
+
+=item type
+
+With objects that have multiple purposes, this can be used to specify
+the purpose type. The currently known use cases are asymmetric keys
+and domain parameters, where the type can be one of:
+
+=over 4
+
+=item private
+
+An implementation with that format property value outputs a private
+key.
+
+=item public
+
+An implementation with that format property value outputs a public
+key.
+
+=item domainparams
+
+An implementation with that format property value outputs domain
+parameters.
+
+=back
+
+=back
+
+The possible values of both these properties is open ended. A
+provider may very well specify other formats that libcrypto doesn't
+know anything about.
+
+=head2 Context functions
+
+OP_serializer_newctx() returns a context to be used with the rest of
+the functions.
+
+OP_serializer_freectx() frees the given I<ctx>, if it was created by
+OP_serializer_newctx().
+
+OP_serializer_set_ctx_params() sets context data according to
+parameters from I<params> that it recognises. Unrecognised parameters
+should be ignored.
+
+OP_serializer_settable_ctx_params() returns a constant B<OSSL_PARAM>
+array describing the parameters that OP_serializer_set_ctx_params()
+can handle.
+
+See L<OSSL_PARAM(3)> for further details on the parameters structure used
+by OP_serializer_set_ctx_params() and OP_serializer_settable_ctx_params().
+
+=head2 Serializing functions
+
+=for comment There will be a "Deserializing functions" title as well
+
+OP_serializer_serialize_data() should take an array of B<OSSL_PARAM>,
+I<data>, and if it contains the data necessary for the object type
+that the implementation handles, it should output the object in
+serialized form to the B<BIO>.
+
+OP_serializer_serialize_object() should take a pointer to an object
+that it knows intimately, and output that object in serialized form to
+the B<BIO>. The caller I<must> ensure that this function is called
+with a pointer that the provider of this function is familiar with.
+It is not suitable to use with object pointers coming from other
+providers.
+
+Both serialization functions also take an B<OSSL_PASSPHRASE_CALLBACK>
+function pointer along with a pointer to application data I<cbarg>,
+which should be used when a pass phrase prompt is needed.
+
+=head1 RETURN VALUES
+
+OP_serializer_newctx() returns a pointer to a context, or NULL on
+failure.
+
+OP_serializer_set_ctx_params() returns 1, unless a recognised
+parameters was invalid or caused an error, for which 0 is returned.
+
+OP_serializer_settable_ctx_params() returns a pointer to an array of
+constant B<OSSL_PARAM> elements.
+
+OP_serializer_serialize_data() and OP_serializer_serialize_object()
+return 1 on success, or 0 on failure.
+
+=head1 SEE ALSO
+
+L<provider(7)>
+
+=head1 HISTORY
+
+The SERIALIZER interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019 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
+L<https://www.openssl.org/source/license.html>.
+
+=cut
The functions the provider can offer are described in
L<provider-keyexch(7)>
+=item Serialization
+
+In the OpenSSL libraries, the corresponding method object is
+B<OSSL_SERIALIZER>.
+The number for this operation is B<OSSL_OP_SERIALIZER>.
+The functions the provider can offer are described in
+L<provider-serializer(7)>
+
=back
=head2 Fetching algorithms
--- /dev/null
+/*
+ * Copyright 2019 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 <openssl/types.h>
+
+OSSL_SERIALIZER *ossl_serializer_fetch_by_number(OPENSSL_CTX *libctx, int id,
+ const char *properties);
# define OPENSSL_CTX_RAND_CRNGT_INDEX 7
# define OPENSSL_CTX_THREAD_EVENT_HANDLER_INDEX 8
# define OPENSSL_CTX_FIPS_PROV_INDEX 9
-# define OPENSSL_CTX_MAX_INDEXES 10
+# define OPENSSL_CTX_SERIALIZER_STORE_INDEX 10
+# define OPENSSL_CTX_MAX_INDEXES 11
typedef struct openssl_ctx_method {
void *(*new_func)(OPENSSL_CTX *ctx);
*/
typedef int (OSSL_CALLBACK)(const OSSL_PARAM params[], void *arg);
+/*
+ * Passphrase callback function signature
+ *
+ * This is similar to the generic callback function above, but adds a
+ * result parameter.
+ */
+typedef int (OSSL_PASSPHRASE_CALLBACK)(char *pass, size_t pass_size,
+ size_t *pass_len,
+ const OSSL_PARAM params[], void *arg);
+
# ifdef __cplusplus
}
# endif
# define OSSL_OP_KEYEXCH 11
# define OSSL_OP_SIGNATURE 12
# define OSSL_OP_ASYM_CIPHER 13
+/* New section for non-EVP operations */
+# define OSSL_OP_SERIALIZER 20
/* Highest known operation number */
-# define OSSL_OP__HIGHEST 13
+# define OSSL_OP__HIGHEST 20
/* Digests */
OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_asym_cipher_settable_ctx_params,
(void))
+/* Serializers */
+# define OSSL_FUNC_SERIALIZER_NEWCTX 1
+# define OSSL_FUNC_SERIALIZER_FREECTX 2
+# define OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS 3
+# define OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS 4
+# define OSSL_FUNC_SERIALIZER_SERIALIZE_DATA 10
+# define OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT 11
+OSSL_CORE_MAKE_FUNC(void *, OP_serializer_newctx, (void *provctx))
+OSSL_CORE_MAKE_FUNC(void, OP_serializer_freectx, (void *ctx))
+OSSL_CORE_MAKE_FUNC(int, OP_serializer_set_ctx_params,
+ (void *ctx, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_serializer_settable_ctx_params,
+ (void))
+
+OSSL_CORE_MAKE_FUNC(int, OP_serializer_serialize_data,
+ (void *ctx, const OSSL_PARAM[], BIO *out,
+ OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg))
+OSSL_CORE_MAKE_FUNC(int, OP_serializer_serialize_object,
+ (void *ctx, void *obj, BIO *out,
+ OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg))
+
# ifdef __cplusplus
}
# endif
# define ERR_LIB_CRMF 56
# define ERR_LIB_PROV 57
# define ERR_LIB_CMP 58
+# define ERR_LIB_OSSL_SERIALIZER 59
# define ERR_LIB_USER 128
# define ERR_R_INIT_FAIL (6|ERR_R_FATAL)
# define ERR_R_PASSED_INVALID_ARGUMENT (7)
# define ERR_R_OPERATION_FAIL (8|ERR_R_FATAL)
+# define ERR_R_INVALID_PROVIDER_FUNCTIONS (9|ERR_R_FATAL)
/*
* 99 is the maximum possible ERR_R_... code, higher values are reserved for
# define DECLARE_PEM_rw_cb(name, type) \
DECLARE_PEM_read(name, type) \
DECLARE_PEM_write_cb(name, type)
-typedef int pem_password_cb (char *buf, int size, int rwflag, void *userdata);
int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher);
int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *len,
--- /dev/null
+/*
+ * Copyright 2019 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 OPENSSL_SERIALIZER_H
+# define OPENSSL_SERIALIZER_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+
+# ifndef OPENSSL_NO_STDIO
+# include <stdio.h>
+# endif
+# include <stdarg.h>
+# include <stddef.h>
+# include <openssl/types.h>
+# include <openssl/core.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+OSSL_SERIALIZER *OSSL_SERIALIZER_fetch(OPENSSL_CTX *libctx,
+ const char *name,
+ const char *properties);
+int OSSL_SERIALIZER_up_ref(OSSL_SERIALIZER *ser);
+void OSSL_SERIALIZER_free(OSSL_SERIALIZER *ser);
+
+const OSSL_PROVIDER *OSSL_SERIALIZER_provider(const OSSL_SERIALIZER *ser);
+const char *OSSL_SERIALIZER_properties(const OSSL_SERIALIZER *ser);
+int OSSL_SERIALIZER_number(const OSSL_SERIALIZER *ser);
+int OSSL_SERIALIZER_is_a(const OSSL_SERIALIZER *ser,
+ const char *name);
+
+void OSSL_SERIALIZER_do_all_provided(OPENSSL_CTX *libctx,
+ void (*fn)(OSSL_SERIALIZER *ser,
+ void *arg),
+ void *arg);
+void OSSL_SERIALIZER_names_do_all(const OSSL_SERIALIZER *ser,
+ void (*fn)(const char *name, void *data),
+ void *data);
+
+const OSSL_PARAM *OSSL_SERIALIZER_settable_ctx_params(OSSL_SERIALIZER *ser);
+OSSL_SERIALIZER_CTX *OSSL_SERIALIZER_CTX_new(OSSL_SERIALIZER *ser);
+const OSSL_SERIALIZER *
+OSSL_SERIALIZER_CTX_get_serializer(OSSL_SERIALIZER_CTX *ctx);
+int OSSL_SERIALIZER_CTX_set_params(OSSL_SERIALIZER_CTX *ctx,
+ const OSSL_PARAM params[]);
+void OSSL_SERIALIZER_CTX_free(OSSL_SERIALIZER_CTX *ctx);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
typedef struct ossl_algorithm_st OSSL_ALGORITHM;
typedef struct ossl_param_st OSSL_PARAM;
+typedef int pem_password_cb (char *buf, int size, int rwflag, void *userdata);
+
+typedef struct ossl_serializer_st OSSL_SERIALIZER;
+typedef struct ossl_serializer_ctx_st OSSL_SERIALIZER_CTX;
+
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
defined(INTMAX_MAX) && defined(UINTMAX_MAX)
typedef intmax_t ossl_intmax_t;
EVP_PKEY_meth_set_digestverify ? 3_0_0 EXIST::FUNCTION:
EVP_PKEY_meth_get_digestsign ? 3_0_0 EXIST::FUNCTION:
EVP_PKEY_meth_get_digestverify ? 3_0_0 EXIST::FUNCTION:
+OSSL_SERIALIZER_up_ref ? 3_0_0 EXIST::FUNCTION:
+OSSL_SERIALIZER_free ? 3_0_0 EXIST::FUNCTION:
+OSSL_SERIALIZER_fetch ? 3_0_0 EXIST::FUNCTION:
+OSSL_SERIALIZER_number ? 3_0_0 EXIST::FUNCTION:
+OSSL_SERIALIZER_is_a ? 3_0_0 EXIST::FUNCTION:
+OSSL_SERIALIZER_provider ? 3_0_0 EXIST::FUNCTION:
+OSSL_SERIALIZER_do_all_provided ? 3_0_0 EXIST::FUNCTION:
+OSSL_SERIALIZER_names_do_all ? 3_0_0 EXIST::FUNCTION:
+OSSL_SERIALIZER_settable_ctx_params ? 3_0_0 EXIST::FUNCTION:
+OSSL_SERIALIZER_CTX_new ? 3_0_0 EXIST::FUNCTION:
+OSSL_SERIALIZER_CTX_get_serializer ? 3_0_0 EXIST::FUNCTION:
+OSSL_SERIALIZER_CTX_set_params ? 3_0_0 EXIST::FUNCTION:
+OSSL_SERIALIZER_CTX_free ? 3_0_0 EXIST::FUNCTION:
+OSSL_SERIALIZER_properties ? 3_0_0 EXIST::FUNCTION:
NAMING_AUTHORITY datatype
OSSL_PARAM datatype
OSSL_PROVIDER datatype
+OSSL_SERIALIZER datatype
+OSSL_SERIALIZER_CTX datatype
OSSL_STORE_CTX datatype
OSSL_STORE_INFO datatype
OSSL_STORE_LOADER datatype