serialisation: Add a built-in base provider.
authorPauli <paul.dale@oracle.com>
Wed, 10 Jun 2020 23:08:01 +0000 (09:08 +1000)
committerPauli <paul.dale@oracle.com>
Thu, 30 Jul 2020 10:15:22 +0000 (20:15 +1000)
Move the libcrypto serialisation functionality into a place where it can
be provided at some point. The serialisation still remains native in the
default provider.

Add additional code to the list command to display what kind of serialisation
each entry is capable of.

Having the FIPS provider auto load the base provider is a future
(but necessary) enhancement.

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/12104)

apps/list.c
crypto/provider_predefined.c
doc/man1/openssl-list.pod.in
doc/man7/OSSL_PROVIDER-base.pod [new file with mode: 0644]
doc/man7/OSSL_PROVIDER-default.pod
doc/man7/provider.pod
providers/baseprov.c [new file with mode: 0644]
providers/build.info
providers/defltprov.c
providers/serializers.inc [new file with mode: 0644]

index b58871b1c56dec79c95b374a57b26acce325b057..5b93f7dfed6f6aadfac7e4d1e650d66ea659adc0 100644 (file)
@@ -16,6 +16,8 @@
 #include <openssl/provider.h>
 #include <openssl/safestack.h>
 #include <openssl/kdf.h>
+#include <openssl/serializer.h>
+#include <openssl/core_names.h>
 #include "apps.h"
 #include "app_params.h"
 #include "progs.h"
@@ -351,6 +353,66 @@ static void list_random_generators(void)
     sk_EVP_RAND_pop_free(rands, EVP_RAND_free);
 }
 
+/*
+ * Serializers
+ */
+DEFINE_STACK_OF(OSSL_SERIALIZER)
+static int serializer_cmp(const OSSL_SERIALIZER * const *a,
+                          const OSSL_SERIALIZER * const *b)
+{
+    int ret = OSSL_SERIALIZER_number(*a) - OSSL_SERIALIZER_number(*b);
+
+    if (ret == 0)
+        ret = strcmp(OSSL_PROVIDER_name(OSSL_SERIALIZER_provider(*a)),
+                     OSSL_PROVIDER_name(OSSL_SERIALIZER_provider(*b)));
+    return ret;
+}
+
+static void collect_serializers(OSSL_SERIALIZER *serializer, void *stack)
+{
+    STACK_OF(OSSL_SERIALIZER) *serializer_stack = stack;
+
+    sk_OSSL_SERIALIZER_push(serializer_stack, serializer);
+    OSSL_SERIALIZER_up_ref(serializer);
+}
+
+static void list_serializers(void)
+{
+    STACK_OF(OSSL_SERIALIZER) *serializers;
+    int i;
+
+    serializers = sk_OSSL_SERIALIZER_new(serializer_cmp);
+    if (serializers == NULL) {
+        BIO_printf(bio_err, "ERROR: Memory allocation\n");
+        return;
+    }
+    BIO_printf(bio_out, "Provided SERIALIZERs:\n");
+    OSSL_SERIALIZER_do_all_provided(NULL, collect_serializers, serializers);
+    sk_OSSL_SERIALIZER_sort(serializers);
+
+    for (i = 0; i < sk_OSSL_SERIALIZER_num(serializers); i++) {
+        OSSL_SERIALIZER *k = sk_OSSL_SERIALIZER_value(serializers, i);
+        STACK_OF(OPENSSL_CSTRING) *names =
+            sk_OPENSSL_CSTRING_new(name_cmp);
+
+        OSSL_SERIALIZER_names_do_all(k, collect_names, names);
+
+        BIO_printf(bio_out, "  ");
+        print_names(bio_out, names);
+        BIO_printf(bio_out, " @ %s (%s)\n",
+                   OSSL_PROVIDER_name(OSSL_SERIALIZER_provider(k)),
+                   OSSL_SERIALIZER_properties(k));
+
+        sk_OPENSSL_CSTRING_free(names);
+
+        if (verbose) {
+            print_param_types("settable operation parameters",
+                              OSSL_SERIALIZER_settable_ctx_params(k), 4);
+        }
+    }
+    sk_OSSL_SERIALIZER_pop_free(serializers, OSSL_SERIALIZER_free);
+}
+
 static void list_missing_help(void)
 {
     const FUNCTION *fp;
@@ -697,7 +759,8 @@ typedef enum HELPLIST_CHOICE {
     OPT_COMMANDS, OPT_DIGEST_COMMANDS, OPT_MAC_ALGORITHMS, OPT_OPTIONS,
     OPT_DIGEST_ALGORITHMS, OPT_CIPHER_COMMANDS, OPT_CIPHER_ALGORITHMS,
     OPT_PK_ALGORITHMS, OPT_PK_METHOD, OPT_DISABLED,
-    OPT_KDF_ALGORITHMS, OPT_RANDOM_GENERATORS, OPT_MISSING_HELP, OPT_OBJECTS,
+    OPT_KDF_ALGORITHMS, OPT_RANDOM_GENERATORS, OPT_SERIALIZERS,
+    OPT_MISSING_HELP, OPT_OBJECTS,
 #ifndef OPENSSL_NO_DEPRECATED_3_0
     OPT_ENGINES, 
 #endif
@@ -727,6 +790,7 @@ const OPTIONS list_options[] = {
     {"cipher-commands", OPT_CIPHER_COMMANDS, '-', "List of cipher commands"},
     {"cipher-algorithms", OPT_CIPHER_ALGORITHMS, '-',
      "List of cipher algorithms"},
+    {"serializers", OPT_SERIALIZERS, '-', "List of serialization methods" },
     {"public-key-algorithms", OPT_PK_ALGORITHMS, '-',
      "List of public key algorithms"},
 #ifndef OPENSSL_NO_DEPRECATED_3_0
@@ -735,8 +799,7 @@ const OPTIONS list_options[] = {
     {"engines", OPT_ENGINES, '-',
      "List of loaded engines"},
 #endif
-    {"disabled", OPT_DISABLED, '-',
-     "List of disabled features"},
+    {"disabled", OPT_DISABLED, '-', "List of disabled features"},
     {"missing-help", OPT_MISSING_HELP, '-',
      "List missing detailed help strings"},
     {"options", OPT_OPTIONS, 's',
@@ -762,6 +825,7 @@ int list_main(int argc, char **argv)
         unsigned int mac_algorithms:1;
         unsigned int cipher_commands:1;
         unsigned int cipher_algorithms:1;
+        unsigned int serializer_algorithms:1;
         unsigned int pk_algorithms:1;
         unsigned int pk_method:1;
 #ifndef OPENSSL_NO_DEPRECATED_3_0
@@ -813,6 +877,9 @@ opthelp:
         case OPT_CIPHER_ALGORITHMS:
             todo.cipher_algorithms = 1;
             break;
+        case OPT_SERIALIZERS:
+            todo.serializer_algorithms = 1;
+            break;
         case OPT_PK_ALGORITHMS:
             todo.pk_algorithms = 1;
             break;
@@ -867,6 +934,8 @@ opthelp:
         list_type(FT_cipher, one);
     if (todo.cipher_algorithms)
         list_ciphers();
+    if (todo.serializer_algorithms)
+        list_serializers();
     if (todo.pk_algorithms)
         list_pkey();
 #ifndef OPENSSL_NO_DEPRECATED_3_0
index d1c3a6e02404351aacad26bd844809573160908f..6acf2ea1af9ad5909aeba20e37d609e59e711db4 100644 (file)
@@ -11,6 +11,7 @@
 #include "provider_local.h"
 
 OSSL_provider_init_fn ossl_default_provider_init;
+OSSL_provider_init_fn ossl_base_provider_init;
 OSSL_provider_init_fn ossl_null_provider_init;
 OSSL_provider_init_fn fips_intern_provider_init;
 #ifdef STATIC_LEGACY
@@ -24,6 +25,7 @@ const struct predefined_providers_st predefined_providers[] = {
 # ifdef STATIC_LEGACY
     { "legacy", ossl_legacy_provider_init, 0 },
 # endif
+    { "base", ossl_base_provider_init, 0 },
     { "null", ossl_null_provider_init, 0 },
 #endif
     { NULL, NULL, 0 }
index e13b6c34cfb774ace22389e85ca4070867fe481a..89116888f4277c2127b719794a4942aa7f792e63 100644 (file)
@@ -19,6 +19,7 @@ B<openssl list>
 [B<-random-generators>]
 [B<-cipher-commands>]
 [B<-cipher-algorithms>]
+[B<-serializers>]
 [B<-public-key-algorithms>]
 {- output_off() if $disabled{"deprecated-3.0"}; ""
 -}[B<-public-key-methods>]
@@ -79,7 +80,12 @@ information on what parameters each implementation supports.
 =item B<-random-generators>
 
 Display a list of random number generators.
+See L</Display of algorithm names> for a description of how names are
+displayed.
+
+=item B<-serializers>
 
+Display a list of serializers.
 See L</Display of algorithm names> for a description of how names are
 displayed.
 
diff --git a/doc/man7/OSSL_PROVIDER-base.pod b/doc/man7/OSSL_PROVIDER-base.pod
new file mode 100644 (file)
index 0000000..5896c5a
--- /dev/null
@@ -0,0 +1,96 @@
+=pod
+
+=head1 NAME
+
+OSSL_PROVIDER-base - OpenSSL base provider
+
+=head1 DESCRIPTION
+
+The OpenSSL base provider supplies the serialization for OpenSSL's
+asymmetric cryptography.
+
+=head2 Properties
+
+The implementations in this provider specifically have this property
+defined:
+
+=over 4
+
+=item "provider=base"
+
+=back
+
+It may be used in a property query string with fetching functions.
+
+It isn't mandatory to query for this property, except to make sure to get
+implementations of this provider and none other.
+
+=over 4
+
+=item "type=parameters"
+
+=item "type=private"
+
+=item "type=public"
+
+=back
+
+These may be used in a property query string with fetching functions to select
+which data are to be serialized.  Either the private key material, the public
+key material or the domain parameters can be selected.
+
+=over 4
+
+=item "format=der"
+
+=item "format=pem"
+
+=item "format=text"
+
+=back
+
+These may be used in a property query string with fetching functions to select
+the serialization output format.  Either the DER, PEM and plaintext are
+currently permitted.
+
+=head1 OPERATIONS AND ALGORITHMS
+
+The OpenSSL base provider supports these operations and algorithms:
+
+=head2 Asymmetric Key Serializer
+
+In addition to "provider=base", some of these serializers define the
+property "fips=yes", to allow them to be used together with the FIPS
+provider.
+
+=over 4
+
+=item RSA, see L<OSSL_SERIALIZER-RSA(7)>
+
+=item DH, see L<OSSL_SERIALIZER-DH(7)>
+
+=item DSA, see L<OSSL_SERIALIZER-DSA(7)>
+
+=item EC, see L<OSSL_SERIALIZER-EC(7)>
+
+=item X25519, see L<OSSL_SERIALIZER-X25519(7)>
+
+=item X448, see L<OSSL_SERIALIZER-X448(7)>
+
+=back
+
+=head1 SEE ALSO
+
+L<OSSL_PROVIDER-default(7)>, L<openssl-core.h(7)>,
+L<openssl-core_dispatch.h(7)>, L<provider(7)>
+
+=head1 COPYRIGHT
+
+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
+L<https://www.openssl.org/source/license.html>.
+
+=cut
index d9a51dce0001bed11255241deaf6aeeb66484876..5fe7dbde8c354299dd97dfa44b04c8390d059b11 100644 (file)
@@ -192,9 +192,9 @@ The OpenSSL default provider supports these operations and algorithms:
 
 =head2 Asymmetric Key Serializer
 
-In addition to "provider=default", this set of implementations define the
-property "fips=yes", to allow them to be used together with the FIPS
-provider.
+The default provider also includes all of the serialization algorithms
+present in the base provider.  Some of these have the property "fips=yes",
+to allow them to be used together with the FIPS provider.
 
 =over 4
 
@@ -214,7 +214,8 @@ provider.
 
 =head1 SEE ALSO
 
-L<openssl-core.h(7)>, L<openssl-core_dispatch.h(7)>, L<provider(7)>
+L<openssl-core.h(7)>, L<openssl-core_dispatch.h(7)>, L<provider(7)>,
+L<OSSL_PROVIDER-base(7)>
 
 =head1 COPYRIGHT
 
index 08edb4a1dd5ba8b0ef82aed37cf665c44d19c9e6..62ff8695f14e8d8f90266b389294a5b6ceed4420 100644 (file)
@@ -268,6 +268,14 @@ algorithm identifier to the appropriate fetching function.
 The default provider is built in as part of the F<libcrypto> library.
 Should it be needed (if other providers are loaded and offer
 implementations of the same algorithms), the property "provider=default"
+can be used as a search criterion for these implementations.  The default
+provider includes all the functionality of the base provider below.
+
+=head2 Base provider
+
+The base provider is built in as part of the F<libcrypto> library.
+Should it be needed (if other providers are loaded and offer
+implementations of the same algorithms), the property "provider=base"
 can be used as a search criterion for these implementations. Some
 non-cryptographic algorithms (such as serializers for loading keys and
 parameters from files) are not FIPS algorithm implementations in themselves but
diff --git a/providers/baseprov.c b/providers/baseprov.c
new file mode 100644 (file)
index 0000000..d40535b
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * 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 <string.h>
+#include <stdio.h>
+#include <openssl/opensslconf.h>
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include "prov/bio.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_util.h"
+#include "internal/nelem.h"
+
+/*
+ * Forward declarations to ensure that interface functions are correctly
+ * defined.
+ */
+static OSSL_FUNC_provider_gettable_params_fn base_gettable_params;
+static OSSL_FUNC_provider_get_params_fn base_get_params;
+static OSSL_FUNC_provider_query_operation_fn base_query;
+
+/* Functions provided by the core */
+static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL;
+static OSSL_FUNC_core_get_params_fn *c_get_params = NULL;
+
+/* Parameters we provide to the core */
+static const OSSL_PARAM base_param_types[] = {
+    OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0),
+    OSSL_PARAM_DEFN(OSSL_PROV_PARAM_VERSION, OSSL_PARAM_UTF8_PTR, NULL, 0),
+    OSSL_PARAM_DEFN(OSSL_PROV_PARAM_BUILDINFO, OSSL_PARAM_UTF8_PTR, NULL, 0),
+    OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *base_gettable_params(void *provctx)
+{
+    return base_param_types;
+}
+
+static int base_get_params(void *provctx, OSSL_PARAM params[])
+{
+    OSSL_PARAM *p;
+
+    p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME);
+    if (p != NULL
+            && !OSSL_PARAM_set_utf8_ptr(p, "OpenSSL Base Provider"))
+        return 0;
+    p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_VERSION);
+    if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_VERSION_STR))
+        return 0;
+    p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_BUILDINFO);
+    if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_FULL_VERSION_STR))
+        return 0;
+
+    return 1;
+}
+
+static const OSSL_ALGORITHM base_serializer[] = {
+#define SER(name, fips, format, type, func_table)                           \
+    { name,                                                                 \
+      "provider=base,fips=" fips ",format=" format ",type=" type,           \
+      (func_table) }
+
+#include "serializers.inc"
+    { NULL, NULL, NULL }
+};
+#undef SER
+
+static const OSSL_ALGORITHM *base_query(void *provctx, int operation_id,
+                                         int *no_cache)
+{
+    *no_cache = 0;
+    return operation_id == OSSL_OP_SERIALIZER ? base_serializer : NULL;
+}
+
+static void base_teardown(void *provctx)
+{
+    BIO_meth_free(PROV_CTX_get0_core_bio_method(provctx));
+    PROV_CTX_free(provctx);
+}
+
+/* Functions we provide to the core */
+static const OSSL_DISPATCH base_dispatch_table[] = {
+    { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))base_teardown },
+    { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS,
+      (void (*)(void))base_gettable_params },
+    { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))base_get_params },
+    { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))base_query },
+    { 0, NULL }
+};
+
+OSSL_provider_init_fn ossl_base_provider_init;
+
+int ossl_base_provider_init(const OSSL_CORE_HANDLE *handle,
+                            const OSSL_DISPATCH *in, const OSSL_DISPATCH **out,
+                            void **provctx)
+{
+    OSSL_FUNC_core_get_library_context_fn *c_get_libctx = NULL;
+    BIO_METHOD *corebiometh;
+
+    if (!ossl_prov_bio_from_dispatch(in))
+        return 0;
+    for (; in->function_id != 0; in++) {
+        switch (in->function_id) {
+        case OSSL_FUNC_CORE_GETTABLE_PARAMS:
+            c_gettable_params = OSSL_FUNC_core_gettable_params(in);
+            break;
+        case OSSL_FUNC_CORE_GET_PARAMS:
+            c_get_params = OSSL_FUNC_core_get_params(in);
+            break;
+        case OSSL_FUNC_CORE_GET_LIBRARY_CONTEXT:
+            c_get_libctx = OSSL_FUNC_core_get_library_context(in);
+            break;
+        default:
+            /* Just ignore anything we don't understand */
+            break;
+        }
+    }
+
+    if (c_get_libctx == NULL)
+        return 0;
+
+    /*
+     * We want to make sure that all calls from this provider that requires
+     * a library context use the same context as the one used to call our
+     * functions.  We do that by passing it along in the provider context.
+     *
+     * This only works for built-in providers.  Most providers should
+     * create their own library context.
+     */
+    if ((*provctx = PROV_CTX_new()) == NULL
+            || (corebiometh = bio_prov_init_bio_method()) == NULL) {
+        PROV_CTX_free(*provctx);
+        *provctx = NULL;
+        return 0;
+    }
+    PROV_CTX_set0_library_context(*provctx, (OPENSSL_CTX *)c_get_libctx(handle));
+    PROV_CTX_set0_handle(*provctx, handle);
+    PROV_CTX_set0_core_bio_method(*provctx, corebiometh);
+
+    *out = base_dispatch_table;
+
+    return 1;
+}
index b1bb966b700f228a74d7f993ba7d48efc06a2202..8d82d3f91140e1cf1d425e5f9071fc4b187924e7 100644 (file)
@@ -108,6 +108,16 @@ INCLUDE[$DEFAULTGOAL]=implementations/include
 
 LIBS=$DEFAULTGOAL
 
+#
+# Base provider stuff
+#
+# Because the base provider is built in, it means that libcrypto
+# must include all of the object files that are needed.
+$BASEGOAL=../libcrypto
+SOURCE[$BASEGOAL]=$LIBIMPLEMENTATIONS $LIBNONFIPS
+SOURCE[$BASEGOAL]=baseprov.c
+INCLUDE[$BASEGOAL]=implementations/include
+
 #
 # FIPS provider stuff
 #
index 466b7908a118711c3699807e3d6420cf79d55844..fa6e18fdcac1cba80dfd9573aa85bd17e6c61a37 100644 (file)
@@ -385,154 +385,16 @@ static const OSSL_ALGORITHM deflt_keymgmt[] = {
     { NULL, NULL, NULL }
 };
 
-/*
- * Unlike most algorithms in the default provider, the serializers are allowed
- * for use in FIPS mode because they are not FIPS relevant, and therefore have
- * the "fips=yes" property.
- */
 static const OSSL_ALGORITHM deflt_serializer[] = {
-    { "RSA", "provider=default,fips=yes,format=text,type=private",
-      rsa_priv_text_serializer_functions },
-    { "RSA", "provider=default,fips=yes,format=text,type=public",
-      rsa_pub_text_serializer_functions },
-    { "RSA", "provider=default,fips=yes,format=der,type=private",
-      rsa_priv_der_serializer_functions },
-    { "RSA", "provider=default,fips=yes,format=der,type=public",
-      rsa_pub_der_serializer_functions },
-    { "RSA", "provider=default,fips=yes,format=pem,type=private",
-      rsa_priv_pem_serializer_functions },
-    { "RSA", "provider=default,fips=yes,format=pem,type=public",
-      rsa_pub_pem_serializer_functions },
-    { "RSA-PSS", "provider=default,fips=yes,format=text,type=private",
-      rsa_priv_text_serializer_functions },
-    { "RSA-PSS", "provider=default,fips=yes,format=text,type=public",
-      rsa_pub_text_serializer_functions },
-    { "RSA-PSS", "provider=default,fips=yes,format=der,type=private",
-      rsa_priv_der_serializer_functions },
-    { "RSA-PSS", "provider=default,fips=yes,format=der,type=public",
-      rsa_pub_der_serializer_functions },
-    { "RSA-PSS", "provider=default,fips=yes,format=pem,type=private",
-      rsa_priv_pem_serializer_functions },
-    { "RSA-PSS", "provider=default,fips=yes,format=pem,type=public",
-      rsa_pub_pem_serializer_functions },
-
-#ifndef OPENSSL_NO_DH
-    { "DH", "provider=default,fips=yes,format=text,type=private",
-      dh_priv_text_serializer_functions },
-    { "DH", "provider=default,fips=yes,format=text,type=public",
-      dh_pub_text_serializer_functions },
-    { "DH", "provider=default,fips=yes,format=text,type=parameters",
-      dh_param_text_serializer_functions },
-    { "DH", "provider=default,fips=yes,format=der,type=private",
-      dh_priv_der_serializer_functions },
-    { "DH", "provider=default,fips=yes,format=der,type=public",
-      dh_pub_der_serializer_functions },
-    { "DH", "provider=default,fips=yes,format=der,type=parameters",
-      dh_param_der_serializer_functions },
-    { "DH", "provider=default,fips=yes,format=pem,type=private",
-      dh_priv_pem_serializer_functions },
-    { "DH", "provider=default,fips=yes,format=pem,type=public",
-      dh_pub_pem_serializer_functions },
-    { "DH", "provider=default,fips=yes,format=pem,type=parameters",
-      dh_param_pem_serializer_functions },
-#endif
-
-#ifndef OPENSSL_NO_DSA
-    { "DSA", "provider=default,fips=yes,format=text,type=private",
-      dsa_priv_text_serializer_functions },
-    { "DSA", "provider=default,fips=yes,format=text,type=public",
-      dsa_pub_text_serializer_functions },
-    { "DSA", "provider=default,fips=yes,format=text,type=parameters",
-      dsa_param_text_serializer_functions },
-    { "DSA", "provider=default,fips=yes,format=der,type=private",
-      dsa_priv_der_serializer_functions },
-    { "DSA", "provider=default,fips=yes,format=der,type=public",
-      dsa_pub_der_serializer_functions },
-    { "DSA", "provider=default,fips=yes,format=der,type=parameters",
-      dsa_param_der_serializer_functions },
-    { "DSA", "provider=default,fips=yes,format=pem,type=private",
-      dsa_priv_pem_serializer_functions },
-    { "DSA", "provider=default,fips=yes,format=pem,type=public",
-      dsa_pub_pem_serializer_functions },
-    { "DSA", "provider=default,fips=yes,format=pem,type=parameters",
-      dsa_param_pem_serializer_functions },
-#endif
-
-#ifndef OPENSSL_NO_EC
-    { "X25519", "provider=default,fips=yes,format=text,type=private",
-      x25519_priv_print_serializer_functions },
-    { "X25519", "provider=default,fips=yes,format=text,type=public",
-      x25519_pub_print_serializer_functions },
-    { "X25519", "provider=default,fips=yes,format=der,type=private",
-      x25519_priv_der_serializer_functions },
-    { "X25519", "provider=default,fips=yes,format=der,type=public",
-      x25519_pub_der_serializer_functions },
-    { "X25519", "provider=default,fips=yes,format=pem,type=private",
-      x25519_priv_pem_serializer_functions },
-    { "X25519", "provider=default,fips=yes,format=pem,type=public",
-      x25519_pub_pem_serializer_functions },
-
-    { "X448", "provider=default,format=text,type=private",
-      x448_priv_print_serializer_functions },
-    { "X448", "provider=default,format=text,type=public",
-      x448_pub_print_serializer_functions },
-    { "X448", "provider=default,format=der,type=private",
-      x448_priv_der_serializer_functions },
-    { "X448", "provider=default,format=der,type=public",
-      x448_pub_der_serializer_functions },
-    { "X448", "provider=default,format=pem,type=private",
-      x448_priv_pem_serializer_functions },
-    { "X448", "provider=default,format=pem,type=public",
-      x448_pub_pem_serializer_functions },
-
-    { "ED25519", "provider=default,fips=yes,format=text,type=private",
-      ed25519_priv_print_serializer_functions },
-    { "ED25519", "provider=default,fips=yes,format=text,type=public",
-      ed25519_pub_print_serializer_functions },
-    { "ED25519", "provider=default,fips=yes,format=der,type=private",
-      ed25519_priv_der_serializer_functions },
-    { "ED25519", "provider=default,fips=yes,format=der,type=public",
-      ed25519_pub_der_serializer_functions },
-    { "ED25519", "provider=default,fips=yes,format=pem,type=private",
-      ed25519_priv_pem_serializer_functions },
-    { "ED25519", "provider=default,fips=yes,format=pem,type=public",
-      ed25519_pub_pem_serializer_functions },
-
-    { "ED448", "provider=default,format=text,type=private",
-      ed448_priv_print_serializer_functions },
-    { "ED448", "provider=default,format=text,type=public",
-      ed448_pub_print_serializer_functions },
-    { "ED448", "provider=default,format=der,type=private",
-      ed448_priv_der_serializer_functions },
-    { "ED448", "provider=default,format=der,type=public",
-      ed448_pub_der_serializer_functions },
-    { "ED448", "provider=default,format=pem,type=private",
-      ed448_priv_pem_serializer_functions },
-    { "ED448", "provider=default,format=pem,type=public",
-      ed448_pub_pem_serializer_functions },
-
-    { "EC", "provider=default,fips=yes,format=text,type=private",
-      ec_priv_text_serializer_functions },
-    { "EC", "provider=default,fips=yes,format=text,type=public",
-      ec_pub_text_serializer_functions },
-    { "EC", "provider=default,fips=yes,format=text,type=parameters",
-      ec_param_text_serializer_functions },
-    { "EC", "provider=default,fips=yes,format=der,type=private",
-      ec_priv_der_serializer_functions },
-    { "EC", "provider=default,fips=yes,format=der,type=public",
-      ec_pub_der_serializer_functions },
-    { "EC", "provider=default,fips=yes,format=der,type=parameters",
-      ec_param_der_serializer_functions },
-    { "EC", "provider=default,fips=yes,format=pem,type=private",
-      ec_priv_pem_serializer_functions },
-    { "EC", "provider=default,fips=yes,format=pem,type=public",
-      ec_pub_pem_serializer_functions },
-    { "EC", "provider=default,fips=yes,format=pem,type=parameters",
-      ec_param_pem_serializer_functions },
-#endif
+#define SER(name, fips, format, type, func_table)                           \
+    { name,                                                                 \
+      "provider=default,fips=" fips ",format=" format ",type=" type,  \
+      (func_table) }
 
+#include "serializers.inc"
     { NULL, NULL, NULL }
 };
+#undef SER
 
 static const OSSL_ALGORITHM deflt_deserializer[] = {
     { "RSA", "provider=default,fips=yes,input=der",
diff --git a/providers/serializers.inc b/providers/serializers.inc
new file mode 100644 (file)
index 0000000..3143ebb
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * 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 SER
+# error Macro SER undefined
+#endif
+
+    SER("RSA", "yes", "text", "private", rsa_priv_text_serializer_functions),
+    SER("RSA", "yes", "text", "public", rsa_pub_text_serializer_functions),
+    SER("RSA", "yes", "der", "private", rsa_priv_der_serializer_functions),
+    SER("RSA", "yes", "der", "public", rsa_pub_der_serializer_functions),
+    SER("RSA", "yes", "pem", "private", rsa_priv_pem_serializer_functions),
+    SER("RSA", "yes", "pem", "public", rsa_pub_pem_serializer_functions),
+    SER("RSA-PSS", "yes", "text", "private",
+        rsa_priv_text_serializer_functions),
+    SER("RSA-PSS", "yes", "text", "public", rsa_pub_text_serializer_functions),
+    SER("RSA-PSS", "yes", "der", "private", rsa_priv_der_serializer_functions),
+    SER("RSA-PSS", "yes", "der", "public", rsa_pub_der_serializer_functions),
+    SER("RSA-PSS", "yes", "pem", "private", rsa_priv_pem_serializer_functions),
+    SER("RSA-PSS", "yes", "pem", "public", rsa_pub_pem_serializer_functions),
+
+#ifndef OPENSSL_NO_DH
+    SER("DH", "yes", "text", "private", dh_priv_text_serializer_functions),
+    SER("DH", "yes", "text", "public", dh_pub_text_serializer_functions),
+    SER("DH", "yes", "text", "parameters", dh_param_text_serializer_functions),
+    SER("DH", "yes", "der", "private", dh_priv_der_serializer_functions),
+    SER("DH", "yes", "der", "public", dh_pub_der_serializer_functions),
+    SER("DH", "yes", "der", "parameters", dh_param_der_serializer_functions),
+    SER("DH", "yes", "pem", "private", dh_priv_pem_serializer_functions),
+    SER("DH", "yes", "pem", "public", dh_pub_pem_serializer_functions),
+    SER("DH", "yes", "pem", "parameters", dh_param_pem_serializer_functions),
+#endif
+
+#ifndef OPENSSL_NO_DSA
+    SER("DSA", "yes", "text", "private", dsa_priv_text_serializer_functions),
+    SER("DSA", "yes", "text", "public", dsa_pub_text_serializer_functions),
+    SER("DSA", "yes", "text", "parameters",
+        dsa_param_text_serializer_functions),
+    SER("DSA", "yes", "der", "private", dsa_priv_der_serializer_functions),
+    SER("DSA", "yes", "der", "public", dsa_pub_der_serializer_functions),
+    SER("DSA", "yes", "der", "parameters", dsa_param_der_serializer_functions),
+    SER("DSA", "yes", "pem", "private", dsa_priv_pem_serializer_functions),
+    SER("DSA", "yes", "pem", "public", dsa_pub_pem_serializer_functions),
+    SER("DSA", "yes", "pem", "parameters", dsa_param_pem_serializer_functions),
+#endif
+
+#ifndef OPENSSL_NO_EC
+    SER("X25519", "yes", "text", "private",
+        x25519_priv_print_serializer_functions),
+    SER("X25519", "yes", "text", "public",
+        x25519_pub_print_serializer_functions),
+    SER("X25519", "yes", "der", "private",
+        x25519_priv_der_serializer_functions),
+    SER("X25519", "yes", "der", "public", x25519_pub_der_serializer_functions),
+    SER("X25519", "yes", "pem", "private",
+        x25519_priv_pem_serializer_functions),
+    SER("X25519", "yes", "pem", "public", x25519_pub_pem_serializer_functions),
+
+    SER("X448", "no", "text", "private", x448_priv_print_serializer_functions),
+    SER("X448", "no", "text", "public", x448_pub_print_serializer_functions),
+    SER("X448", "no", "der", "private", x448_priv_der_serializer_functions),
+    SER("X448", "no", "der", "public", x448_pub_der_serializer_functions),
+    SER("X448", "no", "pem", "private", x448_priv_pem_serializer_functions),
+    SER("X448", "no", "pem", "public", x448_pub_pem_serializer_functions),
+
+    SER("ED25519", "yes", "text", "private",
+        ed25519_priv_print_serializer_functions),
+    SER("ED25519", "yes", "text", "public",
+        ed25519_pub_print_serializer_functions),
+    SER("ED25519", "yes", "der", "private",
+        ed25519_priv_der_serializer_functions),
+    SER("ED25519", "yes", "der", "public",
+        ed25519_pub_der_serializer_functions),
+    SER("ED25519", "yes", "pem", "private",
+        ed25519_priv_pem_serializer_functions),
+    SER("ED25519", "yes", "pem", "public",
+        ed25519_pub_pem_serializer_functions),
+
+    SER("ED448", "no", "text", "private",
+        ed448_priv_print_serializer_functions),
+    SER("ED448", "no", "text", "public", ed448_pub_print_serializer_functions),
+    SER("ED448", "no", "der", "private", ed448_priv_der_serializer_functions),
+    SER("ED448", "no", "der", "public", ed448_pub_der_serializer_functions),
+    SER("ED448", "no", "pem", "private", ed448_priv_pem_serializer_functions),
+    SER("ED448", "no", "pem", "public", ed448_pub_pem_serializer_functions),
+
+    SER("EC", "yes", "text", "private", ec_priv_text_serializer_functions),
+    SER("EC", "yes", "text", "public", ec_pub_text_serializer_functions),
+    SER("EC", "yes", "text", "parameters", ec_param_text_serializer_functions),
+    SER("EC", "yes", "der", "private", ec_priv_der_serializer_functions),
+    SER("EC", "yes", "der", "public", ec_pub_der_serializer_functions),
+    SER("EC", "yes", "der", "parameters", ec_param_der_serializer_functions),
+    SER("EC", "yes", "pem", "private", ec_priv_pem_serializer_functions),
+    SER("EC", "yes", "pem", "public", ec_pub_pem_serializer_functions),
+    SER("EC", "yes", "pem", "parameters", ec_param_pem_serializer_functions),
+#endif