]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - test_context.c
test_context: Instantiate ciphers using EVP API instead of direct calls
[openssl-gost/engine.git] / test_context.c
1 /*
2  * Copyright (C) 2018 vt@altlinux.org. All Rights Reserved.
3  *
4  * Contents licensed under the terms of the OpenSSL license
5  * See https://www.openssl.org/source/license.html for details
6  */
7
8 #include <openssl/engine.h>
9 #include <openssl/evp.h>
10 #include <openssl/rand.h>
11 #include <openssl/err.h>
12 #include <openssl/asn1.h>
13 #include <string.h>
14
15 #define T(e) if (!(e)) {\
16         ERR_print_errors_fp(stderr);\
17         OpenSSLDie(__FILE__, __LINE__, #e);\
18     }
19
20 #define cRED    "\033[1;31m"
21 #define cDRED   "\033[0;31m"
22 #define cGREEN  "\033[1;32m"
23 #define cDGREEN "\033[0;32m"
24 #define cBLUE   "\033[1;34m"
25 #define cDBLUE  "\033[0;34m"
26 #define cNORM   "\033[m"
27 #define TEST_ASSERT(e) {if ((test = (e))) \
28                  printf(cRED "  Test FAILED\n" cNORM); \
29              else \
30                  printf(cGREEN "  Test passed\n" cNORM);}
31
32 static void hexdump(const void *ptr, size_t len)
33 {
34     const unsigned char *p = ptr;
35     size_t i, j;
36
37     for (i = 0; i < len; i += j) {
38         for (j = 0; j < 16 && i + j < len; j++)
39             printf("%s%02x", j? "" : " ", p[i + j]);
40     }
41     printf("\n");
42 }
43
44 #define TEST_SIZE 256
45 #define STEP_SIZE 16
46
47 static int test_contexts(int nid, const int enc, int acpkm)
48 {
49     EVP_CIPHER_CTX *ctx, *save;
50     unsigned char pt[TEST_SIZE] = {1};
51     unsigned char b[TEST_SIZE]; /* base output */
52     unsigned char c[TEST_SIZE]; /* cloned output */
53     unsigned char K[32] = {1};
54     unsigned char iv[16] = {1};
55     int outlen, tmplen;
56     int ret = 0, test = 0;
57
58     const EVP_CIPHER *type = EVP_get_cipherbynid(nid);
59     const char *name = EVP_CIPHER_name(type);
60
61     printf(cBLUE "%s test for %s (nid %d)\n" cNORM,
62         enc ? "Encryption" : "Decryption", name, nid);
63
64     /* produce base encryption */
65     ctx = EVP_CIPHER_CTX_new();
66     T(ctx);
67     T(EVP_CipherInit_ex(ctx, type, NULL, K, iv, enc));
68     if (acpkm)
69         T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, acpkm, NULL));
70     T(EVP_CIPHER_CTX_set_padding(ctx, 0));
71     T(EVP_CipherUpdate(ctx, b, &outlen, pt, sizeof(b)));
72     T(EVP_CipherFinal_ex(ctx, b + outlen, &tmplen));
73
74     /* and now tests */
75     EVP_CIPHER_CTX_reset(ctx);
76     EVP_CIPHER_CTX_reset(ctx); /* double call is intentional */
77     T(EVP_CipherInit_ex(ctx, type, NULL, K, iv, enc));
78     T(EVP_CIPHER_CTX_set_padding(ctx, 0));
79     if (acpkm)
80         T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, acpkm, NULL));
81     save = ctx;
82
83     printf(" cloned contexts: ");
84     int i;
85     memset(c, 0, sizeof(c));
86     for (i = 0; i < TEST_SIZE / STEP_SIZE; i++) {
87         EVP_CIPHER_CTX *copy = EVP_CIPHER_CTX_new();
88         T(copy);
89         T(EVP_CIPHER_CTX_copy(copy, ctx));
90         if (save != ctx) /* else original context */
91             EVP_CIPHER_CTX_free(ctx);
92         ctx = copy;
93
94         T(EVP_CipherUpdate(ctx, c + STEP_SIZE * i, &outlen,
95                 pt + STEP_SIZE * i, STEP_SIZE));
96     }
97
98     outlen = i * STEP_SIZE;
99     T(EVP_CipherFinal_ex(ctx, c + outlen, &tmplen));
100     TEST_ASSERT(outlen != TEST_SIZE || memcmp(c, b, TEST_SIZE));
101     EVP_CIPHER_CTX_free(ctx);
102     if (test) {
103         printf("  b[%d] = ", outlen);
104         hexdump(b, outlen);
105         printf("  c[%d] = ", outlen);
106         hexdump(c, outlen);
107     }
108     ret |= test;
109
110     /* resume original context */
111     printf("    base context: ");
112     memset(c, 0, sizeof(c));
113     T(EVP_CipherUpdate(save, c, &outlen, pt, sizeof(c)));
114     T(EVP_CipherFinal_ex(save, c + outlen, &tmplen));
115     TEST_ASSERT(outlen != TEST_SIZE || memcmp(c, b, TEST_SIZE));
116     EVP_CIPHER_CTX_cleanup(save); /* multiple calls are intentional */
117     EVP_CIPHER_CTX_cleanup(save);
118     EVP_CIPHER_CTX_free(save);
119     if (test) {
120         printf("  b[%d] = ", outlen);
121         hexdump(b, outlen);
122         printf("  c[%d] = ", outlen);
123         hexdump(c, outlen);
124     }
125     ret |= test;
126
127     return ret;
128 }
129
130 static struct testcase {
131     int nid;
132     int acpkm;
133 } testcases[] = {
134     { NID_id_Gost28147_89, },
135     { NID_gost89_cnt, },
136     { NID_gost89_cnt_12, },
137     { NID_gost89_cbc, },
138     { NID_grasshopper_ecb, },
139     { NID_grasshopper_cbc, },
140     { NID_grasshopper_cfb, },
141     { NID_grasshopper_ofb, },
142     { NID_grasshopper_ctr, },
143     { NID_magma_cbc, },
144     { NID_magma_ctr, },
145     { NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm, 256 / 8 },
146     { 0 },
147 };
148
149 int main(int argc, char **argv)
150 {
151     int ret = 0;
152
153     setenv("OPENSSL_ENGINES", ENGINE_DIR, 0);
154     OPENSSL_add_all_algorithms_conf();
155     ERR_load_crypto_strings();
156     ENGINE *eng;
157     T(eng = ENGINE_by_id("gost"));
158     T(ENGINE_init(eng));
159     T(ENGINE_set_default(eng, ENGINE_METHOD_ALL));
160
161     const struct testcase *t;
162     for (t = testcases; t->nid; t++) {
163         ret |= test_contexts(t->nid, 1, t->acpkm);
164         ret |= test_contexts(t->nid, 0, t->acpkm);
165     }
166
167     ENGINE_finish(eng);
168     ENGINE_free(eng);
169
170     if (ret)
171         printf(cDRED "= Some tests FAILED!\n" cNORM);
172     else
173         printf(cDGREEN "= All tests passed!\n" cNORM);
174     return ret;
175 }