]> www.wagner.pp.ru Git - openssl-gost/engine.git/blobdiff - test_ciphers.c
MSVC: Do not build in library form
[openssl-gost/engine.git] / test_ciphers.c
index a88c28154497d7c321e6cde547df705aee09573f..60384988e40f43a012ea93768ae5fbf887af18b6 100644 (file)
@@ -5,19 +5,32 @@
  * See https://www.openssl.org/source/license.html for details
  */
 
+#ifdef _MSC_VER
+# pragma warning(push, 3)
+# include <openssl/applink.c>
+# pragma warning(pop)
+#endif
 #include <openssl/engine.h>
+#include <openssl/provider.h>
 #include <openssl/evp.h>
 #include <openssl/rand.h>
 #include <openssl/err.h>
 #include <openssl/asn1.h>
 #include <string.h>
 
-#define T(e) ({ \
-    if (!(e)) {\
-       ERR_print_errors_fp(stderr);\
-       OpenSSLDie(__FILE__, __LINE__, #e);\
-    } \
-})
+#if defined _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+#elif defined __linux__
+# include <alloca.h>
+#endif
+#include <stdlib.h>
+
+#define T(e) \
+    if (!(e)) { \
+       ERR_print_errors_fp(stderr); \
+       OpenSSLDie(__FILE__, __LINE__, #e); \
+    }
 
 #define cRED   "\033[1;31m"
 #define cDRED  "\033[0;31m"
             else \
                 printf(cGREEN "Test passed" cNORM "\n");}
 
+#ifdef __GNUC__
 /* Pragma to allow commenting out some tests. */
-#pragma GCC diagnostic ignored "-Wunused-const-variable"
+# pragma GCC diagnostic ignored "-Wunused-const-variable"
+#endif
 
 /*
  * Test keys from both GOST R 34.12-2015 and GOST R 34.13-2015,
@@ -170,7 +185,7 @@ static const unsigned char iv_128bit[]      = { 0x12,0x34,0x56,0x78,0x90,0xab,0xce,0x
 static const unsigned char iv_acpkm_m[]        = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
 
 static struct testcase {
-    int nid;
+    const char *algname;
     int block; /* Actual underlying block size (bytes). */
     int stream; /* Stream cipher. */
     const unsigned char *plaintext;
@@ -182,7 +197,7 @@ static struct testcase {
     int acpkm;
 } testcases[] = {
     {
-       .nid = NID_grasshopper_ecb,
+       .algname = SN_grasshopper_ecb,
        .block = 16,
        .plaintext = P,
        .key = K,
@@ -190,7 +205,7 @@ static struct testcase {
        .size = sizeof(P),
     },
     {
-       .nid = NID_grasshopper_ctr,
+       .algname = SN_grasshopper_ctr,
        .block = 16,
        .stream = 1,
        .plaintext = P,
@@ -201,7 +216,7 @@ static struct testcase {
        .iv_size = sizeof(iv_ctr),
     },
     {
-       .nid = NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm,
+       .algname = SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm,
        .block = 16,
        .stream = 1,
        .plaintext = P,
@@ -213,7 +228,7 @@ static struct testcase {
        /* no acpkm works same as ctr */
     },
     {
-       .nid = NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm,
+       .algname = SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm,
        .block = 16,
        .stream = 1,
        .plaintext = P_acpkm,
@@ -225,7 +240,7 @@ static struct testcase {
        .acpkm = 256 / 8,
     },
     {
-       .nid = NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm,
+       .algname = SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm,
        .block = 16,
        .plaintext = P_acpkm_master,
        .key = K,
@@ -236,7 +251,7 @@ static struct testcase {
        .acpkm = 768 / 8
     },
     {
-       .nid = NID_grasshopper_ofb,
+       .algname = SN_grasshopper_ofb,
        .block = 16,
        .stream = 1,
        .plaintext = P,
@@ -247,7 +262,7 @@ static struct testcase {
        .iv_size = sizeof(iv_128bit),
     },
     {
-       .nid = NID_grasshopper_cbc,
+       .algname = SN_grasshopper_cbc,
        .block = 16,
        .plaintext = P,
        .key = K,
@@ -257,7 +272,7 @@ static struct testcase {
        .iv_size = sizeof(iv_128bit),
     },
     {
-       .nid = NID_grasshopper_cfb,
+       .algname = SN_grasshopper_cfb,
        .block = 16,
        .plaintext = P,
        .key = K,
@@ -267,7 +282,7 @@ static struct testcase {
        .iv_size = sizeof(iv_128bit),
     },
     {
-       .nid = NID_magma_ctr,
+       .algname = SN_magma_ctr,
        .block = 8,
        .plaintext = Pm,
        .key = Km,
@@ -277,7 +292,7 @@ static struct testcase {
        .iv_size = sizeof(iv_ctr) / 2,
     },
     {
-       .nid = NID_magma_cbc,
+       .algname = SN_magma_cbc,
        .block = 8,
        .plaintext = Pm,
        .key = Km,
@@ -303,12 +318,12 @@ static void hexdump(const void *ptr, size_t len)
 
 static int test_block(const EVP_CIPHER *type, const char *name, int block_size,
     const unsigned char *pt, const unsigned char *key, const unsigned char *exp,
-    size_t size, const unsigned char *iv, size_t iv_size, int acpkm,
+    const size_t size, const unsigned char *iv, size_t iv_size, int acpkm,
     int inplace)
 {
     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
     const char *standard = acpkm? "R 23565.1.017-2018" : "GOST R 34.13-2015";
-    unsigned char c[size];
+    unsigned char *c = alloca(size);
     int outlen, tmplen;
     int ret = 0, test;
 
@@ -331,9 +346,18 @@ static int test_block(const EVP_CIPHER *type, const char *name, int block_size,
     if (inplace)
        memcpy(c, pt, size);
     else
-       memset(c, 0, sizeof(c));
-    if (acpkm)
-       T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, acpkm, NULL));
+       memset(c, 0, size);
+    if (acpkm) {
+       if (EVP_CIPHER_get0_provider(type) != NULL) {
+           OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+           size_t v = (size_t)acpkm;
+
+           params[0] = OSSL_PARAM_construct_size_t("key-mesh", &v);
+           T(EVP_CIPHER_CTX_set_params(ctx, params));
+       } else {
+           T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, acpkm, NULL));
+       }
+    }
     T(EVP_CipherUpdate(ctx, c, &outlen, inplace? c : pt, size));
     T(EVP_CipherFinal_ex(ctx, c + outlen, &tmplen));
     EVP_CIPHER_CTX_cleanup(ctx);
@@ -356,9 +380,18 @@ static int test_block(const EVP_CIPHER *type, const char *name, int block_size,
     if (inplace)
        memcpy(c, pt, size);
     else
-       memset(c, 0, sizeof(c));
-    if (acpkm)
-       T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, acpkm, NULL));
+       memset(c, 0, size);
+    if (acpkm) {
+       if (EVP_CIPHER_get0_provider(type) != NULL) {
+           OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+           size_t v = (size_t)acpkm;
+
+           params[0] = OSSL_PARAM_construct_size_t("key-mesh", &v);
+           T(EVP_CIPHER_CTX_set_params(ctx, params));
+       } else {
+           T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, acpkm, NULL));
+       }
+    }
     for (z = 0; z < blocks; z++) {
        int offset = z * block_size;
        int sz = block_size;
@@ -385,9 +418,18 @@ static int test_block(const EVP_CIPHER *type, const char *name, int block_size,
     if (inplace)
        memcpy(c, exp, size);
     else
-       memset(c, 0, sizeof(c));
-    if (acpkm)
-       T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, acpkm, NULL));
+       memset(c, 0, size);
+    if (acpkm) {
+       if (EVP_CIPHER_get0_provider(type) != NULL) {
+           OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+           size_t v = (size_t)acpkm;
+
+           params[0] = OSSL_PARAM_construct_size_t("key-mesh", &v);
+           T(EVP_CIPHER_CTX_set_params(ctx, params));
+       } else {
+           T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, acpkm, NULL));
+       }
+    }
     T(EVP_CipherUpdate(ctx, c, &outlen, inplace ? c : exp, size));
     T(EVP_CipherFinal_ex(ctx, c + outlen, &tmplen));
     EVP_CIPHER_CTX_cleanup(ctx);
@@ -405,10 +447,11 @@ static int test_block(const EVP_CIPHER *type, const char *name, int block_size,
 
 static int test_stream(const EVP_CIPHER *type, const char *name,
     const unsigned char *pt, const unsigned char *key, const unsigned char *exp,
-    size_t size, const unsigned char *iv, size_t iv_size, int acpkm)
+    const size_t size, const unsigned char *iv, size_t iv_size, int acpkm)
 {
     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
     const char *standard = acpkm? "R 23565.1.017-2018" : "GOST R 34.13-2015";
+    unsigned char *c = alloca(size);
     int ret = 0, test;
     int z;
 
@@ -420,7 +463,6 @@ static int test_stream(const EVP_CIPHER *type, const char *name,
     T(EVP_CIPHER_block_size(type) == 1);
 
     for (z = 1; z <= size; z++) {
-       unsigned char c[size];
        int outlen, tmplen;
        int sz = 0;
        int i;
@@ -428,9 +470,18 @@ static int test_stream(const EVP_CIPHER *type, const char *name,
        EVP_CIPHER_CTX_init(ctx);
        T(EVP_CipherInit_ex(ctx, type, NULL, key, iv, 1));
        T(EVP_CIPHER_CTX_set_padding(ctx, 0));
-       memset(c, 0xff, sizeof(c));
-       if (acpkm)
-           T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, acpkm, NULL));
+       memset(c, 0xff, size);
+       if (acpkm) {
+           if (EVP_CIPHER_get0_provider(type) != NULL) {
+               OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+               size_t v = (size_t)acpkm;
+
+               params[0] = OSSL_PARAM_construct_size_t("key-mesh", &v);
+               T(EVP_CIPHER_CTX_set_params(ctx, params));
+           } else {
+               T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, acpkm, NULL));
+           }
+       }
        for (i = 0; i < size; i += z) {
            if (i + z > size)
                sz = size - i;
@@ -454,6 +505,64 @@ static int test_stream(const EVP_CIPHER *type, const char *name,
     return ret;
 }
 
+int engine_is_available(const char *name)
+{
+    ENGINE *e = ENGINE_get_first();
+
+    while (e != NULL) {
+        if (strcmp(ENGINE_get_id(e), name) == 0)
+            break;
+        e = ENGINE_get_next(e);
+    }
+    ENGINE_free(e);
+    return 0;
+}
+
+void warn_if_untested(const EVP_CIPHER *ciph, void *provider)
+{
+    const struct testcase *t;
+
+    /* ENGINE provided EVP_MDs have a NULL provider */
+    if (provider != EVP_CIPHER_get0_provider(ciph))
+        return;
+
+    for (t = testcases; t->algname; t++)
+        if (EVP_CIPHER_is_a(ciph, t->algname))
+            break;
+    if (!t->algname)
+        printf(cMAGENT "Cipher %s is untested!" cNORM "\n", EVP_CIPHER_name(ciph));
+}
+
+void warn_all_untested(void)
+{
+    if (engine_is_available("gost")) {
+        ENGINE *eng;
+
+        T(eng = ENGINE_by_id("gost"));
+        T(ENGINE_init(eng));
+
+        ENGINE_CIPHERS_PTR fn_c;
+        T(fn_c = ENGINE_get_ciphers(eng));
+        const int *nids;
+        int n, k;
+        n = fn_c(eng, NULL, &nids, 0);
+        for (k = 0; k < n; ++k)
+            warn_if_untested(ENGINE_get_cipher(eng, nids[k]), NULL);
+        ENGINE_finish(eng);
+        ENGINE_free(eng);
+    }
+    if (OSSL_PROVIDER_available(NULL, "gostprov")) {
+        OSSL_PROVIDER *prov;
+
+        T(prov = OSSL_PROVIDER_load(NULL, "gostprov"));
+        EVP_CIPHER_do_all_provided(NULL,
+                                   (void (*)(EVP_CIPHER *, void *))warn_if_untested,
+                                   prov);
+
+        OSSL_PROVIDER_unload(prov);
+    }
+}
+
 int main(int argc, char **argv)
 {
     int ret = 0;
@@ -465,39 +574,31 @@ int main(int argc, char **argv)
 #endif
     OPENSSL_add_all_algorithms_conf();
 
-    for (t = testcases; t->nid; t++) {
+    for (t = testcases; t->algname; t++) {
        int inplace;
        const char *standard = t->acpkm? "R 23565.1.017-2018" : "GOST R 34.13-2015";
 
-       const EVP_CIPHER *type = EVP_get_cipherbynid(t->nid);
-       const char *name = EVP_CIPHER_name(type);
+       EVP_CIPHER *ciph;
+
+       ERR_set_mark();
+       T((ciph = (EVP_CIPHER *)EVP_get_cipherbyname(t->algname))
+         || (ciph = EVP_CIPHER_fetch(NULL, t->algname, NULL)));
+       ERR_pop_to_mark();
 
-       printf(cBLUE "# Tests for %s [%s]" cNORM "\n", name, standard);
+       printf(cBLUE "# Tests for %s [%s]" cNORM "\n", t->algname, standard);
        for (inplace = 0; inplace <= 1; inplace++)
-           ret |= test_block(type, name, t->block,
+           ret |= test_block(ciph, t->algname, t->block,
                t->plaintext, t->key, t->expected, t->size,
                t->iv, t->iv_size, t->acpkm, inplace);
        if (t->stream)
-           ret |= test_stream(type, name,
+           ret |= test_stream(ciph, t->algname,
                t->plaintext, t->key, t->expected, t->size,
                t->iv, t->iv_size, t->acpkm);
-    }
 
-    ENGINE *eng;
-    ENGINE_CIPHERS_PTR fn_c;
-    T(eng = ENGINE_by_id("gost"));
-    T(fn_c = ENGINE_get_ciphers(eng));
-    const int *nids;
-    int n, k;
-    n = fn_c(eng, NULL, &nids, 0);
-    for (k = 0; k < n; ++k) {
-       for (t = testcases; t->nid; t++)
-           if (t->nid == nids[k])
-               break;
-       if (!t->nid)
-           printf(cMAGENT "Cipher %s is untested!" cNORM "\n", OBJ_nid2sn(nids[k]));
+       EVP_CIPHER_free(ciph);
     }
-    ENGINE_free(eng);
+
+    warn_all_untested();
 
     if (ret)
        printf(cDRED "= Some tests FAILED!" cNORM "\n");