]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - test_sign.c
4a63f420f0535c6e4d5c8b47d15d8bbacac88162
[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 <string.h>
20 #include <stdlib.h>
21
22 #define T(e) ({ if (!(e)) { \
23                 ERR_print_errors_fp(stderr); \
24                 OpenSSLDie(__FILE__, __LINE__, #e); \
25             } \
26         })
27 #define TE(e) ({ if (!(e)) { \
28                 ERR_print_errors_fp(stderr); \
29                 fprintf(stderr, "Error at %s:%d %s\n", __FILE__, __LINE__, #e); \
30                 return -1; \
31             } \
32         })
33
34 #define cRED    "\033[1;31m"
35 #define cDRED   "\033[0;31m"
36 #define cGREEN  "\033[1;32m"
37 #define cDGREEN "\033[0;32m"
38 #define cBLUE   "\033[1;34m"
39 #define cDBLUE  "\033[0;34m"
40 #define cNORM   "\033[m"
41 #define TEST_ASSERT(e) {if ((test = (e))) \
42                  printf(cRED "  Test FAILED\n" cNORM); \
43              else \
44                  printf(cGREEN "  Test passed\n" cNORM);}
45
46 struct test_sign {
47     const char *name;
48     unsigned int nid;
49     size_t bits;
50     const char *paramset;
51 };
52
53 #define D(x,y,z) { .name = #x, .nid = x, .bits = y, .paramset = z }
54 static struct test_sign test_signs[] = {
55     D(NID_id_GostR3410_2001_CryptoPro_A_ParamSet, 256, "A"),
56     D(NID_id_GostR3410_2001_CryptoPro_B_ParamSet, 256, "B"),
57     D(NID_id_GostR3410_2001_CryptoPro_C_ParamSet, 256, "C"),
58     D(NID_id_tc26_gost_3410_2012_256_paramSetA, 256, "TCA"),
59     D(NID_id_tc26_gost_3410_2012_256_paramSetB, 256, "TCB"),
60     D(NID_id_tc26_gost_3410_2012_256_paramSetC, 256, "TCC"),
61     D(NID_id_tc26_gost_3410_2012_256_paramSetD, 256, "TCD"),
62     D(NID_id_tc26_gost_3410_2012_512_paramSetA,   512, "A"),
63     D(NID_id_tc26_gost_3410_2012_512_paramSetB,   512, "B"),
64     D(NID_id_tc26_gost_3410_2012_512_paramSetC,   512, "C"),
65     0
66 };
67 #undef D
68
69 static void hexdump(const void *ptr, size_t len)
70 {
71     const unsigned char *p = ptr;
72     size_t i, j;
73
74     for (i = 0; i < len; i += j) {
75         for (j = 0; j < 16 && i + j < len; j++)
76             printf("%s %02x", j? "" : "\n", p[i + j]);
77     }
78     printf("\n");
79 }
80
81 static void print_test_tf(int err, int val, const char *t, const char *f)
82 {
83     if (err == 1)
84         printf(cGREEN "%s\n" cNORM, t);
85     else
86         printf(cRED "%s [%d]\n" cNORM, f, val);
87 }
88
89 static void print_test_result(int err)
90 {
91     if (err == 1)
92         printf(cGREEN "success\n" cNORM);
93     else if (err == 0)
94         printf(cRED "failure\n" cNORM);
95     else
96         ERR_print_errors_fp(stderr);
97 }
98
99 static int test_sign(struct test_sign *t)
100 {
101     int ret = 0, err;
102     size_t len = t->bits / 8;
103
104     printf(cBLUE "Test %s:\n" cNORM, t->name);
105
106     /* Signature type from size. */
107     int type = 0;
108     const char *algname = NULL;
109     switch (t->bits) {
110         case 256:
111             type = NID_id_GostR3410_2012_256;
112             algname = "gost2012_256";
113             break;
114         case 512:
115             type = NID_id_GostR3410_2012_512;
116             algname = "gost2012_512";
117     }
118
119     /* Keygen. */
120     EVP_PKEY *pkey;
121     T(pkey = EVP_PKEY_new());
122     TE(EVP_PKEY_set_type(pkey, type));
123     EVP_PKEY_CTX *ctx;
124     T(ctx = EVP_PKEY_CTX_new(pkey, NULL));
125     T(EVP_PKEY_keygen_init(ctx));
126     T(EVP_PKEY_CTX_ctrl(ctx, type, -1, EVP_PKEY_CTRL_GOST_PARAMSET, t->nid, NULL));
127     EVP_PKEY *priv_key = NULL;
128     err = EVP_PKEY_keygen(ctx, &priv_key);
129     printf("\tEVP_PKEY_keygen:\t");
130     print_test_result(err);
131     EVP_PKEY_CTX_free(ctx);
132     EVP_PKEY_free(pkey);
133     if (err != 1)
134         return -1;
135
136     /* Create another key using string interface. */
137     EVP_PKEY *key1;
138     T(key1 = EVP_PKEY_new());
139     T(EVP_PKEY_set_type_str(key1, algname, strlen(algname)));
140     EVP_PKEY_CTX *ctx1;
141     T(ctx1 = EVP_PKEY_CTX_new(key1, NULL));
142     T(EVP_PKEY_keygen_init(ctx1));
143     T(EVP_PKEY_CTX_ctrl_str(ctx1, "paramset", t->paramset));
144     EVP_PKEY *key2 = NULL;
145     err = EVP_PKEY_keygen(ctx1, &key2);
146     printf("\tEVP_PKEY_*_str:\t\t");
147     print_test_result(err);
148
149     /* Check if key type and curve_name match expected values. */
150     int id = EVP_PKEY_id(key2);
151     err = id == type;
152     printf("\tEVP_PKEY_id (%d):\t", type);
153     print_test_tf(err, id, "match", "mismatch");
154     ret |= !err;
155
156     const EC_KEY *ec = EVP_PKEY_get0(key2);
157     const EC_GROUP *group = EC_KEY_get0_group(ec);
158     int curve_name = EC_GROUP_get_curve_name(group);
159     err = curve_name == t->nid;
160     printf("\tcurve_name (%d):\t", t->nid);
161     print_test_tf(err, curve_name, "match", "mismatch");
162     ret |= !err;
163
164     /* Compare both keys.
165      * Parameters should match, public keys should mismatch.
166     */
167     err = EVP_PKEY_cmp_parameters(priv_key, key2);
168     printf("\tEVP_PKEY_cmp_parameters:");
169     print_test_tf(err, err, "success", "failure");
170     ret |= err != 1;
171
172     err = EVP_PKEY_cmp(priv_key, key2);
173     err = (err < 0) ? err : !err;
174     printf("\tEVP_PKEY_cmp:\t\t");
175     print_test_tf(err, err, "differ (good)", "equal (error)");
176     ret |= err != 1;
177     EVP_PKEY_CTX_free(ctx1);
178     EVP_PKEY_free(key1);
179
180     /*
181      * Prepare for sign testing.
182      */
183     size_t siglen = EVP_PKEY_size(priv_key);
184     unsigned char *sig;
185     T(sig = OPENSSL_malloc(siglen));
186     unsigned char *hash;
187     T(hash = OPENSSL_zalloc(len));
188     T(ctx = EVP_PKEY_CTX_new(priv_key, NULL));
189
190     /* Sign. */
191     T(EVP_PKEY_sign_init(ctx));
192     err = EVP_PKEY_sign(ctx, sig, &siglen, hash, len);
193     printf("\tEVP_PKEY_sign:\t\t");
194     print_test_result(err);
195     ret |= err != 1;
196
197     /* Non-determinism test.
198      * Check that different signatures for the same data
199      * are not equal. */
200     unsigned char *sig2;
201     T(sig2 = OPENSSL_malloc(siglen));
202     TE(EVP_PKEY_sign(ctx, sig2, &siglen, hash, len) == 1);
203     printf("\tNon-determinism:\t");
204     err = !!memcmp(sig, sig2, siglen);
205     print_test_result(err);
206     ret |= err != 1;
207     OPENSSL_free(sig2);
208
209     /* Verify. */
210     T(EVP_PKEY_verify_init(ctx));
211     hash[0]++; /* JFF */
212     err = EVP_PKEY_verify(ctx, sig, siglen, hash, len);
213     printf("\tEVP_PKEY_verify:\t");
214     print_test_result(err);
215     ret |= err != 1;
216
217     /* False positive Verify. */
218     T(EVP_PKEY_verify_init(ctx));
219     hash[0]++;
220     err = EVP_PKEY_verify(ctx, sig, siglen, hash, len);
221     err = (err < 0) ? err : !err;
222     printf("\tFalse positive test:\t");
223     print_test_result(err);
224     ret |= err != 1;
225
226     EVP_PKEY_CTX_free(ctx);
227     OPENSSL_free(sig);
228     OPENSSL_free(hash);
229     EVP_PKEY_free(priv_key);
230     EVP_PKEY_free(key2);
231
232     return ret;
233 }
234
235 int main(int argc, char **argv)
236 {
237     int ret = 0;
238
239     setenv("OPENSSL_CONF", "../example.conf", 0);
240     OPENSSL_add_all_algorithms_conf();
241     ERR_load_crypto_strings();
242
243     struct test_sign *sp;
244     for (sp = test_signs; sp->name; sp++)
245         ret |= test_sign(sp);
246
247     if (ret)
248         printf(cDRED "= Some tests FAILED!\n" cNORM);
249     else
250         printf(cDGREEN "= All tests passed!\n" cNORM);
251     return ret;
252 }