2 * Copyright (C) 2018 vt@altlinux.org. All Rights Reserved.
4 * Contents licensed under the terms of the OpenSSL license
5 * See https://www.openssl.org/source/license.html for details
8 #include "e_gost_err.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>
19 #define T(e) ({ if (!(e)) { \
20 ERR_print_errors_fp(stderr); \
21 OpenSSLDie(__FILE__, __LINE__, #e); \
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) { \
35 printf(cRED " Test FAILED" cNORM "\n"); \
37 printf(cGREEN " Test passed" cNORM "\n"); \
46 static struct test_curve test_curves[] = {
48 { NID_id_GostR3410_2001_TestParamSet, },
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", },
65 static struct test_curve *get_test_curve(int nid)
69 for (i = 0; test_curves[i].nid; i++)
70 if (test_curves[i].nid == nid)
71 return &test_curves[i];
75 static void print_bn(const char *name, const BIGNUM *n)
77 printf("%3s = ", name);
78 BN_print_fp(stdout, n);
82 // https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography
83 static int parameter_test(struct test_curve *tc)
85 const int nid = tc->nid;
88 printf(cBLUE "Test curve NID %d" cNORM, nid);
90 printf(cBLUE ": %s" cNORM, tc->name);
91 else if (OBJ_nid2sn(nid))
92 printf(cBLUE ": %s" cNORM, OBJ_nid2sn(nid));
95 if (!OBJ_nid2obj(nid)) {
96 printf(cRED "NID %d not found" cNORM "\n", nid);
100 /* nid resolves in both directions */
102 T(sn = OBJ_nid2sn(nid));
103 T(ln = OBJ_nid2ln(nid));
105 T(!strcmp(tc->name, OBJ_nid2sn(nid)));
106 T(nid == OBJ_sn2nid(sn));
107 T(nid == OBJ_ln2nid(ln));
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);
117 const EC_GROUP *group;
118 T(group = EC_KEY_get0_group(ec));
121 T(ctx = BN_CTX_new());
126 EC_GROUP_get_curve(group, p, a, b, ctx);
131 T(BN_is_odd(p)); /* Should be odd for F_p */
135 /* Check generator */
136 const EC_POINT *generator;
137 T(generator = EC_GROUP_get0_generator(group));
141 T(EC_POINT_get_affine_coordinates(group, generator, x, y, ctx));
146 /* Generator is not identity element 0 */
147 T(EC_POINT_is_at_infinity(group, generator) == 0);
149 /* x and y is in range [1 .. p-1] */
150 T(!BN_is_negative(x));
151 T(!BN_is_negative(y));
155 /* Generator should be on curve */
156 T(EC_POINT_is_on_curve(group, generator, ctx) == 1);
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);
167 BN_mod_exp(yy, y, r, p, ctx);
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);
186 T(order = EC_GROUP_get0_order(group));
187 T(!BN_is_zero(order));
188 print_bn("q", order);
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);
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);
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);
213 /* Cofactor is 1 or 4 */
215 T(c = EC_GROUP_get0_cofactor(group));
216 T(BN_is_word(c, 1) || BN_is_word(c, 4));
224 int main(int argc, char **argv)
228 setenv("OPENSSL_ENGINES", ENGINE_DIR, 0);
229 OPENSSL_add_all_algorithms_conf();
230 ERR_load_crypto_strings();
232 T(eng = ENGINE_by_id("gost"));
234 T(ENGINE_set_default(eng, ENGINE_METHOD_ALL));
236 struct test_curve *tc;
237 for (tc = test_curves; tc->nid; tc++) {
238 ret |= parameter_test(tc);
245 printf(cDRED "= Some tests FAILED!" cNORM "\n");
247 printf(cDGREEN "= All tests passed!" cNORM "\n");