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