]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - test_curves.c
Always cNORM before "\n"
[openssl-gost/engine.git] / test_curves.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 "e_gost_err.h"
9 #include "gost_lcl.h"
10 #include <openssl/evp.h>
11 #include <openssl/rand.h>
12 #include <openssl/err.h>
13 #include <openssl/asn1.h>
14 #include <openssl/obj_mac.h>
15 #include <openssl/ec.h>
16 #include <openssl/bn.h>
17 #include <string.h>
18
19 #define T(e) ({ if (!(e)) { \
20                 ERR_print_errors_fp(stderr); \
21                 OpenSSLDie(__FILE__, __LINE__, #e); \
22             } \
23         })
24
25 #define cRED    "\033[1;31m"
26 #define cDRED   "\033[0;31m"
27 #define cGREEN  "\033[1;32m"
28 #define cDGREEN "\033[0;32m"
29 #define cBLUE   "\033[1;34m"
30 #define cDBLUE  "\033[0;34m"
31 #define cNORM   "\033[m"
32 #define TEST_ASSERT(e) { \
33         test = e; \
34         if (test) \
35                 printf(cRED "  Test FAILED" cNORM "\n"); \
36         else \
37                 printf(cGREEN "  Test passed" cNORM "\n"); \
38 }
39
40 struct test_curve {
41     int nid;
42     const char *name;
43     int listed;
44 };
45
46 static struct test_curve test_curves[] = {
47 #if 2001
48     { NID_id_GostR3410_2001_TestParamSet, },
49 #endif
50     { NID_id_GostR3410_2001_CryptoPro_A_ParamSet },
51     { NID_id_GostR3410_2001_CryptoPro_B_ParamSet },
52     { NID_id_GostR3410_2001_CryptoPro_C_ParamSet },
53     { NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet },
54     { NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet },
55     { NID_id_tc26_gost_3410_2012_512_paramSetA, "id-tc26-gost-3410-2012-512-paramSetA", },
56     { NID_id_tc26_gost_3410_2012_512_paramSetB, "id-tc26-gost-3410-2012-512-paramSetB", },
57     { NID_id_tc26_gost_3410_2012_512_paramSetC, "id-tc26-gost-3410-2012-512-paramSetC", },
58     { NID_id_tc26_gost_3410_2012_256_paramSetA, "id-tc26-gost-3410-2012-256-paramSetA", },
59     { NID_id_tc26_gost_3410_2012_256_paramSetB, "id-tc26-gost-3410-2012-256-paramSetB", },
60     { NID_id_tc26_gost_3410_2012_256_paramSetC, "id-tc26-gost-3410-2012-256-paramSetC", },
61     { NID_id_tc26_gost_3410_2012_256_paramSetD, "id-tc26-gost-3410-2012-256-paramSetD", },
62     0,
63 };
64
65 static struct test_curve *get_test_curve(int nid)
66 {
67     int i;
68
69     for (i = 0; test_curves[i].nid; i++)
70         if (test_curves[i].nid == nid)
71             return &test_curves[i];
72     return NULL;
73 }
74
75 static void print_bn(const char *name, const BIGNUM *n)
76 {
77     printf("%3s = ", name);
78     BN_print_fp(stdout, n);
79     printf("\n");
80 }
81
82 // https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography
83 static int parameter_test(struct test_curve *tc)
84 {
85     const int nid = tc->nid;
86     int test;
87
88     printf(cBLUE "Test curve NID %d" cNORM, nid);
89     if (tc->name)
90         printf(cBLUE ": %s" cNORM, tc->name);
91     else if (OBJ_nid2sn(nid))
92         printf(cBLUE ": %s" cNORM, OBJ_nid2sn(nid));
93     printf("\n");
94
95     if (!OBJ_nid2obj(nid)) {
96         printf(cRED "NID %d not found" cNORM "\n", nid);
97         return 1;
98     }
99
100     /* nid resolves in both directions */
101     const char *sn, *ln;
102     T(sn = OBJ_nid2sn(nid));
103     T(ln = OBJ_nid2ln(nid));
104     if (tc->name)
105         T(!strcmp(tc->name, OBJ_nid2sn(nid)));
106     T(nid == OBJ_sn2nid(sn));
107     T(nid == OBJ_ln2nid(ln));
108
109     EC_KEY *ec;
110     T(ec = EC_KEY_new());
111     if (!fill_GOST_EC_params(ec, nid)) {
112         printf(cRED "fill_GOST_EC_params FAIL" cNORM "\n");
113         ERR_print_errors_fp(stderr);
114         return 1;
115     }
116
117     const EC_GROUP *group;
118     T(group = EC_KEY_get0_group(ec));
119
120     BN_CTX *ctx;
121     T(ctx = BN_CTX_new());
122     BIGNUM *p, *a, *b;
123     T(p = BN_new());
124     T(a = BN_new());
125     T(b = BN_new());
126     EC_GROUP_get_curve(group, p, a, b, ctx);
127     print_bn("p", p);
128     print_bn("a", a);
129     print_bn("b", b);
130     T(!BN_is_zero(p));
131     T(BN_is_odd(p)); /* Should be odd for F_p */
132     T(!BN_is_zero(a));
133     T(!BN_is_zero(b));
134
135     /* Check generator */
136     const EC_POINT *generator;
137     T(generator = EC_GROUP_get0_generator(group));
138     BIGNUM *x, *y;
139     T(x = BN_new());
140     T(y = BN_new());
141     T(EC_POINT_get_affine_coordinates(group, generator, x, y, ctx));
142     print_bn("x", x);
143     print_bn("y", y);
144     T(!BN_is_zero(y));
145
146     /* Generator is not identity element 0 */
147     T(EC_POINT_is_at_infinity(group, generator) == 0);
148
149     /* x and y is in range [1 .. p-1] */
150     T(!BN_is_negative(x));
151     T(!BN_is_negative(y));
152     T(BN_cmp(x, p) < 0);
153     T(BN_cmp(y, p) < 0);
154
155     /* Generator should be on curve */
156     T(EC_POINT_is_on_curve(group, generator, ctx) == 1);
157
158     /* y^2 == (x^3 + ax + b) mod p
159      * Should be same as EC_POINT_is_on_curve(generator),
160      * but, let's calculate it manually. */
161     BIGNUM *yy  = BN_new();
162     BIGNUM *r   = BN_new();
163     BIGNUM *xxx = BN_new();
164     BIGNUM *ax  = BN_new();
165     T(yy && r && xxx && ax);
166     BN_set_word(r, 2);
167     BN_mod_exp(yy, y, r, p, ctx);
168     BN_set_word(r, 3);
169     BN_mod_exp(xxx, x, r, p, ctx);
170     BN_mod_mul(ax, a, x, p, ctx);
171     BN_mod_add(xxx, xxx, ax, p, ctx);
172     BN_mod_add(xxx, xxx, b, p, ctx);
173     T(BN_cmp(yy, xxx) == 0);
174     BN_free(yy);
175     BN_free(r);
176     BN_free(xxx);
177     BN_free(ax);
178     BN_free(p);
179     BN_free(a);
180     BN_free(b);
181     BN_free(x);
182     BN_free(y);
183
184     /* Check order */
185     const BIGNUM *order;
186     T(order = EC_GROUP_get0_order(group));
187     T(!BN_is_zero(order));
188     print_bn("q", order);
189     T(BN_is_odd(order));
190     EC_POINT *point;
191     T((point = EC_POINT_new(group)));
192     T(EC_POINT_mul(group, point, NULL, generator, order, ctx));
193     /* generator * order is the point at infinity? */
194     T(EC_POINT_is_at_infinity(group, point) == 1);
195     EC_POINT_free(point);
196
197     /* Check if order is cyclic */
198     BIGNUM *k1 = BN_new();
199     BIGNUM *k2 = BN_new();
200     EC_POINT *p1 = EC_POINT_new(group);
201     EC_POINT *p2 = EC_POINT_new(group);
202     BN_set_word(k1, 3);
203     BN_set_word(k2, 3);
204     BN_add(k2, k2, order);
205     T(EC_POINT_mul(group, p1, NULL, generator, k1, ctx));
206     T(EC_POINT_mul(group, p2, NULL, generator, k2, ctx));
207     T(EC_POINT_cmp(group, p1, p2, ctx) == 0);
208     BN_free(k1);
209     BN_free(k2);
210     EC_POINT_free(p1);
211     EC_POINT_free(p2);
212
213     /* Cofactor is 1 or 4 */
214     const BIGNUM *c;
215     T(c = EC_GROUP_get0_cofactor(group));
216     T(BN_is_word(c, 1) || BN_is_word(c, 4));
217
218     BN_CTX_free(ctx);
219     EC_KEY_free(ec);
220     TEST_ASSERT(0);
221     return test;
222 }
223
224 int main(int argc, char **argv)
225 {
226     int ret = 0;
227
228     setenv("OPENSSL_ENGINES", ENGINE_DIR, 0);
229     OPENSSL_add_all_algorithms_conf();
230     ERR_load_crypto_strings();
231     ENGINE *eng;
232     T(eng = ENGINE_by_id("gost"));
233     T(ENGINE_init(eng));
234     T(ENGINE_set_default(eng, ENGINE_METHOD_ALL));
235
236     struct test_curve *tc;
237     for (tc = test_curves; tc->nid; tc++) {
238         ret |= parameter_test(tc);
239     }
240
241     ENGINE_finish(eng);
242     ENGINE_free(eng);
243
244     if (ret)
245         printf(cDRED "= Some tests FAILED!" cNORM "\n");
246     else
247         printf(cDGREEN "= All tests passed!" cNORM "\n");
248     return ret;
249 }