From: Dmitry Belyavskiy Date: Tue, 2 Oct 2018 07:28:54 +0000 (+0300) Subject: Merge branch 'master' of https://github.com/gost-engine/engine X-Git-Tag: v3.0.0~334 X-Git-Url: http://www.wagner.pp.ru/gitweb/?a=commitdiff_plain;h=3383ad117b305cad929bc2aa57f5b724fe699b9a;hp=302dc2039fbbb7c7e91368e8455cbf8570518911;p=openssl-gost%2Fengine.git Merge branch 'master' of https://github.com/gost-engine/engine --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 15fe22d..774a1a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,6 +113,11 @@ set(GOST_ENGINE_SOURCE_FILES gost_omac_acpkm.c ) +add_executable(test_curves test_curves.c) +target_link_libraries(test_curves gost_engine gost_core ${OPENSSL_CRYPTO_LIBRARY}) +add_test(NAME curves + COMMAND test_curves) + add_executable(test_context test_context.c) target_link_libraries(test_context gost_engine gost_core ${OPENSSL_CRYPTO_LIBRARY}) add_test(NAME context diff --git a/gost_params.c b/gost_params.c index 0a7557d..799672b 100644 --- a/gost_params.c +++ b/gost_params.c @@ -130,5 +130,41 @@ R3410_ec_params R3410_2012_512_paramset[] = { "DCB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD", "1"} , + {NID_id_tc26_gost_3410_2012_256_paramSetA, + /* a */ + "C2173F1513981673AF4892C23035A27CE25E2013BF95AA33B22C656F277E7335", + /* b */ + "295F9BAE7428ED9CCC20E7C359A9D41A22FCCD9108E17BF7BA9337A6F8AE9513", + /* p */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97", + /* m */ + "01000000000000000000000000000000003F63377F21ED98D70456BD55B0D8319C", + /* x */ + "91E38443A5E82C0D880923425712B2BB658B9196932E02C78B2582FE742DAA28", + /* y */ + "32879423AB1A0375895786C4BB46E9565FDE0B5344766740AF268ADB32322E5C", + "4"} + , + {NID_id_tc26_gost_3410_2012_512_paramSetC, + /* a */ + "DC9203E514A721875485A529D2C722FB187BC8980EB866644DE41C68E1430645" + "46E861C0E2C9EDD92ADE71F46FCF50FF2AD97F951FDA9F2A2EB6546F39689BD3", + /* b */ + "B4C4EE28CEBC6C2C8AC12952CF37F16AC7EFB6A9F69F4B57FFDA2E4F0DE5ADE0" + "38CBC2FFF719D2C18DE0284B8BFEF3B52B8CC7A5F5BF0A3C8D2319A5312557E1", + /* p */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7", + /* m */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "26336E91941AAC0130CEA7FD451D40B323B6A79E9DA6849A5188F3BD1FC08FB4", + /* x */ + "E2E31EDFC23DE7BDEBE241CE593EF5DE2295B7A9CBAEF021D385F7074CEA043A" + "A27272A7AE602BF2A7B9033DB9ED3610C6FB85487EAE97AAC5BC7928C1950148", + /* y */ + "F5CE40D95B5EB899ABBCCFF5911CB8577939804D6527378B8C108C3D2090FF9B" + "E18E2D33E3021ED2EF32D85822423B6304F726AA854BAE07D0396E9A9ADDC40F", + "4"} + , {NID_undef, NULL, NULL, NULL, NULL, NULL, NULL, NULL} }; diff --git a/test_curves.c b/test_curves.c new file mode 100644 index 0000000..7f36c75 --- /dev/null +++ b/test_curves.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2018 vt@altlinux.org. All Rights Reserved. + * + * Contents licensed under the terms of the OpenSSL license + * See https://www.openssl.org/source/license.html for details + */ + +#include "e_gost_err.h" +#include "gost_lcl.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define T(e) ({ if (!(e)) { \ + ERR_print_errors_fp(stderr); \ + OpenSSLDie(__FILE__, __LINE__, #e); \ + } \ + }) + +#define cRED "\033[1;31m" +#define cDRED "\033[0;31m" +#define cGREEN "\033[1;32m" +#define cDGREEN "\033[0;32m" +#define cBLUE "\033[1;34m" +#define cDBLUE "\033[0;34m" +#define cNORM "\033[m" +#define TEST_ASSERT(e) {if ((test = (e))) \ + printf(cRED " Test FAILED\n" cNORM); \ + else \ + printf(cGREEN " Test passed\n" cNORM);} + +struct test_curve { + int nid; + const char *name; + int listed; +}; + +static struct test_curve test_curves[] = { +#if 2001 + { NID_id_GostR3410_2001_TestParamSet, }, + { NID_id_GostR3410_2001_CryptoPro_A_ParamSet }, + { NID_id_GostR3410_2001_CryptoPro_B_ParamSet }, + { NID_id_GostR3410_2001_CryptoPro_C_ParamSet }, + { NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet }, + { NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet }, +#endif + { + NID_id_tc26_gost_3410_2012_512_paramSetA, + "id-tc26-gost-3410-2012-512-paramSetA", + }, + { + NID_id_tc26_gost_3410_2012_512_paramSetB, + "id-tc26-gost-3410-2012-512-paramSetB", + }, + { + NID_id_tc26_gost_3410_2012_512_paramSetC, + "id-tc26-gost-3410-2012-512-paramSetC", + }, + { + NID_id_tc26_gost_3410_2012_256_paramSetA, + "id-tc26-gost-3410-2012-256-paramSetA", + }, + 0, +}; + +static struct test_curve *get_test_curve(int nid) +{ + int i; + + for (i = 0; test_curves[i].nid; i++) + if (test_curves[i].nid == nid) + return &test_curves[i]; + return NULL; +} + +static void print_bn(const char *name, const BIGNUM *n) +{ + printf("%3s = ", name); + BN_print_fp(stdout, n); + printf("\n"); +} + +// https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography +static int parameter_test(struct test_curve *tc) +{ + const int nid = tc->nid; + int test; + + printf(cBLUE "Test curve NID %d" cNORM, nid); + if (tc->name) + printf(cBLUE ": %s" cNORM, tc->name); + else if (OBJ_nid2sn(nid)) + printf(cBLUE ": %s" cNORM, OBJ_nid2sn(nid)); + printf("\n"); + + if (!OBJ_nid2obj(nid)) { + printf(cRED "NID %d not found\n" cNORM, nid); + return 1; + } + + /* nid resolves in both directions */ + const char *sn, *ln; + T(sn = OBJ_nid2sn(nid)); + T(ln = OBJ_nid2ln(nid)); + if (tc->name) + T(!strcmp(tc->name, OBJ_nid2sn(nid))); + T(nid == OBJ_sn2nid(sn)); + T(nid == OBJ_ln2nid(ln)); + + EC_KEY *ec; + T(ec = EC_KEY_new()); + if (!fill_GOST_EC_params(ec, nid)) { + printf(cRED "fill_GOST_EC_params FAIL\n" cNORM); + ERR_print_errors_fp(stderr); + return 1; + } + + const EC_GROUP *group; + T(group = EC_KEY_get0_group(ec)); + + BN_CTX *ctx; + T(ctx = BN_CTX_new()); + BIGNUM *p, *a, *b; + T(p = BN_new()); + T(a = BN_new()); + T(b = BN_new()); + EC_GROUP_get_curve_GFp(group, p, a, b, ctx); + print_bn("p", p); + print_bn("a", a); + print_bn("b", b); + T(!BN_is_zero(p)); + T(BN_is_odd(p)); /* Should be odd for F_p */ + T(!BN_is_zero(a)); + T(!BN_is_zero(b)); + + /* Check generator */ + const EC_POINT *generator; + T(generator = EC_GROUP_get0_generator(group)); + BIGNUM *x, *y; + T(x = BN_new()); + T(y = BN_new()); + T(EC_POINT_get_affine_coordinates_GFp(group, generator, x, y, ctx)); + print_bn("x", x); + print_bn("y", y); + T(!BN_is_zero(y)); + + /* Generator is not identity element 0 */ + T(EC_POINT_is_at_infinity(group, generator) == 0); + + /* x and y is in range [1 .. p-1] */ + T(!BN_is_negative(x)); + T(!BN_is_negative(y)); + T(BN_cmp(x, p) < 0); + T(BN_cmp(y, p) < 0); + + /* Generator should be on curve */ + T(EC_POINT_is_on_curve(group, generator, ctx) == 1); + + /* y^2 == (x^3 + ax + b) mod p + * Should be same as EC_POINT_is_on_curve(generator), + * but, let's calculate it manually. */ + BIGNUM *yy = BN_new(); + BIGNUM *r = BN_new(); + BIGNUM *xxx = BN_new(); + BIGNUM *ax = BN_new(); + T(yy && r && xxx && ax); + BN_set_word(r, 2); + BN_mod_exp(yy, y, r, p, ctx); + BN_set_word(r, 3); + BN_mod_exp(xxx, x, r, p, ctx); + BN_mod_mul(ax, a, x, p, ctx); + BN_mod_add(xxx, xxx, ax, p, ctx); + BN_mod_add(xxx, xxx, b, p, ctx); + T(BN_cmp(yy, xxx) == 0); + + /* Check order */ + const BIGNUM *order; + T(order = EC_GROUP_get0_order(group)); + T(!BN_is_zero(order)); + print_bn("m", order); + T(!BN_is_zero(order)); + EC_POINT *point; + T((point = EC_POINT_new(group))); + T(EC_POINT_mul(group, point, NULL, generator, order, ctx)); + /* generator * order is the point at infinity? */ + T(EC_POINT_is_at_infinity(group, point) == 1); + + /* Check if order is cyclic */ + BIGNUM *k1 = BN_new(); + BIGNUM *k2 = BN_new(); + EC_POINT *p1 = EC_POINT_new(group); + EC_POINT *p2 = EC_POINT_new(group); + BN_set_word(k1, 3); + BN_set_word(k2, 3); + BN_add(k2, k2, order); + T(EC_POINT_mul(group, p1, NULL, generator, k1, ctx)); + T(EC_POINT_mul(group, p2, NULL, generator, k2, ctx)); + + /* Cofactor is 1 or 4 */ + const BIGNUM *c; + T(c = EC_GROUP_get0_cofactor(group)); + if (BN_is_odd(order)) + T(BN_is_word(c, 1)); + else + T(BN_is_word(c, 4)); + + TEST_ASSERT(0); + return test; +} + +int main(int argc, char **argv) +{ + int ret = 0; + + struct test_curve *tc; + for (tc = test_curves; tc->nid; tc++) { + ret |= parameter_test(tc); + } + + if (ret) + printf(cDRED "= Some tests FAILED!\n" cNORM); + else + printf(cDGREEN "= All tests passed!\n" cNORM); + return ret; +}