summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/build.info2
-rw-r--r--crypto/err/err.c2
-rw-r--r--crypto/err/openssl.ec1
-rw-r--r--crypto/property/property_parse.c2
-rw-r--r--crypto/serializer/build.info1
-rw-r--r--crypto/serializer/serializer_local.h34
-rw-r--r--crypto/serializer/serializer_meth.c514
-rw-r--r--doc/man3/OSSL_SERIALIZER.pod128
-rw-r--r--doc/man3/OSSL_SERIALIZER_CTX.pod94
-rw-r--r--doc/man7/openssl-core.h.pod23
-rw-r--r--doc/man7/provider-serializer.pod227
-rw-r--r--doc/man7/provider.pod8
-rw-r--r--include/crypto/serializer.h13
-rw-r--r--include/internal/cryptlib.h3
-rw-r--r--include/openssl/core.h10
-rw-r--r--include/openssl/core_numbers.h25
-rw-r--r--include/openssl/err.h2
-rw-r--r--include/openssl/pem.h1
-rw-r--r--include/openssl/serializer.h59
-rw-r--r--include/openssl/types.h5
-rw-r--r--util/libcrypto.num14
-rw-r--r--util/other.syms2
22 files changed, 1165 insertions, 5 deletions
diff --git a/crypto/build.info b/crypto/build.info
index 5f90a2eda2..5beaf528be 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -5,7 +5,7 @@ SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 conf \
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
diff --git a/crypto/err/err.c b/crypto/err/err.c
index bc33a06b7e..0fb46bef4d 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -75,6 +75,7 @@ static ERR_STRING_DATA ERR_str_libraries[] = {
{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},
};
@@ -111,6 +112,7 @@ static ERR_STRING_DATA ERR_str_reasons[] = {
{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},
};
diff --git a/crypto/err/openssl.ec b/crypto/err/openssl.ec
index 211edd42f3..485c0c89ce 100644
--- a/crypto/err/openssl.ec
+++ b/crypto/err/openssl.ec
@@ -40,6 +40,7 @@ L OSSL_STORE include/openssl/store.h crypto/store/store_err.c
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
diff --git a/crypto/property/property_parse.c b/crypto/property/property_parse.c
index a16bcd6dba..f6377e7714 100644
--- a/crypto/property/property_parse.c
+++ b/crypto/property/property_parse.c
@@ -568,6 +568,8 @@ int ossl_property_parse_init(OPENSSL_CTX *ctx)
"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;
diff --git a/crypto/serializer/build.info b/crypto/serializer/build.info
new file mode 100644
index 0000000000..7d69df931c
--- /dev/null
+++ b/crypto/serializer/build.info
@@ -0,0 +1 @@
+SOURCE[../../libcrypto]=serializer_meth.c
diff --git a/crypto/serializer/serializer_local.h b/crypto/serializer/serializer_local.h
new file mode 100644
index 0000000000..979ba83e78
--- /dev/null
+++ b/crypto/serializer/serializer_local.h
@@ -0,0 +1,34 @@
+/*
+ * 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;
+};
diff --git a/crypto/serializer/serializer_meth.c b/crypto/serializer/serializer_meth.c
new file mode 100644
index 0000000000..103188f93a
--- /dev/null
+++ b/crypto/serializer/serializer_meth.c
@@ -0,0 +1,514 @@
+/*
+ * 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);
+ }
+}
diff --git a/doc/man3/OSSL_SERIALIZER.pod b/doc/man3/OSSL_SERIALIZER.pod
new file mode 100644
index 0000000000..34767734f7
--- /dev/null
+++ b/doc/man3/OSSL_SERIALIZER.pod
@@ -0,0 +1,128 @@
+=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
diff --git a/doc/man3/OSSL_SERIALIZER_CTX.pod b/doc/man3/OSSL_SERIALIZER_CTX.pod
new file mode 100644
index 0000000000..d446b842d0
--- /dev/null
+++ b/doc/man3/OSSL_SERIALIZER_CTX.pod
@@ -0,0 +1,94 @@
+=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
diff --git a/doc/man7/openssl-core.h.pod b/doc/man7/openssl-core.h.pod
index b5323e9d21..28307a97d4 100644
--- a/doc/man7/openssl-core.h.pod
+++ b/doc/man7/openssl-core.h.pod
@@ -76,7 +76,7 @@ B<OSSL_PARAM> is further described in L<OSSL_PARAM(3)>
=item B<OSSL_C