X-Git-Url: http://www.wagner.pp.ru/gitweb/?a=blobdiff_plain;f=test_params.c;h=114193346e63da2362a1b265ae74ac134e424b3b;hb=HEAD;hp=b4776628150e9fa487f7dbd4cfbc095525d3481e;hpb=d370b91c2fa5a5e81ce7a3ab710349f14dd9ed9e;p=openssl-gost%2Fengine.git diff --git a/test_params.c b/test_params.c index b477662..1141933 100644 --- a/test_params.c +++ b/test_params.c @@ -7,6 +7,11 @@ * See https://www.openssl.org/source/license.html for details */ +#ifdef _MSC_VER +# pragma warning(push, 3) +# include +# pragma warning(pop) +#endif #include "e_gost_err.h" #include "gost_lcl.h" #include @@ -19,17 +24,17 @@ #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 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" @@ -39,9 +44,9 @@ #define cDBLUE "\033[0;34m" #define cNORM "\033[m" #define TEST_ASSERT(e) {if ((test = (e))) \ - printf(cRED " Test FAILED\n" cNORM); \ + printf(cRED " Test FAILED" cNORM "\n"); \ else \ - printf(cGREEN " Test passed\n" cNORM);} + printf(cGREEN " Test passed" cNORM "\n");} struct test_param { unsigned int param; /* NID of EC parameters */ @@ -873,20 +878,39 @@ static void hexdump(const void *ptr, size_t len) static void print_test_result(int err) { if (err == 1) - printf(cGREEN "correct\n" cNORM); + printf(cGREEN "correct" cNORM "\n"); else if (err == 0) - printf(cRED "incorrect\n" cNORM); + printf(cRED "incorrect" cNORM "\n"); else ERR_print_errors_fp(stderr); } +/* copy-paste from crypto/crmf/crmf_lib.c */ +static int X509_PUBKEY_cmp(X509_PUBKEY *a, X509_PUBKEY *b) +{ + X509_ALGOR *algA = NULL, *algB = NULL; + int res = 0; + + if (a == b) + return 0; + if (a == NULL || !X509_PUBKEY_get0_param(NULL, NULL, NULL, &algA, a) + || algA == NULL) + return -1; + if (b == NULL || !X509_PUBKEY_get0_param(NULL, NULL, NULL, &algB, b) + || algB == NULL) + return 1; + if ((res = X509_ALGOR_cmp(algA, algB)) != 0) + return res; + return !EVP_PKEY_cmp(X509_PUBKEY_get0(a), X509_PUBKEY_get0(b)); +} + static int test_cert(struct test_cert *tc) { - int err = 0; + int ret = 0, err; X509 *x; const unsigned char *p; - printf(cBLUE "Test %s (it):\n" cNORM, tc->name); + printf(cBLUE "Test %s (it): " cNORM, tc->name); p = tc->cert; T(x = d2i_X509(NULL, &p, tc->len)); @@ -914,18 +938,114 @@ static int test_cert(struct test_cert *tc) printf(" (curve %s)\n", OBJ_nid2sn(param_nid)); sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free); + /* + * Conversion tests. + */ + /* Convert cert to DER and back. */ + BIO *bp; + T(bp = BIO_new(BIO_s_mem())); + T(i2d_X509_bio(bp, x)); + X509 *y = NULL; + T(d2i_X509_bio(bp, &y)); + err = X509_cmp(x, y); + printf(" d2i_X509_bio\t\t\t"); + print_test_result(!err); + ret |= err; + X509_free(y); + + /* Convert cert to PEM and back. */ + y = NULL; + T(PEM_write_bio_X509(bp, x)); + T(PEM_read_bio_X509(bp, &y, 0, NULL)); + err = X509_cmp(x, y); + printf(" PEM_read_bio_X509\t\t"); + print_test_result(!err); + ret |= err; + X509_free(y); + + /* Convert public key to PEM and back. */ + T(BIO_reset(bp)); + T(PEM_write_bio_X509_PUBKEY(bp, xk)); + X509_PUBKEY *tk = NULL; + T(PEM_read_bio_X509_PUBKEY(bp, &tk, NULL, NULL)); + err = X509_PUBKEY_cmp(xk, tk); + X509_PUBKEY_free(tk); + printf(" PEM_read_bio_X509_PUBKEY\t"); + print_test_result(!err); + ret |= err; + + /* Convert public key to DER and back. */ + T(BIO_reset(bp)); + T(i2d_X509_PUBKEY_bio(bp, xk)); + tk = NULL; + T(d2i_X509_PUBKEY_bio(bp, &tk)); + err = X509_PUBKEY_cmp(xk, tk); + X509_PUBKEY_free(tk); + printf(" d2i_X509_PUBKEY_bio\t\t"); + print_test_result(!err); + ret |= err; + BIO_free(bp); + /* * Verify */ - printf(" X509_verify API\t"); + printf(" X509_verify API\t\t"); fflush(stdout); EVP_PKEY *pk; TE(pk = X509_get0_pubkey(x)); /* Similar to: openssl verify -partial_chain -check_ss_sig ... */ + /* X509_verify uses EVP_DigestVerify internally */ err = X509_verify(x, pk); print_test_result(err); + ret |= err != 1; + + /* Verify manually. */ + const ASN1_BIT_STRING *signature; + X509_get0_signature(&signature, NULL, x); + unsigned char *tbs = NULL; /* signed part */ + int tbs_len; + T((tbs_len = i2d_re_X509_tbs(x, &tbs)) > 0); + int algnid, hash_nid, pknid; + T(algnid = X509_get_signature_nid(x)); + T(OBJ_find_sigid_algs(algnid, &hash_nid, &pknid)); + + printf(" EVP_Verify API\t\t"); + EVP_MD_CTX *md_ctx; + T(md_ctx = EVP_MD_CTX_new()); + const EVP_MD *mdtype; + T(mdtype = EVP_get_digestbynid(hash_nid)); + T(EVP_VerifyInit(md_ctx, mdtype)); + T(EVP_VerifyUpdate(md_ctx, tbs, tbs_len)); + err = EVP_VerifyFinal(md_ctx, signature->data, signature->length, pk); + print_test_result(err); + EVP_MD_CTX_free(md_ctx); + ret |= err != 1; - return err != 1; + X509_free(x); + OPENSSL_free(tbs); + return ret; +} + +/* Generate EC_KEY with proper parameters using temporary PKEYs. + * This emulates fill_GOST_EC_params() call. + */ +static int EC_KEY_create(int type, int param_nid, EC_KEY *dst) +{ + EVP_PKEY *pkey; + T(pkey = EVP_PKEY_new()); + T(EVP_PKEY_set_type(pkey, type)); + EVP_PKEY_CTX *ctx; + T(ctx = EVP_PKEY_CTX_new(pkey, NULL)); + T(EVP_PKEY_paramgen_init(ctx)); + T(EVP_PKEY_CTX_ctrl(ctx, type, -1, EVP_PKEY_CTRL_GOST_PARAMSET, param_nid, NULL)); + EVP_PKEY *pkey2 = NULL; + int err; + TE((err = EVP_PKEY_paramgen(ctx, &pkey2)) == 1); + T(EC_KEY_copy(dst, EVP_PKEY_get0(pkey2))); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + EVP_PKEY_free(pkey2); + return err; } static int test_param(struct test_param *t) @@ -935,8 +1055,7 @@ static int test_param(struct test_param *t) int hash_nid = 0; const char *sn = OBJ_nid2sn(t->param); - printf(cBLUE "Test %s (cp):\n" cNORM, sn); - //T(pkey = EVP_PKEY_new_raw_public_key(NID_id_GostR3410_2001, NULL, t->pub_key, 64)); + printf(cBLUE "Test %s (cp):" cNORM "\n", sn); switch (t->len) { case 256 / 8: @@ -962,7 +1081,7 @@ static int test_param(struct test_param *t) /* Manually construct public key */ EC_KEY *ec; T(ec = EC_KEY_new()); - T(fill_GOST_EC_params(ec, t->param)); + T(EC_KEY_create(type, t->param, ec)); const EC_GROUP *group; T(group = EC_KEY_get0_group(ec)); unsigned char *pub_key; @@ -992,32 +1111,53 @@ static int test_param(struct test_param *t) T(ctx = EVP_PKEY_CTX_new(pkey, NULL)); unsigned char *sig; T(sig = OPENSSL_malloc(siglen)); - /* Need to reverse provided signature for unknown reason */ + /* Need to reverse provided signature for unknown reason, + * contrary to how it goes into signature. */ BUF_reverse(sig, t->signature, siglen); /* Verify using EVP_PKEY_verify API */ - printf(" EVP_PKEY_verify API\t"); + printf(" EVP_PKEY_verify API\t\t"); T(EVP_PKEY_verify_init(ctx)); err = EVP_PKEY_verify(ctx, sig, siglen, t->hash, t->len); + EVP_PKEY_CTX_free(ctx); print_test_result(err); ret |= err != 1; /* Verify using EVP_Verify API */ if (t->data) { - printf(" EVP_Verify API\t"); + printf(" EVP_Verify API\t\t"); EVP_MD_CTX *md_ctx; T(md_ctx = EVP_MD_CTX_new()); const EVP_MD *mdtype; T(mdtype = EVP_get_digestbynid(hash_nid)); T(EVP_VerifyInit(md_ctx, mdtype)); - T(EVP_VerifyUpdate(md_ctx, t->data, t->data_len)); + /* Feed byte-by-byte. */ + size_t i; + for (i = 0; i < t->data_len; i++) + T(EVP_VerifyUpdate(md_ctx, &t->data[i], 1)); err = EVP_VerifyFinal(md_ctx, sig, siglen, pkey); print_test_result(err); EVP_MD_CTX_free(md_ctx); ret |= err != 1; } + /* Verify using EVP_DigestVerifyInit API */ + if (t->data) { + printf(" EVP_DigestVerifyInit API\t"); + EVP_MD_CTX *md_ctx; + T(md_ctx = EVP_MD_CTX_new()); + const EVP_MD *mdtype; + T(mdtype = EVP_get_digestbynid(hash_nid)); + T(EVP_DigestVerifyInit(md_ctx, NULL, mdtype, NULL, pkey)); + /* Verify in one step. */ + err = EVP_DigestVerify(md_ctx, sig, siglen, t->data, t->data_len); + print_test_result(err); + EVP_MD_CTX_free(md_ctx); + ret |= err != 1; + } + OPENSSL_free(sig); + EVP_PKEY_free(pkey); return ret; } @@ -1026,10 +1166,6 @@ int main(int argc, char **argv) int ret = 0; OPENSSL_add_all_algorithms_conf(); - ERR_load_crypto_strings(); - ENGINE *e = ENGINE_new(); - bind_gost(e, "gost"); - ENGINE_register_complete(e); struct test_param **tpp; for (tpp = test_params; *tpp; tpp++) @@ -1039,5 +1175,9 @@ int main(int argc, char **argv) for (tc = test_certs; tc->cert; tc++) ret |= test_cert(tc); + if (ret) + printf(cDRED "= Some tests FAILED!" cNORM "\n"); + else + printf(cDGREEN "= All tests passed!" cNORM "\n"); return ret; }