]> www.wagner.pp.ru Git - openssl-gost/engine.git/commitdiff
Also build gost-engine in library form
authorRichard Levitte <richard@levitte.org>
Wed, 17 Feb 2021 18:01:19 +0000 (19:01 +0100)
committerDmitry Belyavskiy <beldmit@users.noreply.github.com>
Mon, 22 Feb 2021 08:11:38 +0000 (09:11 +0100)
In this form, the GOST engine isn't loadable through OpenSSL's dynamic
ENGINE loader, but directly as its own function, ENGINE_load_gost().
After making that call, the engine functionality can be used as usual.
This includes a public header file called gost-engine.h, which declares
that functions.

This also rearranges the code in gost_eng.c, as the binding
functionality was spread around in the file.  Now, it's all nicely
tucked at the end.

CMakeLists.txt
gost-engine.h [new file with mode: 0644]
gost_eng.c

index c32b90f233d205be3811cb1118f6be33222c727b..ed2d44f33fd724ebd9251e89692c636c4d858fd3 100644 (file)
@@ -275,6 +275,7 @@ set_property(TARGET ${BINARY_TESTS_TARGETS} APPEND PROPERTY COMPILE_DEFINITIONS
 add_library(gost_core STATIC ${GOST_LIB_SOURCE_FILES})
 set_target_properties(gost_core PROPERTIES POSITION_INDEPENDENT_CODE ON)
 
+# The GOST engine in module form
 add_library(gost_engine MODULE ${GOST_ENGINE_SOURCE_FILES})
 # Set the suffix explicitly to adapt to OpenSSL's idea of what a
 # module suffix should be
@@ -282,6 +283,15 @@ set_target_properties(gost_engine PROPERTIES
   PREFIX "" OUTPUT_NAME "gost" SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX})
 target_link_libraries(gost_engine gost_core ${OPENSSL_CRYPTO_LIBRARY})
 
+# The GOST engine in library form
+add_library(lib_gost_engine SHARED ${GOST_ENGINE_SOURCE_FILES})
+set_target_properties(lib_gost_engine PROPERTIES
+  COMPILE_DEFINITIONS "BUILDING_ENGINE_AS_LIBRARY"
+  PUBLIC_HEADER gost-engine.h
+  OUTPUT_NAME "gost")
+target_link_libraries(lib_gost_engine gost_core ${OPENSSL_CRYPTO_LIBRARY})
+
+
 set(GOST_SUM_SOURCE_FILES
         gostsum.c
         )
diff --git a/gost-engine.h b/gost-engine.h
new file mode 100644 (file)
index 0000000..da292c3
--- /dev/null
@@ -0,0 +1,14 @@
+/**********************************************************************
+ *                            gost-engine.h                           *
+ *                     GOST engine in library form                    *
+ *                                                                    *
+ *      Copyright (c) 2021 Richard Levitte <richard@levitte.org>      *
+ *     This file is distributed under the same license as OpenSSL     *
+ *                                                                    *
+ **********************************************************************/
+#ifndef GOST_ENGINE_H
+# define GOST_ENGINE_H
+
+void ENGINE_load_gost(void);
+
+#endif
index f930faa2f5e2043911206be1ecffd13e33728b0a..d2371d297640d3f82d53a339a7838f9b1003fc5d 100644 (file)
@@ -16,6 +16,7 @@
 #include <openssl/obj_mac.h>
 #include "e_gost_err.h"
 #include "gost_lcl.h"
+#include "gost-engine.h"
 
 #include "gost_grasshopper_cipher.h"
 
@@ -190,6 +191,101 @@ static int known_cipher_nids[OSSL_NELEM(gost_cipher_array)];
 /* `- 1' because of terminating zero element */
 static int known_meths_nids[OSSL_NELEM(gost_meth_array) - 1];
 
+/* ENGINE_DIGESTS_PTR callback installed by ENGINE_set_digests */
+static int gost_digests(ENGINE *e, const EVP_MD **digest,
+                        const int **nids, int nid)
+{
+    int i;
+
+    if (!digest) {
+        int *n = known_digest_nids;
+
+        *nids = n;
+        for (i = 0; i < OSSL_NELEM(gost_digest_array); i++)
+            *n++ = gost_digest_array[i]->nid;
+        return i;
+    }
+
+    for (i = 0; i < OSSL_NELEM(gost_digest_array); i++)
+        if (nid == gost_digest_array[i]->nid) {
+            *digest = GOST_init_digest(gost_digest_array[i]);
+            return 1;
+        }
+    *digest = NULL;
+    return 0;
+}
+
+/* ENGINE_CIPHERS_PTR callback installed by ENGINE_set_ciphers */
+static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
+                        const int **nids, int nid)
+{
+    int i;
+
+    if (!cipher) {
+        int *n = known_cipher_nids;
+
+        *nids = n;
+        for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++)
+            *n++ = gost_cipher_array[i]->nid;
+        return i;
+    }
+
+    for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++)
+        if (nid == gost_cipher_array[i]->nid) {
+            *cipher = GOST_init_cipher(gost_cipher_array[i]);
+            return 1;
+        }
+    *cipher = NULL;
+    return 0;
+}
+
+static int gost_meth_nids(const int **nids)
+{
+    struct gost_meth_minfo *info = gost_meth_array;
+    int *n = known_meths_nids;
+
+    *nids = n;
+    for (; info->nid; info++)
+        *n++ = info->nid;
+    return OSSL_NELEM(known_meths_nids);
+}
+
+/* ENGINE_PKEY_METHS_PTR installed by ENGINE_set_pkey_meths */
+static int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
+                           const int **nids, int nid)
+{
+    struct gost_meth_minfo *info;
+
+    if (!pmeth)
+        return gost_meth_nids(nids);
+
+    for (info = gost_meth_array; info->nid; info++)
+        if (nid == info->nid) {
+            *pmeth = *info->pmeth;
+            return 1;
+        }
+    *pmeth = NULL;
+    return 0;
+}
+
+/* ENGINE_PKEY_ASN1_METHS_PTR installed by ENGINE_set_pkey_asn1_meths */
+static int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
+                                const int **nids, int nid)
+{
+    struct gost_meth_minfo *info;
+
+    if (!ameth)
+        return gost_meth_nids(nids);
+
+    for (info = gost_meth_array; info->nid; info++)
+        if (nid == info->nid) {
+            *ameth = *info->ameth;
+            return 1;
+        }
+    *ameth = NULL;
+    return 0;
+}
+
 static int gost_engine_init(ENGINE* e) {
     return 1;
 }
@@ -219,14 +315,16 @@ static int gost_engine_destroy(ENGINE* e) {
     return 1;
 }
 
-static int bind_gost(ENGINE* e, const char* id) {
+/*
+ * Following is the glue that populates the ENGINE structure and that
+ * binds it to OpenSSL libraries
+ */
+
+static int populate_gost_engine(ENGINE* e) {
     int ret = 0;
-    if (id != NULL && strcmp(id, engine_gost_id) != 0)
-        return 0;
-    if (ameth_GostR3410_2001) {
-        printf("GOST engine already loaded\n");
+
+    if (e == NULL)
         goto end;
-    }
     if (!ENGINE_set_id(e, engine_gost_id)) {
         printf("ENGINE_set_id failed\n");
         goto end;
@@ -266,6 +364,12 @@ static int bind_gost(ENGINE* e, const char* id) {
         goto end;
     }
 
+    /*
+     * "register" in "register_ameth_gost" and "register_pmeth_gost" is
+     * not registering in an ENGINE sense, where things are hooked into
+     * OpenSSL's library.  "register_ameth_gost" and "register_pmeth_gost"
+     * merely allocate and populate the method structures of this engine.
+     */
     struct gost_meth_minfo *minfo = gost_meth_array;
     for (; minfo->nid; minfo++) {
 
@@ -280,6 +384,14 @@ static int bind_gost(ENGINE* e, const char* id) {
             goto end;
     }
 
+    ret = 1;
+  end:
+    return ret;
+}
+
+static int bind_gost_engine(ENGINE* e) {
+    int ret = 0;
+
     if (!ENGINE_register_ciphers(e)
         || !ENGINE_register_digests(e)
         || !ENGINE_register_pkey_meths(e))
@@ -300,133 +412,57 @@ static int bind_gost(ENGINE* e, const char* id) {
 
     ERR_load_GOST_strings();
     ret = 1;
-    end:
+  end:
     return ret;
 }
 
-#ifndef OPENSSL_NO_DYNAMIC_ENGINE
-IMPLEMENT_DYNAMIC_BIND_FN(bind_gost)
-    IMPLEMENT_DYNAMIC_CHECK_FN()
-#endif                          /* ndef OPENSSL_NO_DYNAMIC_ENGINE */
-
-/* ENGINE_DIGESTS_PTR callback installed by ENGINE_set_digests */
-static int gost_digests(ENGINE *e, const EVP_MD **digest,
-                        const int **nids, int nid)
+static int check_gost_engine(ENGINE* e, const char* id)
 {
-    int i;
-
-    if (!digest) {
-        int *n = known_digest_nids;
-
-        *nids = n;
-        for (i = 0; i < OSSL_NELEM(gost_digest_array); i++)
-            *n++ = gost_digest_array[i]->nid;
-        return i;
-    }
-
-    for (i = 0; i < OSSL_NELEM(gost_digest_array); i++)
-        if (nid == gost_digest_array[i]->nid) {
-            *digest = GOST_init_digest(gost_digest_array[i]);
-            return 1;
-        }
-    *digest = NULL;
-    return 0;
-}
-
-/* ENGINE_CIPHERS_PTR callback installed by ENGINE_set_ciphers */
-static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
-                        const int **nids, int nid)
-{
-    int i;
-
-    if (!cipher) {
-        int *n = known_cipher_nids;
-
-        *nids = n;
-        for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++)
-            *n++ = gost_cipher_array[i]->nid;
-        return i;
+    if (id != NULL && strcmp(id, engine_gost_id) != 0)
+        return 0;
+    if (ameth_GostR3410_2001) {
+        printf("GOST engine already loaded\n");
+        return 0;
     }
-
-    for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++)
-        if (nid == gost_cipher_array[i]->nid) {
-            *cipher = GOST_init_cipher(gost_cipher_array[i]);
-            return 1;
-        }
-    *cipher = NULL;
-    return 0;
+    return 1;
 }
 
-static int gost_meth_nids(const int **nids)
+static int make_gost_engine(ENGINE* e, const char* id)
 {
-    struct gost_meth_minfo *info = gost_meth_array;
-    int *n = known_meths_nids;
-
-    *nids = n;
-    for (; info->nid; info++)
-        *n++ = info->nid;
-    return OSSL_NELEM(known_meths_nids);
+    return check_gost_engine(e, id)
+        && populate_gost_engine(e)
+        && bind_gost_engine(e);
 }
 
-/* ENGINE_PKEY_METHS_PTR installed by ENGINE_set_pkey_meths */
-static int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
-                           const int **nids, int nid)
-{
-    struct gost_meth_minfo *info;
+#ifndef BUILDING_ENGINE_AS_LIBRARY
 
-    if (!pmeth)
-        return gost_meth_nids(nids);
+/*
+ * When building gost-engine as a dynamically loadable module, these two
+ * lines do everything that's needed, and OpenSSL's libcrypto will be able
+ * to call its entry points, v_check and bind_engine.
+ */
 
-    for (info = gost_meth_array; info->nid; info++)
-        if (nid == info->nid) {
-            *pmeth = *info->pmeth;
-            return 1;
-        }
-    *pmeth = NULL;
-    return 0;
-}
+IMPLEMENT_DYNAMIC_BIND_FN(make_gost_engine)
+IMPLEMENT_DYNAMIC_CHECK_FN()
 
-/* ENGINE_PKEY_ASN1_METHS_PTR installed by ENGINE_set_pkey_asn1_meths */
-static int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
-                                const int **nids, int nid)
-{
-    struct gost_meth_minfo *info;
+#else
 
-    if (!ameth)
-        return gost_meth_nids(nids);
-
-    for (info = gost_meth_array; info->nid; info++)
-        if (nid == info->nid) {
-            *ameth = *info->ameth;
-            return 1;
-        }
-    *ameth = NULL;
-    return 0;
-}
-
-#ifdef OPENSSL_NO_DYNAMIC_ENGINE
-
-static ENGINE* engine_gost(void) {
-    ENGINE* ret = ENGINE_new();
-    if (!ret)
-        return NULL;
-    if (!bind_gost(ret, engine_gost_id)) {
-        ENGINE_free(ret);
-        return NULL;
-    }
-    return ret;
-}
+/*
+ * When building gost-engine as a shared library, the application that uses
+ * it must manually call ENGINE_load_gost() for it to bind itself into the
+ * libcrypto libraries.
+ */
 
 void ENGINE_load_gost(void) {
     ENGINE* toadd;
-    if (pmeth_GostR3410_2001)
-        return;
-    toadd = engine_gost();
-    if (!toadd)
-        return;
-    ENGINE_add(toadd);
+    int ret = 0;
+
+    if ((toadd = ENGINE_new()) != NULL
+        && (ret = make_gost_engine(toadd, engine_gost_id)) > 0)
+        ENGINE_add(toadd);
     ENGINE_free(toadd);
-    ERR_clear_error();
+    if (ret > 0)
+        ERR_clear_error();
 }
 
 #endif