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