]> www.wagner.pp.ru Git - openssl-gost/engine.git/blobdiff - gost_eng.c
Also build gost-engine in library form
[openssl-gost/engine.git] / gost_eng.c
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