]> git.ipfire.org Git - thirdparty/openssl.git/blobdiff - test/ectest.c
[test] computing ECC cofactors: regression test
[thirdparty/openssl.git] / test / ectest.c
index 7236b43bd1f7be01efa89d47ecec54df301ffc0c..2cbbd4e34074d99b09dbace4a3abecd175912b89 100644 (file)
@@ -1625,22 +1625,22 @@ static int check_named_curve_test(int id)
     }
 
     /* Passes because this is a valid curve */
-    if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0), nid)
+    if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0, NULL), nid)
         /* Only NIST curves pass */
-        || !TEST_int_eq(EC_GROUP_check_named_curve(group, 1),
+        || !TEST_int_eq(EC_GROUP_check_named_curve(group, 1, NULL),
                         EC_curve_nid2nist(nid) != NULL ? nid : NID_undef))
         goto err;
 
     /* Fail if the curve name doesn't match the parameters */
     EC_GROUP_set_curve_name(group, nid + 1);
     ERR_set_mark();
-    if (!TEST_int_le(EC_GROUP_check_named_curve(group, 0), 0))
+    if (!TEST_int_le(EC_GROUP_check_named_curve(group, 0, NULL), 0))
         goto err;
     ERR_pop_to_mark();
 
     /* Restore curve name and ensure it's passing */
     EC_GROUP_set_curve_name(group, nid);
-    if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0), nid))
+    if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0, NULL), nid))
         goto err;
 
     if (!TEST_int_eq(EC_GROUP_set_seed(group, invalid_seed, invalid_seed_len),
@@ -1652,47 +1652,46 @@ static int check_named_curve_test(int id)
          * If the built-in curve has a seed and we set the seed to another value
          * then it will fail the check.
          */
-        if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0), 0))
+        if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0, NULL), 0))
             goto err;
     } else {
         /*
          * If the built-in curve does not have a seed then setting the seed will
          * pass the check (as the seed is optional).
          */
-        if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0), nid))
+        if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0, NULL), nid))
             goto err;
     }
     /* Pass if the seed is unknown (as it is optional) */
     if (!TEST_int_eq(EC_GROUP_set_seed(group, NULL, 0), 1)
-        || !TEST_int_eq(EC_GROUP_check_named_curve(group, 0), nid))
+        || !TEST_int_eq(EC_GROUP_check_named_curve(group, 0, NULL), nid))
         goto err;
 
     /* Check that a duped group passes */
-    if (!TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0), nid))
+    if (!TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), nid))
         goto err;
 
     /* check that changing any generator parameter fails */
     if (!TEST_true(EC_GROUP_set_generator(gtest, other_gen, group_order,
                                           group_cofactor))
-        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0), 0)
+        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), 0)
         || !TEST_true(EC_GROUP_set_generator(gtest, group_gen, other_order,
                                              group_cofactor))
-        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0), 0)
+        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), 0)
         /* The order is not an optional field, so this should fail */
-        || !TEST_true(EC_GROUP_set_generator(gtest, group_gen, NULL,
-                                             group_cofactor))
-        || !TEST_int_le(EC_GROUP_check_named_curve(gtest, 0), 0)
+        || TEST_true(EC_GROUP_set_generator(gtest, group_gen, NULL,
+                                            group_cofactor))
         || !TEST_true(EC_GROUP_set_generator(gtest, group_gen, group_order,
                                              other_cofactor))
-        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0), 0)
+        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), 0)
         /* Check that if the cofactor is not set then it still passes */
         || !TEST_true(EC_GROUP_set_generator(gtest, group_gen, group_order,
                                              NULL))
-        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0), nid)
+        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), nid)
         /* check that restoring the generator passes */
         || !TEST_true(EC_GROUP_set_generator(gtest, group_gen, group_order,
                                              group_cofactor))
-        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0), nid))
+        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), nid))
         goto err;
 
     /*
@@ -1704,7 +1703,7 @@ static int check_named_curve_test(int id)
      */
     ERR_set_mark();
     if (EC_GROUP_set_curve(gtest, other_p, group_a, group_b, NULL)) {
-        if (!TEST_int_le(EC_GROUP_check_named_curve(gtest, 0), 0))
+        if (!TEST_int_le(EC_GROUP_check_named_curve(gtest, 0, NULL), 0))
             goto err;
     } else {
         /* clear the error stack if EC_GROUP_set_curve() failed */
@@ -1712,7 +1711,7 @@ static int check_named_curve_test(int id)
         ERR_set_mark();
     }
     if (EC_GROUP_set_curve(gtest, group_p, other_a, group_b, NULL)) {
-        if (!TEST_int_le(EC_GROUP_check_named_curve(gtest, 0), 0))
+        if (!TEST_int_le(EC_GROUP_check_named_curve(gtest, 0, NULL), 0))
             goto err;
     } else {
         /* clear the error stack if EC_GROUP_set_curve() failed */
@@ -1720,7 +1719,7 @@ static int check_named_curve_test(int id)
         ERR_set_mark();
     }
     if (EC_GROUP_set_curve(gtest, group_p, group_a, other_b, NULL)) {
-        if (!TEST_int_le(EC_GROUP_check_named_curve(gtest, 0), 0))
+        if (!TEST_int_le(EC_GROUP_check_named_curve(gtest, 0, NULL), 0))
             goto err;
     } else {
         /* clear the error stack if EC_GROUP_set_curve() failed */
@@ -1731,7 +1730,7 @@ static int check_named_curve_test(int id)
 
     /* Check that restoring the curve parameters passes */
     if (!TEST_true(EC_GROUP_set_curve(gtest, group_p, group_a, group_b, NULL))
-        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0), nid))
+        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), nid))
         goto err;
 
     ret = 1;
@@ -1778,7 +1777,7 @@ static int check_named_curve_lookup_test(int id)
     if (!TEST_ptr(g = EC_GROUP_new_from_ecparameters(p)))
         goto err;
 
-    if (!TEST_int_gt(rv = EC_GROUP_check_named_curve(g, 0), 0))
+    if (!TEST_int_gt(rv = EC_GROUP_check_named_curve(g, 0, NULL), 0))
         goto err;
     if (rv != nid) {
         /*
@@ -1820,7 +1819,7 @@ static int parameter_test(void)
     unsigned char *buf = NULL;
     int r = 0, len;
 
-    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_secp112r1))
+    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_secp384r1))
         || !TEST_ptr(ecparameters = EC_GROUP_get_ecparameters(group, NULL))
         || !TEST_ptr(group2 = EC_GROUP_new_from_ecparameters(ecparameters))
         || !TEST_int_eq(EC_GROUP_cmp(group, group2, NULL), 0))
@@ -1855,7 +1854,145 @@ err:
     OPENSSL_free(buf);
     return r;
 }
+
+/*-
+ * For named curves, test that:
+ * - the lib correctly computes the cofactor if passed a NULL or zero cofactor
+ * - a nonsensical cofactor throws an error (negative test)
+ * - nonsensical orders throw errors (negative tests)
+ */
+static int cardinality_test(int n)
+{
+    int ret = 0;
+    int nid = curves[n].nid;
+    BN_CTX *ctx = NULL;
+    EC_GROUP *g1 = NULL, *g2 = NULL;
+    EC_POINT *g2_gen = NULL;
+    BIGNUM *g1_p = NULL, *g1_a = NULL, *g1_b = NULL, *g1_x = NULL, *g1_y = NULL,
+           *g1_order = NULL, *g1_cf = NULL, *g2_cf = NULL;
+
+   TEST_info("Curve %s cardinality test", OBJ_nid2sn(nid));
+
+    if (!TEST_ptr(ctx = BN_CTX_new())
+        || !TEST_ptr(g1 = EC_GROUP_new_by_curve_name(nid))
+        || !TEST_ptr(g2 = EC_GROUP_new(EC_GROUP_method_of(g1)))) {
+        EC_GROUP_free(g1);
+        EC_GROUP_free(g2);
+        BN_CTX_free(ctx);
+        return 0;
+    }
+
+    BN_CTX_start(ctx);
+    g1_p = BN_CTX_get(ctx);
+    g1_a = BN_CTX_get(ctx);
+    g1_b = BN_CTX_get(ctx);
+    g1_x = BN_CTX_get(ctx);
+    g1_y = BN_CTX_get(ctx);
+    g1_order = BN_CTX_get(ctx);
+    g1_cf = BN_CTX_get(ctx);
+
+    if (!TEST_ptr(g2_cf = BN_CTX_get(ctx))
+        /* pull out the explicit curve parameters */
+        || !TEST_true(EC_GROUP_get_curve(g1, g1_p, g1_a, g1_b, ctx))
+        || !TEST_true(EC_POINT_get_affine_coordinates(g1,
+                      EC_GROUP_get0_generator(g1), g1_x, g1_y, ctx))
+        || !TEST_true(BN_copy(g1_order, EC_GROUP_get0_order(g1)))
+        || !TEST_true(EC_GROUP_get_cofactor(g1, g1_cf, ctx))
+        /* construct g2 manually with g1 parameters */
+        || !TEST_true(EC_GROUP_set_curve(g2, g1_p, g1_a, g1_b, ctx))
+        || !TEST_ptr(g2_gen = EC_POINT_new(g2))
+        || !TEST_true(EC_POINT_set_affine_coordinates(g2, g2_gen, g1_x, g1_y, ctx))
+        /* pass NULL cofactor: lib should compute it */
+        || !TEST_true(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL))
+        || !TEST_true(EC_GROUP_get_cofactor(g2, g2_cf, ctx))
+        || !TEST_BN_eq(g1_cf, g2_cf)
+        /* pass zero cofactor: lib should compute it */
+        || !TEST_true(BN_set_word(g2_cf, 0))
+        || !TEST_true(EC_GROUP_set_generator(g2, g2_gen, g1_order, g2_cf))
+        || !TEST_true(EC_GROUP_get_cofactor(g2, g2_cf, ctx))
+        || !TEST_BN_eq(g1_cf, g2_cf)
+        /* negative test for invalid cofactor */
+        || !TEST_true(BN_set_word(g2_cf, 0))
+        || !TEST_true(BN_sub(g2_cf, g2_cf, BN_value_one()))
+        || TEST_true(EC_GROUP_set_generator(g2, g2_gen, g1_order, g2_cf))
+        /* negative test for NULL order */
+        || TEST_true(EC_GROUP_set_generator(g2, g2_gen, NULL, NULL))
+        /* negative test for zero order */
+        || !TEST_true(BN_set_word(g1_order, 0))
+        || TEST_true(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL))
+        /* negative test for negative order */
+        || !TEST_true(BN_set_word(g2_cf, 0))
+        || !TEST_true(BN_sub(g2_cf, g2_cf, BN_value_one()))
+        || TEST_true(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL))
+        /* negative test for too large order */
+        || !TEST_true(BN_lshift(g1_order, g1_p, 2))
+        || TEST_true(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL)))
+        goto err;
+    ret = 1;
+ err:
+    EC_POINT_free(g2_gen);
+    EC_GROUP_free(g1);
+    EC_GROUP_free(g2);
+    BN_CTX_end(ctx);
+    BN_CTX_free(ctx);
+    return ret;
+}
+
+static int check_ec_key_field_public_range_test(int id)
+{
+    int ret = 0, type = 0;
+    const EC_POINT *pub = NULL;
+    const EC_GROUP *group = NULL;
+    const EC_METHOD *meth = NULL;
+    const BIGNUM *field = NULL;
+    BIGNUM *x = NULL, *y = NULL;
+    EC_KEY *key = NULL;
+
+    if (!(TEST_ptr(x = BN_new())
+          && TEST_ptr(y = BN_new())
+          && TEST_ptr(key = EC_KEY_new_by_curve_name(curves[id].nid))
+          && TEST_ptr(group = EC_KEY_get0_group(key))
+          && TEST_ptr(meth = EC_GROUP_method_of(group))
+          && TEST_ptr(field = EC_GROUP_get0_field(group))
+          && TEST_int_gt(EC_KEY_generate_key(key), 0)
+          && TEST_int_gt(EC_KEY_check_key(key), 0)
+          && TEST_ptr(pub = EC_KEY_get0_public_key(key))
+          && TEST_int_gt(EC_POINT_get_affine_coordinates(group, pub, x, y,
+                                                         NULL), 0)))
+        goto err;
+
+    /*
+     * Make the public point out of range by adding the field (which will still
+     * be the same point on the curve). The add is different for char2 fields.
+     */
+    type = EC_METHOD_get_field_type(meth);
+#ifndef OPENSSL_NO_EC2M
+    if (type == NID_X9_62_characteristic_two_field) {
+        /* test for binary curves */
+        if (!TEST_true(BN_GF2m_add(x, x, field)))
+            goto err;
+    } else
 #endif
+    if (type == NID_X9_62_prime_field) {
+        /* test for prime curves */
+        if (!TEST_true(BN_add(x, x, field)))
+            goto err;
+    } else {
+        /* this should never happen */
+        TEST_error("Unsupported EC_METHOD field_type");
+        goto err;
+    }
+    if (!TEST_int_le(EC_KEY_set_public_key_affine_coordinates(key, x, y), 0))
+        goto err;
+
+    ret = 1;
+err:
+    BN_free(x);
+    BN_free(y);
+    EC_KEY_free(key);
+    return ret;
+}
+#endif /* OPENSSL_NO_EC */
 
 int setup_tests(void)
 {
@@ -1866,6 +2003,7 @@ int setup_tests(void)
         return 0;
 
     ADD_TEST(parameter_test);
+    ADD_ALL_TESTS(cardinality_test, crv_len);
     ADD_TEST(prime_field_tests);
 # ifndef OPENSSL_NO_EC2M
     ADD_TEST(char2_field_tests);
@@ -1880,7 +2018,8 @@ int setup_tests(void)
     ADD_TEST(group_field_test);
     ADD_ALL_TESTS(check_named_curve_test, crv_len);
     ADD_ALL_TESTS(check_named_curve_lookup_test, crv_len);
-#endif
+    ADD_ALL_TESTS(check_ec_key_field_public_range_test, crv_len);
+#endif /* OPENSSL_NO_EC */
     return 1;
 }