]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - test_sign.c
Update the OpenSSL 3.0 tag to openssl-3.0.0-alpha17
[openssl-gost/engine.git] / test_sign.c
1 /*
2  * Test GOST 34.10 Sign/Verify operation for every curve parameter
3  *
4  * Copyright (C) 2019 vt@altlinux.org. All Rights Reserved.
5  *
6  * Contents licensed under the terms of the OpenSSL license
7  * See https://www.openssl.org/source/license.html for details
8  */
9
10 #include "e_gost_err.h"
11 #include "gost_lcl.h"
12 #include <openssl/evp.h>
13 #include <openssl/rand.h>
14 #include <openssl/err.h>
15 #include <openssl/asn1.h>
16 #include <openssl/obj_mac.h>
17 #include <openssl/ec.h>
18 #include <openssl/bn.h>
19 #include <openssl/store.h>
20 #include <string.h>
21 #include <stdlib.h>
22
23 #define T(e) ({ if (!(e)) { \
24                 ERR_print_errors_fp(stderr); \
25                 OpenSSLDie(__FILE__, __LINE__, #e); \
26             } \
27         })
28 #define TE(e) ({ if (!(e)) { \
29                 ERR_print_errors_fp(stderr); \
30                 fprintf(stderr, "Error at %s:%d %s\n", __FILE__, __LINE__, #e); \
31                 return -1; \
32             } \
33         })
34
35 #define cRED    "\033[1;31m"
36 #define cDRED   "\033[0;31m"
37 #define cGREEN  "\033[1;32m"
38 #define cDGREEN "\033[0;32m"
39 #define cBLUE   "\033[1;34m"
40 #define cDBLUE  "\033[0;34m"
41 #define cCYAN   "\033[1;36m"
42 #define cNORM   "\033[m"
43 #define TEST_ASSERT(e) {if ((test = (e))) \
44                  printf(cRED "  Test FAILED" cNORM "\n"); \
45              else \
46                  printf(cGREEN "  Test passed" cNORM "\n");}
47
48 struct test_sign {
49     const char *name;
50     unsigned int nid;
51     size_t bits;
52     const char *paramset;
53 };
54
55 #define D(x,y,z) { .name = #x, .nid = x, .bits = y, .paramset = z }
56 static struct test_sign test_signs[] = {
57     D(NID_id_GostR3410_2001_CryptoPro_A_ParamSet, 256, "A"),
58     D(NID_id_GostR3410_2001_CryptoPro_B_ParamSet, 256, "B"),
59     D(NID_id_GostR3410_2001_CryptoPro_C_ParamSet, 256, "C"),
60     D(NID_id_tc26_gost_3410_2012_256_paramSetA, 256, "TCA"),
61     D(NID_id_tc26_gost_3410_2012_256_paramSetB, 256, "TCB"),
62     D(NID_id_tc26_gost_3410_2012_256_paramSetC, 256, "TCC"),
63     D(NID_id_tc26_gost_3410_2012_256_paramSetD, 256, "TCD"),
64     D(NID_id_tc26_gost_3410_2012_512_paramSetA,   512, "A"),
65     D(NID_id_tc26_gost_3410_2012_512_paramSetB,   512, "B"),
66     D(NID_id_tc26_gost_3410_2012_512_paramSetC,   512, "C"),
67     0
68 };
69 #undef D
70
71 static void hexdump(const void *ptr, size_t len)
72 {
73     const unsigned char *p = ptr;
74     size_t i, j;
75
76     for (i = 0; i < len; i += j) {
77         for (j = 0; j < 16 && i + j < len; j++)
78             printf("%s %02x", j? "" : "\n", p[i + j]);
79     }
80     printf("\n");
81 }
82
83 static void print_test_tf(int err, int val, const char *t, const char *f)
84 {
85     if (err == 1)
86         printf(cGREEN "%s" cNORM "\n", t);
87     else
88         printf(cRED "%s [%d]" cNORM "\n", f, val);
89 }
90
91 static void print_test_result(int err)
92 {
93     if (err == 1)
94         printf(cGREEN "success" cNORM "\n");
95     else if (err == 0)
96         printf(cRED "failure" cNORM "\n");
97     else
98         ERR_print_errors_fp(stderr);
99 }
100
101 static int test_sign(struct test_sign *t)
102 {
103     int ret = 0, err;
104     size_t len = t->bits / 8;
105
106     printf(cBLUE "Test %s:" cNORM "\n", t->name);
107
108     /* Signature type from size. */
109     int type = 0;
110     const char *algname = NULL;
111     switch (t->bits) {
112         case 256:
113             type = NID_id_GostR3410_2012_256;
114             algname = "gost2012_256";
115             break;
116         case 512:
117             type = NID_id_GostR3410_2012_512;
118             algname = "gost2012_512";
119     }
120
121     /* Keygen. */
122     EVP_PKEY *pkey;
123     T(pkey = EVP_PKEY_new());
124     TE(EVP_PKEY_set_type(pkey, type));
125     EVP_PKEY_CTX *ctx;
126     T(ctx = EVP_PKEY_CTX_new(pkey, NULL));
127     T(EVP_PKEY_keygen_init(ctx));
128     T(EVP_PKEY_CTX_ctrl(ctx, type, -1, EVP_PKEY_CTRL_GOST_PARAMSET, t->nid, NULL));
129     EVP_PKEY *priv_key = NULL;
130     err = EVP_PKEY_keygen(ctx, &priv_key);
131     printf("\tEVP_PKEY_keygen:\t");
132     print_test_result(err);
133     EVP_PKEY_CTX_free(ctx);
134     EVP_PKEY_free(pkey);
135     if (err != 1)
136         return -1;
137
138     /* Convert to PEM and back. */
139     BIO *bp;
140     T(bp = BIO_new(BIO_s_secmem()));
141     T(PEM_write_bio_PrivateKey(bp, priv_key, NULL, NULL, 0, NULL, NULL));
142     pkey = NULL;
143     T(PEM_read_bio_PrivateKey(bp, &pkey, NULL, NULL));
144     printf("\tPEM_read_bio_PrivateKey:");
145     /* Yes, it compares only public part. */
146     err = !EVP_PKEY_cmp(priv_key, pkey);
147     print_test_result(!err);
148     ret |= err;
149     EVP_PKEY_free(pkey);
150
151     /* Convert to DER and back, using _PrivateKey_bio API. */
152     T(BIO_reset(bp));
153     T(i2d_PrivateKey_bio(bp, priv_key));
154     T(d2i_PrivateKey_bio(bp, &pkey));
155     printf("\td2i_PrivateKey_bio:\t");
156     err = !EVP_PKEY_cmp(priv_key, pkey);
157     print_test_result(!err);
158     ret |= err;
159     EVP_PKEY_free(pkey);
160
161 #if OPENSSL_VERSION_MAJOR >= 3
162     /* Try d2i_PrivateKey_ex_bio, added in 3.0. */
163     T(BIO_reset(bp));
164     T(i2d_PrivateKey_bio(bp, priv_key));
165     T(d2i_PrivateKey_ex_bio(bp, &pkey, NULL, NULL));
166     printf("\td2i_PrivateKey_ex_bio:\t");
167     err = !EVP_PKEY_cmp(priv_key, pkey);
168     print_test_result(!err);
169     ret |= err;
170     EVP_PKEY_free(pkey);
171 #endif
172
173     /* Convert to DER and back, using OSSL_STORE API. */
174     T(BIO_reset(bp));
175     T(i2d_PrivateKey_bio(bp, priv_key));
176     printf("\tOSSL_STORE_attach:\t");
177     fflush(stdout);
178     pkey = NULL;
179     OSSL_STORE_CTX *cts;
180     T(cts = OSSL_STORE_attach(bp, "file", NULL, NULL, NULL, NULL, NULL, NULL));
181     for (;;) {
182         OSSL_STORE_INFO *info = OSSL_STORE_load(cts);
183         if (!info) {
184             ERR_print_errors_fp(stderr);
185             T(OSSL_STORE_eof(cts));
186             break;
187         }
188         if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) {
189             T((pkey = OSSL_STORE_INFO_get1_PKEY(info)));
190         }
191         OSSL_STORE_INFO_free(info);
192     }
193     OSSL_STORE_close(cts);
194     if (pkey) {
195         err = !EVP_PKEY_cmp(priv_key, pkey);
196         print_test_result(!err);
197         ret |= err;
198         EVP_PKEY_free(pkey);
199     } else
200         printf(cCYAN "skipped" cNORM "\n");
201     BIO_free(bp);
202
203     /* Convert to DER and back, using memory API. */
204     unsigned char *kptr = NULL;
205     int klen;
206     T(klen = i2d_PrivateKey(priv_key, &kptr));
207     const unsigned char *tptr = kptr; /* will be moved by d2i_PrivateKey */
208     pkey = NULL;
209     T(d2i_PrivateKey(type, &pkey, &tptr, klen));
210     printf("\td2i_PrivateKey:\t\t");
211     err = !EVP_PKEY_cmp(priv_key, pkey);
212     print_test_result(!err);
213     ret |= err;
214     EVP_PKEY_free(pkey);
215     OPENSSL_free(kptr);
216
217     /* Create another key using string interface. */
218     EVP_PKEY *key1;
219     T(key1 = EVP_PKEY_new());
220     T(EVP_PKEY_set_type_str(key1, algname, strlen(algname)));
221     EVP_PKEY_CTX *ctx1;
222     T(ctx1 = EVP_PKEY_CTX_new(key1, NULL));
223     T(EVP_PKEY_keygen_init(ctx1));
224     T(EVP_PKEY_CTX_ctrl_str(ctx1, "paramset", t->paramset));
225     EVP_PKEY *key2 = NULL;
226     err = EVP_PKEY_keygen(ctx1, &key2);
227     printf("\tEVP_PKEY_*_str:\t\t");
228     print_test_result(err);
229     ret |= !err;
230
231     /* Check if key type and curve_name match expected values. */
232     int id = EVP_PKEY_id(key2);
233     err = id == type;
234     printf("\tEVP_PKEY_id (%d):\t", type);
235     print_test_tf(err, id, "match", "mismatch");
236     ret |= !err;
237
238     const EC_KEY *ec = EVP_PKEY_get0(key2);
239     const EC_GROUP *group = EC_KEY_get0_group(ec);
240     int curve_name = EC_GROUP_get_curve_name(group);
241     err = curve_name == t->nid;
242     printf("\tcurve_name (%u):\t", t->nid);
243     print_test_tf(err, curve_name, "match", "mismatch");
244     ret |= !err;
245
246     /* Compare both keys.
247      * Parameters should match, public keys should mismatch.
248     */
249     err = EVP_PKEY_cmp_parameters(priv_key, key2);
250     printf("\tEVP_PKEY_cmp_parameters:");
251     print_test_tf(err, err, "success", "failure");
252     ret |= err != 1;
253
254     err = EVP_PKEY_cmp(priv_key, key2);
255     err = (err < 0) ? err : !err;
256     printf("\tEVP_PKEY_cmp:\t\t");
257     print_test_tf(err, err, "differ (good)", "equal (error)");
258     ret |= err != 1;
259     EVP_PKEY_CTX_free(ctx1);
260     EVP_PKEY_free(key1);
261
262     /*
263      * Prepare for sign testing.
264      */
265     size_t siglen = EVP_PKEY_size(priv_key);
266     unsigned char *sig;
267     T(sig = OPENSSL_malloc(siglen));
268     unsigned char *hash;
269     T(hash = OPENSSL_zalloc(len));
270     T(ctx = EVP_PKEY_CTX_new(priv_key, NULL));
271
272     /* Sign. */
273     T(EVP_PKEY_sign_init(ctx));
274     err = EVP_PKEY_sign(ctx, sig, &siglen, hash, len);
275     printf("\tEVP_PKEY_sign:\t\t");
276     print_test_result(err);
277     ret |= err != 1;
278
279     /* Non-determinism test.
280      * Check that different signatures for the same data
281      * are not equal. */
282     unsigned char *sig2;
283     T(sig2 = OPENSSL_malloc(siglen));
284     TE(EVP_PKEY_sign(ctx, sig2, &siglen, hash, len) == 1);
285     printf("\tNon-determinism:\t");
286     err = !!memcmp(sig, sig2, siglen);
287     print_test_result(err);
288     ret |= err != 1;
289     OPENSSL_free(sig2);
290
291     /* Verify. */
292     T(EVP_PKEY_verify_init(ctx));
293     hash[0]++; /* JFF */
294     err = EVP_PKEY_verify(ctx, sig, siglen, hash, len);
295     printf("\tEVP_PKEY_verify:\t");
296     print_test_result(err);
297     ret |= err != 1;
298
299     /* False positive Verify. */
300     T(EVP_PKEY_verify_init(ctx));
301     hash[0]++;
302     err = EVP_PKEY_verify(ctx, sig, siglen, hash, len);
303     err = (err < 0) ? err : !err;
304     printf("\tFalse positive test:\t");
305     print_test_result(err);
306     ret |= err != 1;
307
308     EVP_PKEY_CTX_free(ctx);
309     OPENSSL_free(sig);
310     OPENSSL_free(hash);
311     EVP_PKEY_free(priv_key);
312     EVP_PKEY_free(key2);
313
314     return ret;
315 }
316
317 int main(int argc, char **argv)
318 {
319     int ret = 0;
320
321     setenv("OPENSSL_ENGINES", ENGINE_DIR, 0);
322     OPENSSL_add_all_algorithms_conf();
323     ERR_load_crypto_strings();
324     ENGINE *eng;
325     T(eng = ENGINE_by_id("gost"));
326     T(ENGINE_init(eng));
327     T(ENGINE_set_default(eng, ENGINE_METHOD_ALL));
328
329     struct test_sign *sp;
330     for (sp = test_signs; sp->name; sp++)
331         ret |= test_sign(sp);
332
333     ENGINE_finish(eng);
334     ENGINE_free(eng);
335
336     if (ret)
337         printf(cDRED "= Some tests FAILED!" cNORM "\n");
338     else
339         printf(cDGREEN "= All tests passed!" cNORM "\n");
340     return ret;
341 }