From: Dmitry Belyavskiy Date: Mon, 28 Jan 2019 13:05:08 +0000 (+0300) Subject: Merge pull request #108 from vt-alt/perl X-Git-Tag: v3.0.0~311 X-Git-Url: http://www.wagner.pp.ru/gitweb/?a=commitdiff_plain;h=d0b341aa04b1871eee78cfbbe19900352f4ce1e7;hp=6d7502c539c8c5f0637c9db2f0da8410cfa2e300;p=openssl-gost%2Fengine.git Merge pull request #108 from vt-alt/perl run_tests: pass OPENSSL_ROOT_DIR into perl tests --- diff --git a/.travis.yml b/.travis.yml index 861ad17..f46d234 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,9 +24,9 @@ matrix: # compiler: gcc before_script: - - git clone -b ${OPENSSL_BRANCH} https://github.com/openssl/openssl.git + - git clone --depth 1 -b ${OPENSSL_BRANCH} https://github.com/openssl/openssl.git - cd openssl - - ./config shared --prefix=${PREFIX} --openssldir=${PREFIX} && make all install_sw > build.log 2>&1 || (cat build.log && exit 1) + - ./config shared --prefix=${PREFIX} --openssldir=${PREFIX} && make -j$(nproc) all && make install_sw > build.log 2>&1 || (cat build.log && exit 1) - cd .. script: diff --git a/CMakeLists.txt b/CMakeLists.txt index 408da4d..326b8f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,15 +123,20 @@ 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_params test_params.c) target_link_libraries(test_params gost_engine gost_core ${OPENSSL_CRYPTO_LIBRARY}) add_test(NAME parameters COMMAND test_params) -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_sign test_sign.c) +target_link_libraries(test_sign gost_engine gost_core ${OPENSSL_CRYPTO_LIBRARY}) +add_test(NAME sign/verify + COMMAND test_sign) add_executable(test_context test_context.c) target_link_libraries(test_context gost_engine gost_core ${OPENSSL_CRYPTO_LIBRARY}) diff --git a/README.gost b/README.gost index db6b4b9..3579665 100644 --- a/README.gost +++ b/README.gost @@ -70,8 +70,8 @@ USAGE WITH COMMAND LINE openssl UTILITY Use -pkeyopt option to pass paramset to algorithm. The following paramsets are supported by gost2001: 0,A,B,C,XA,XB - gost2012_256: 0,A,B,C,XA,XB - gost2012_512: A,B + gost2012_256: 0,A,B,C,XA,XB,TCA,TCB,TCC,TCD + gost2012_512: A,B,C You can also use numeric representation of OID as to destinate paramset. diff --git a/benchmark/sign.c b/benchmark/sign.c index 2d1d786..765b9f0 100644 --- a/benchmark/sign.c +++ b/benchmark/sign.c @@ -23,9 +23,14 @@ const char *tests[] = { "md_gost12_256", "gost2012_256", "A", "md_gost12_256", "gost2012_256", "B", "md_gost12_256", "gost2012_256", "C", + "md_gost12_256", "gost2012_256", "TCA", + "md_gost12_256", "gost2012_256", "TCB", + "md_gost12_256", "gost2012_256", "TCC", + "md_gost12_256", "gost2012_256", "TCD", "md_gost12_512", "gost2012_512", "A", "md_gost12_512", "gost2012_512", "B", + "md_gost12_512", "gost2012_512", "C", NULL, }; diff --git a/gost_ameth.c b/gost_ameth.c index df59520..6ae2786 100644 --- a/gost_ameth.c +++ b/gost_ameth.c @@ -67,11 +67,18 @@ static ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key) switch (EVP_PKEY_base_id(key)) { case NID_id_GostR3410_2012_256: pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(key_ptr)); - gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_2012_256); + switch (pkey_param_nid) { + case NID_id_GostR3410_2001_TestParamSet: + case NID_id_GostR3410_2001_CryptoPro_A_ParamSet: + case NID_id_GostR3410_2001_CryptoPro_B_ParamSet: + case NID_id_GostR3410_2001_CryptoPro_C_ParamSet: + case NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet: + case NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet: + gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_2012_256); + } break; case NID_id_GostR3410_2012_512: pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(key_ptr)); - gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_2012_512); break; case NID_id_GostR3410_2001: pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(key_ptr)); diff --git a/gost_ec_sign.c b/gost_ec_sign.c index ba12783..3db118a 100644 --- a/gost_ec_sign.c +++ b/gost_ec_sign.c @@ -146,7 +146,7 @@ int fill_GOST_EC_params(EC_KEY *eckey, int nid) GOSTerr(GOST_F_FILL_GOST_EC_PARAMS, ERR_R_INTERNAL_ERROR); goto end; } - EC_GROUP_set_curve_name(grp, params->nid); + EC_GROUP_set_curve_name(grp, nid); if (!EC_KEY_set_group(eckey, grp)) { GOSTerr(GOST_F_FILL_GOST_EC_PARAMS, ERR_R_INTERNAL_ERROR); goto end; diff --git a/gost_pmeth.c b/gost_pmeth.c index b2e0a49..41bda94 100644 --- a/gost_pmeth.c +++ b/gost_pmeth.c @@ -208,6 +208,25 @@ static int pkey_gost_ec_ctrl_str_256(EVP_PKEY_CTX *ctx, default: return 0; } + } else if ((strlen(value) == 3) + && (toupper((unsigned char)value[0]) == 'T') + && (toupper((unsigned char)value[1]) == 'C')) { + switch (toupper((unsigned char)value[2])) { + case 'A': + param_nid = NID_id_tc26_gost_3410_2012_256_paramSetA; + break; + case 'B': + param_nid = NID_id_tc26_gost_3410_2012_256_paramSetB; + break; + case 'C': + param_nid = NID_id_tc26_gost_3410_2012_256_paramSetC; + break; + case 'D': + param_nid = NID_id_tc26_gost_3410_2012_256_paramSetD; + break; + default: + return 0; + } } else { R3410_ec_params *p = R3410_2001_paramset; param_nid = OBJ_txt2nid(value); @@ -252,6 +271,10 @@ static int pkey_gost_ec_ctrl_str_512(EVP_PKEY_CTX *ctx, param_nid = NID_id_tc26_gost_3410_2012_512_paramSetB; break; + case 'C': + param_nid = NID_id_tc26_gost_3410_2012_512_paramSetC; + break; + default: return 0; } @@ -320,6 +343,7 @@ static int pkey_gost2012_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) switch (data->sign_param_nid) { case NID_id_tc26_gost_3410_2012_512_paramSetA: case NID_id_tc26_gost_3410_2012_512_paramSetB: + case NID_id_tc26_gost_3410_2012_512_paramSetC: result = (EVP_PKEY_assign(pkey, NID_id_GostR3410_2012_512, ec)) ? 1 : 0; break; @@ -330,6 +354,10 @@ static int pkey_gost2012_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) case NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet: case NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet: case NID_id_GostR3410_2001_TestParamSet: + case NID_id_tc26_gost_3410_2012_256_paramSetA: + case NID_id_tc26_gost_3410_2012_256_paramSetB: + case NID_id_tc26_gost_3410_2012_256_paramSetC: + case NID_id_tc26_gost_3410_2012_256_paramSetD: result = (EVP_PKEY_assign(pkey, NID_id_GostR3410_2012_256, ec)) ? 1 : 0; break; diff --git a/test_curves.c b/test_curves.c index 1ee15b0..7c57c34 100644 --- a/test_curves.c +++ b/test_curves.c @@ -43,28 +43,19 @@ struct test_curve { static struct test_curve test_curves[] = { #if 2001 { NID_id_GostR3410_2001_TestParamSet, }, +#endif { 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", - }, + { 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", }, + { NID_id_tc26_gost_3410_2012_256_paramSetB, "id-tc26-gost-3410-2012-256-paramSetB", }, + { NID_id_tc26_gost_3410_2012_256_paramSetC, "id-tc26-gost-3410-2012-256-paramSetC", }, + { NID_id_tc26_gost_3410_2012_256_paramSetD, "id-tc26-gost-3410-2012-256-paramSetD", }, 0, }; diff --git a/test_sign.c b/test_sign.c new file mode 100644 index 0000000..763b097 --- /dev/null +++ b/test_sign.c @@ -0,0 +1,250 @@ +/* + * Test GOST 34.10 Sign/Verify operation for every curve parameter + * + * Copyright (C) 2019 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 +#include + +#define T(e) ({ if (!(e)) { \ + ERR_print_errors_fp(stderr); \ + OpenSSLDie(__FILE__, __LINE__, #e); \ + } \ + }) +#define TE(e) ({ if (!(e)) { \ + ERR_print_errors_fp(stderr); \ + fprintf(stderr, "Error at %s:%d %s\n", __FILE__, __LINE__, #e); \ + return -1; \ + } \ + }) + +#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_sign { + const char *name; + unsigned int nid; + size_t bits; + const char *paramset; +}; + +#define D(x,y,z) { .name = #x, .nid = x, .bits = y, .paramset = z } +static struct test_sign test_signs[] = { + D(NID_id_GostR3410_2001_CryptoPro_A_ParamSet, 256, "A"), + D(NID_id_GostR3410_2001_CryptoPro_B_ParamSet, 256, "B"), + D(NID_id_GostR3410_2001_CryptoPro_C_ParamSet, 256, "C"), + D(NID_id_tc26_gost_3410_2012_256_paramSetA, 256, "TCA"), + D(NID_id_tc26_gost_3410_2012_256_paramSetB, 256, "TCB"), + D(NID_id_tc26_gost_3410_2012_256_paramSetC, 256, "TCC"), + D(NID_id_tc26_gost_3410_2012_256_paramSetD, 256, "TCD"), + D(NID_id_tc26_gost_3410_2012_512_paramSetA, 512, "A"), + D(NID_id_tc26_gost_3410_2012_512_paramSetB, 512, "B"), + D(NID_id_tc26_gost_3410_2012_512_paramSetC, 512, "C"), + 0 +}; +#undef D + +static void hexdump(const void *ptr, size_t len) +{ + const unsigned char *p = ptr; + size_t i, j; + + for (i = 0; i < len; i += j) { + for (j = 0; j < 16 && i + j < len; j++) + printf("%s %02x", j? "" : "\n", p[i + j]); + } + printf("\n"); +} + +static void print_test_tf(int err, int val, const char *t, const char *f) +{ + if (err == 1) + printf(cGREEN "%s\n" cNORM, t); + else + printf(cRED "%s [%d]\n" cNORM, f, val); +} + +static void print_test_result(int err) +{ + if (err == 1) + printf(cGREEN "success\n" cNORM); + else if (err == 0) + printf(cRED "failure\n" cNORM); + else + ERR_print_errors_fp(stderr); +} + +static int test_sign(struct test_sign *t) +{ + int ret = 0, err; + size_t len = t->bits / 8; + + printf(cBLUE "Test %s:\n" cNORM, t->name); + + /* Signature type from size. */ + int type = 0; + const char *algname = NULL; + switch (t->bits) { + case 256: + type = NID_id_GostR3410_2012_256; + algname = "gost2012_256"; + break; + case 512: + type = NID_id_GostR3410_2012_512; + algname = "gost2012_512"; + } + + /* Keygen. */ + EVP_PKEY *pkey; + T(pkey = EVP_PKEY_new()); + TE(EVP_PKEY_set_type(pkey, type)); + EVP_PKEY_CTX *ctx; + T(ctx = EVP_PKEY_CTX_new(pkey, NULL)); + T(EVP_PKEY_keygen_init(ctx)); + T(EVP_PKEY_CTX_ctrl(ctx, type, -1, EVP_PKEY_CTRL_GOST_PARAMSET, t->nid, NULL)); + EVP_PKEY *priv_key = NULL; + err = EVP_PKEY_keygen(ctx, &priv_key); + printf("\tEVP_PKEY_keygen:\t"); + print_test_result(err); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + if (err != 1) + return -1; + + /* Create another key using string interface. */ + EVP_PKEY *key1; + T(key1 = EVP_PKEY_new()); + T(EVP_PKEY_set_type_str(key1, algname, strlen(algname))); + EVP_PKEY_CTX *ctx1; + T(ctx1 = EVP_PKEY_CTX_new(key1, NULL)); + T(EVP_PKEY_keygen_init(ctx1)); + T(EVP_PKEY_CTX_ctrl_str(ctx1, "paramset", t->paramset)); + EVP_PKEY *key2 = NULL; + err = EVP_PKEY_keygen(ctx1, &key2); + printf("\tEVP_PKEY_*_str:\t\t"); + print_test_result(err); + + /* Check if key type and curve_name match expected values. */ + int id = EVP_PKEY_id(key2); + err = id == type; + printf("\tEVP_PKEY_id (%d):\t", type); + print_test_tf(err, id, "match", "mismatch"); + ret |= !err; + + const EC_KEY *ec = EVP_PKEY_get0(key2); + const EC_GROUP *group = EC_KEY_get0_group(ec); + int curve_name = EC_GROUP_get_curve_name(group); + err = curve_name == t->nid; + printf("\tcurve_name (%d):\t", t->nid); + print_test_tf(err, curve_name, "match", "mismatch"); + ret |= !err; + + /* Compare both keys. + * Parameters should match, public keys should mismatch. + */ + err = EVP_PKEY_cmp_parameters(priv_key, key2); + printf("\tEVP_PKEY_cmp_parameters:"); + print_test_tf(err, err, "success", "failure"); + ret |= err != 1; + + err = EVP_PKEY_cmp(priv_key, key2); + err = (err < 0) ? err : !err; + printf("\tEVP_PKEY_cmp:\t\t"); + print_test_tf(err, err, "differ (good)", "equal (error)"); + ret |= err != 1; + EVP_PKEY_CTX_free(ctx1); + EVP_PKEY_free(key1); + + /* + * Prepare for sign testing. + */ + size_t siglen = EVP_PKEY_size(priv_key); + unsigned char *sig; + T(sig = OPENSSL_malloc(siglen)); + unsigned char *hash; + T(hash = OPENSSL_zalloc(len)); + T(ctx = EVP_PKEY_CTX_new(priv_key, NULL)); + + /* Sign. */ + T(EVP_PKEY_sign_init(ctx)); + err = EVP_PKEY_sign(ctx, sig, &siglen, hash, len); + printf("\tEVP_PKEY_sign:\t\t"); + print_test_result(err); + ret |= err != 1; + + /* Non-determinism test. + * Check that different signatures for the same data + * are not equal. */ + unsigned char *sig2; + T(sig2 = OPENSSL_malloc(siglen)); + TE(EVP_PKEY_sign(ctx, sig2, &siglen, hash, len) == 1); + printf("\tNon-determinism:\t"); + err = !!memcmp(sig, sig2, siglen); + print_test_result(err); + ret |= err != 1; + OPENSSL_free(sig2); + + /* Verify. */ + T(EVP_PKEY_verify_init(ctx)); + hash[0]++; /* JFF */ + err = EVP_PKEY_verify(ctx, sig, siglen, hash, len); + printf("\tEVP_PKEY_verify:\t"); + print_test_result(err); + ret |= err != 1; + + /* False positive Verify. */ + T(EVP_PKEY_verify_init(ctx)); + hash[0]++; + err = EVP_PKEY_verify(ctx, sig, siglen, hash, len); + err = (err < 0) ? err : !err; + printf("\tFalse positive test:\t"); + print_test_result(err); + ret |= err != 1; + + EVP_PKEY_CTX_free(ctx); + OPENSSL_free(sig); + OPENSSL_free(hash); + + return ret; +} + +int main(int argc, char **argv) +{ + int ret = 0; + + setenv("OPENSSL_CONF", "../example.conf", 0); + OPENSSL_add_all_algorithms_conf(); + ERR_load_crypto_strings(); + + struct test_sign *sp; + for (sp = test_signs; sp->name; sp++) + ret |= test_sign(sp); + + if (ret) + printf(cDRED "= Some tests FAILED!\n" cNORM); + else + printf(cDGREEN "= All tests passed!\n" cNORM); + return ret; +}