]> www.wagner.pp.ru Git - openssl-gost/engine.git/blobdiff - test_params.c
tcl_tests: ca.try: Ignore openssl crl exit status for 'corrupted CRL' test
[openssl-gost/engine.git] / test_params.c
index b4776628150e9fa487f7dbd4cfbc095525d3481e..114193346e63da2362a1b265ae74ac134e424b3b 100644 (file)
@@ -7,6 +7,11 @@
  * See https://www.openssl.org/source/license.html for details
  */
 
+#ifdef _MSC_VER
+# pragma warning(push, 3)
+# include <openssl/applink.c>
+# pragma warning(pop)
+#endif
 #include "e_gost_err.h"
 #include "gost_lcl.h"
 #include <openssl/evp.h>
 #include <openssl/safestack.h>
 #include <string.h>
 
-#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;
 }