deprecate EC_POINTs_mul function
[openssl.git] / test / ectest.c
index 4f3bfb7569c3816d887b5dd82dde3fa568bdbea2..bbcd9677d58fa69564fed576bb4ad69f4dd167cf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
@@ -8,6 +8,14 @@
  * https://www.openssl.org/source/license.html
  */
 
+/*
+ * We need access to the deprecated EC_POINTs_mul for testing purposes
+ * when the deprecated calls are not hidden
+ */
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+# define OPENSSL_SUPPRESS_DEPRECATED
+#endif
+
 #include <string.h>
 #include "internal/nelem.h"
 #include "testutil.h"
@@ -64,8 +72,10 @@ static int group_order_tests(EC_GROUP *group)
         goto err;
 
     for (i = 1; i <= 2; i++) {
+# ifndef OPENSSL_NO_DEPRECATED_3_0
         const BIGNUM *scalars[6];
         const EC_POINT *points[6];
+# endif
 
         if (!TEST_true(BN_set_word(n1, i))
             /*
@@ -97,11 +107,11 @@ static int group_order_tests(EC_GROUP *group)
             /* Add P to verify the result. */
             || !TEST_true(EC_POINT_add(group, Q, Q, P, ctx))
             || !TEST_true(EC_POINT_is_at_infinity(group, Q))
-
-            /* Exercise EC_POINTs_mul, including corner cases. */
             || !TEST_false(EC_POINT_is_at_infinity(group, P)))
             goto err;
 
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+        /* Exercise EC_POINTs_mul, including corner cases. */
         scalars[0] = scalars[1] = BN_value_one();
         points[0]  = points[1]  = P;
 
@@ -125,6 +135,7 @@ static int group_order_tests(EC_GROUP *group)
         if (!TEST_true(EC_POINTs_mul(group, P, NULL, 6, points, scalars, ctx))
             || !TEST_true(EC_POINT_is_at_infinity(group, P)))
             goto err;
+# endif
     }
 
     r = 1;
@@ -152,8 +163,10 @@ static int prime_field_tests(void)
              *P_256 = NULL, *P_384 = NULL, *P_521 = NULL;
     EC_POINT *P = NULL, *Q = NULL, *R = NULL;
     BIGNUM *x = NULL, *y = NULL, *z = NULL, *yplusone = NULL;
+# ifndef OPENSSL_NO_DEPRECATED_3_0
     const EC_POINT *points[4];
     const BIGNUM *scalars[4];
+# endif
     unsigned char buf[100];
     size_t len, r = 0;
     int k;
@@ -268,15 +281,6 @@ static int prime_field_tests(void)
     test_output_memory("Generator as octet string, hybrid form:",
                        buf, len);
 
-    if (!TEST_true(EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z,
-                                                            ctx)))
-        goto err;
-    TEST_info("A representation of the inverse of that generator in");
-    TEST_note("Jacobian projective coordinates");
-    test_output_bignum("x", x);
-    test_output_bignum("y", y);
-    test_output_bignum("z", z);
-
     if (!TEST_true(EC_POINT_invert(group, P, ctx))
         || !TEST_int_eq(0, EC_POINT_cmp(group, P, R, ctx))
 
@@ -287,7 +291,7 @@ static int prime_field_tests(void)
 
         || !TEST_true(BN_hex2bn(&p,                         "FFFFFFFF"
                                     "FFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF"))
-        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
+        || !TEST_int_eq(1, BN_check_prime(p, ctx, NULL))
         || !TEST_true(BN_hex2bn(&a,                         "FFFFFFFF"
                                     "FFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC"))
         || !TEST_true(BN_hex2bn(&b,                         "1C97BEFC"
@@ -327,7 +331,7 @@ static int prime_field_tests(void)
 
         || !TEST_true(BN_hex2bn(&p,                 "FFFFFFFFFFFFFFFF"
                                     "FFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"))
-        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
+        || !TEST_int_eq(1, BN_check_prime(p, ctx, NULL))
         || !TEST_true(BN_hex2bn(&a,                 "FFFFFFFFFFFFFFFF"
                                     "FFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC"))
         || !TEST_true(BN_hex2bn(&b,                 "64210519E59C80E7"
@@ -366,7 +370,7 @@ static int prime_field_tests(void)
 
         || !TEST_true(BN_hex2bn(&p,         "FFFFFFFFFFFFFFFFFFFFFFFF"
                                     "FFFFFFFF000000000000000000000001"))
-        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
+        || !TEST_int_eq(1, BN_check_prime(p, ctx, NULL))
         || !TEST_true(BN_hex2bn(&a,         "FFFFFFFFFFFFFFFFFFFFFFFF"
                                     "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE"))
         || !TEST_true(BN_hex2bn(&b,         "B4050A850C04B3ABF5413256"
@@ -405,7 +409,7 @@ static int prime_field_tests(void)
 
         || !TEST_true(BN_hex2bn(&p, "FFFFFFFF000000010000000000000000"
                                     "00000000FFFFFFFFFFFFFFFFFFFFFFFF"))
-        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
+        || !TEST_int_eq(1, BN_check_prime(p, ctx, NULL))
         || !TEST_true(BN_hex2bn(&a, "FFFFFFFF000000010000000000000000"
                                     "00000000FFFFFFFFFFFFFFFFFFFFFFFC"))
         || !TEST_true(BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC"
@@ -446,7 +450,7 @@ static int prime_field_tests(void)
         || !TEST_true(BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
                                     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
                                     "FFFFFFFF0000000000000000FFFFFFFF"))
-        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
+        || !TEST_int_eq(1, BN_check_prime(p, ctx, NULL))
         || !TEST_true(BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
                                     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
                                     "FFFFFFFF0000000000000000FFFFFFFC"))
@@ -493,7 +497,7 @@ static int prime_field_tests(void)
                                     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
                                     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
                                     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"))
-        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
+        || !TEST_int_eq(1, BN_check_prime(p, ctx, NULL))
         || !TEST_true(BN_hex2bn(&a,                              "1FF"
                                     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
                                     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
@@ -557,6 +561,9 @@ static int prime_field_tests(void)
         || !TEST_true(EC_POINT_is_at_infinity(group, R))    /* R = P + 2Q */
         || !TEST_false(EC_POINT_is_at_infinity(group, Q)))
         goto err;
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+    TEST_note("combined multiplication ...");
     points[0] = Q;
     points[1] = Q;
     points[2] = Q;
@@ -567,11 +574,10 @@ static int prime_field_tests(void)
         || !TEST_BN_even(y)
         || !TEST_true(BN_rshift1(y, y)))
         goto err;
+
     scalars[0] = y;         /* (group order + 1)/2, so y*Q + y*Q = Q */
     scalars[1] = y;
 
-    TEST_note("combined multiplication ...");
-
     /* z is still the group order */
     if (!TEST_true(EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))
         || !TEST_true(EC_POINTs_mul(group, R, z, 2, points, scalars, ctx))
@@ -602,10 +608,8 @@ static int prime_field_tests(void)
     if (!TEST_true(EC_POINTs_mul(group, P, NULL, 4, points, scalars, ctx))
         || !TEST_true(EC_POINT_is_at_infinity(group, P)))
         goto err;
-
+# endif
     TEST_note(" ok\n");
-
-
     r = 1;
 err:
     BN_CTX_free(ctx);
@@ -812,8 +816,10 @@ static int char2_curve_test(int n)
     BIGNUM *x = NULL, *y = NULL, *z = NULL, *cof = NULL, *yplusone = NULL;
     EC_GROUP *group = NULL, *variable = NULL;
     EC_POINT *P = NULL, *Q = NULL, *R = NULL;
+# ifndef OPENSSL_NO_DEPRECATED_3_0
     const EC_POINT *points[3];
     const BIGNUM *scalars[3];
+# endif
     struct c2_curve_test *const test = char2_curve_tests + n;
 
     if (!TEST_ptr(ctx = BN_CTX_new())
@@ -897,6 +903,8 @@ static int char2_curve_test(int n)
             || !TEST_false(EC_POINT_is_at_infinity(group, Q)))
             goto err;
 
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+        TEST_note("combined multiplication ...");
         points[0] = Q;
         points[1] = Q;
         points[2] = Q;
@@ -908,8 +916,6 @@ static int char2_curve_test(int n)
         scalars[0] = y;         /* (group order + 1)/2, so y*Q + y*Q = Q */
         scalars[1] = y;
 
-        TEST_note("combined multiplication ...");
-
         /* z is still the group order */
         if (!TEST_true(EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))
             || !TEST_true(EC_POINTs_mul(group, R, z, 2, points, scalars, ctx))
@@ -938,7 +944,8 @@ static int char2_curve_test(int n)
 
         if (!TEST_true(EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx))
             || !TEST_true(EC_POINT_is_at_infinity(group, P)))
-            goto err;;
+            goto err;
+# endif
     }
 
     r = 1;
@@ -1328,7 +1335,7 @@ static int nistp_single_test(int idx)
 
         || !TEST_ptr(NISTP = EC_GROUP_new(test->meth()))
         || !TEST_true(BN_hex2bn(&p, test->p))
-        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
+        || !TEST_int_eq(1, BN_check_prime(p, ctx, NULL))
         || !TEST_true(BN_hex2bn(&a, test->a))
         || !TEST_true(BN_hex2bn(&b, test->b))
         || !TEST_true(EC_GROUP_set_curve(NISTP, p, a, b, ctx))
@@ -1441,75 +1448,6 @@ err:
     BN_CTX_free(ctx);
     return r;
 }
-
-/*
- * Tests a point known to cause an incorrect underflow in an old version of
- * ecp_nist521.c
- */
-static int underflow_test(void)
-{
-    BN_CTX *ctx = NULL;
-    EC_GROUP *grp = NULL;
-    EC_POINT *P = NULL, *Q = NULL, *R = NULL;
-    BIGNUM *x1 = NULL, *y1 = NULL, *z1 = NULL, *x2 = NULL, *y2 = NULL;
-    BIGNUM *k = NULL;
-    int testresult = 0;
-    const char *x1str =
-        "1534f0077fffffe87e9adcfe000000000000000000003e05a21d2400002e031b1f4"
-        "b80000c6fafa4f3c1288798d624a247b5e2ffffffffffffffefe099241900004";
-    const char *p521m1 =
-        "1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-        "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe";
-
-    ctx = BN_CTX_new();
-    if (!TEST_ptr(ctx))
-        return 0;
-
-    BN_CTX_start(ctx);
-    x1 = BN_CTX_get(ctx);
-    y1 = BN_CTX_get(ctx);
-    z1 = BN_CTX_get(ctx);
-    x2 = BN_CTX_get(ctx);
-    y2 = BN_CTX_get(ctx);
-    k = BN_CTX_get(ctx);
-    if (!TEST_ptr(k))
-        goto err;
-
-    grp = EC_GROUP_new_by_curve_name(NID_secp521r1);
-    P = EC_POINT_new(grp);
-    Q = EC_POINT_new(grp);
-    R = EC_POINT_new(grp);
-    if (!TEST_ptr(grp) || !TEST_ptr(P) || !TEST_ptr(Q) || !TEST_ptr(R))
-        goto err;
-
-    if (!TEST_int_gt(BN_hex2bn(&x1, x1str), 0)
-            || !TEST_int_gt(BN_hex2bn(&y1, p521m1), 0)
-            || !TEST_int_gt(BN_hex2bn(&z1, p521m1), 0)
-            || !TEST_int_gt(BN_hex2bn(&k, "02"), 0)
-            || !TEST_true(EC_POINT_set_Jprojective_coordinates_GFp(grp, P, x1,
-                                                                   y1, z1, ctx))
-            || !TEST_true(EC_POINT_mul(grp, Q, NULL, P, k, ctx))
-            || !TEST_true(EC_POINT_get_affine_coordinates(grp, Q, x1, y1, ctx))
-            || !TEST_true(EC_POINT_dbl(grp, R, P, ctx))
-            || !TEST_true(EC_POINT_get_affine_coordinates(grp, R, x2, y2, ctx)))
-        goto err;
-
-    if (!TEST_int_eq(BN_cmp(x1, x2), 0)
-            || !TEST_int_eq(BN_cmp(y1, y2), 0))
-        goto err;
-
-    testresult = 1;
-
- err:
-    BN_CTX_end(ctx);
-    EC_POINT_free(P);
-    EC_POINT_free(Q);
-    EC_POINT_free(R);
-    EC_GROUP_free(grp);
-    BN_CTX_free(ctx);
-
-    return testresult;
-}
 # endif
 
 static const unsigned char p521_named[] = {
@@ -2121,6 +2059,96 @@ err:
     return r;
 }
 
+/*-
+ * random 256-bit explicit parameters curve, cofactor absent
+ * order:    0x0c38d96a9f892b88772ec2e39614a82f4f (132 bit)
+ * cofactor:   0x12bc94785251297abfafddf1565100da (125 bit)
+ */
+static const unsigned char params_cf_pass[] = {
+    0x30, 0x81, 0xcd, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86,
+    0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xe5, 0x00, 0x1f, 0xc5,
+    0xca, 0x71, 0x9d, 0x8e, 0xf7, 0x07, 0x4b, 0x48, 0x37, 0xf9, 0x33, 0x2d,
+    0x71, 0xbf, 0x79, 0xe7, 0xdc, 0x91, 0xc2, 0xff, 0xb6, 0x7b, 0xc3, 0x93,
+    0x44, 0x88, 0xe6, 0x91, 0x30, 0x44, 0x04, 0x20, 0xe5, 0x00, 0x1f, 0xc5,
+    0xca, 0x71, 0x9d, 0x8e, 0xf7, 0x07, 0x4b, 0x48, 0x37, 0xf9, 0x33, 0x2d,
+    0x71, 0xbf, 0x79, 0xe7, 0xdc, 0x91, 0xc2, 0xff, 0xb6, 0x7b, 0xc3, 0x93,
+    0x44, 0x88, 0xe6, 0x8e, 0x04, 0x20, 0x18, 0x8c, 0x59, 0x57, 0xc4, 0xbc,
+    0x85, 0x57, 0xc3, 0x66, 0x9f, 0x89, 0xd5, 0x92, 0x0d, 0x7e, 0x42, 0x27,
+    0x07, 0x64, 0xaa, 0x26, 0xed, 0x89, 0xc4, 0x09, 0x05, 0x4d, 0xc7, 0x23,
+    0x47, 0xda, 0x04, 0x41, 0x04, 0x1b, 0x6b, 0x41, 0x0b, 0xf9, 0xfb, 0x77,
+    0xfd, 0x50, 0xb7, 0x3e, 0x23, 0xa3, 0xec, 0x9a, 0x3b, 0x09, 0x31, 0x6b,
+    0xfa, 0xf6, 0xce, 0x1f, 0xff, 0xeb, 0x57, 0x93, 0x24, 0x70, 0xf3, 0xf4,
+    0xba, 0x7e, 0xfa, 0x86, 0x6e, 0x19, 0x89, 0xe3, 0x55, 0x6d, 0x5a, 0xe9,
+    0xc0, 0x3d, 0xbc, 0xfb, 0xaf, 0xad, 0xd4, 0x7e, 0xa6, 0xe5, 0xfa, 0x1a,
+    0x58, 0x07, 0x9e, 0x8f, 0x0d, 0x3b, 0xf7, 0x38, 0xca, 0x02, 0x11, 0x0c,
+    0x38, 0xd9, 0x6a, 0x9f, 0x89, 0x2b, 0x88, 0x77, 0x2e, 0xc2, 0xe3, 0x96,
+    0x14, 0xa8, 0x2f, 0x4f
+};
+
+/*-
+ * random 256-bit explicit parameters curve, cofactor absent
+ * order:    0x045a75c0c17228ebd9b169a10e34a22101 (131 bit)
+ * cofactor:   0x2e134b4ede82649f67a2e559d361e5fe (126 bit)
+ */
+static const unsigned char params_cf_fail[] = {
+    0x30, 0x81, 0xcd, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86,
+    0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xc8, 0x95, 0x27, 0x37,
+    0xe8, 0xe1, 0xfd, 0xcc, 0xf9, 0x6e, 0x0c, 0xa6, 0x21, 0xc1, 0x7d, 0x6b,
+    0x9d, 0x44, 0x42, 0xea, 0x73, 0x4e, 0x04, 0xb6, 0xac, 0x62, 0x50, 0xd0,
+    0x33, 0xc2, 0xea, 0x13, 0x30, 0x44, 0x04, 0x20, 0xc8, 0x95, 0x27, 0x37,
+    0xe8, 0xe1, 0xfd, 0xcc, 0xf9, 0x6e, 0x0c, 0xa6, 0x21, 0xc1, 0x7d, 0x6b,
+    0x9d, 0x44, 0x42, 0xea, 0x73, 0x4e, 0x04, 0xb6, 0xac, 0x62, 0x50, 0xd0,
+    0x33, 0xc2, 0xea, 0x10, 0x04, 0x20, 0xbf, 0xa6, 0xa8, 0x05, 0x1d, 0x09,
+    0xac, 0x70, 0x39, 0xbb, 0x4d, 0xb2, 0x90, 0x8a, 0x15, 0x41, 0x14, 0x1d,
+    0x11, 0x86, 0x9f, 0x13, 0xa2, 0x63, 0x1a, 0xda, 0x95, 0x22, 0x4d, 0x02,
+    0x15, 0x0a, 0x04, 0x41, 0x04, 0xaf, 0x16, 0x71, 0xf9, 0xc4, 0xc8, 0x59,
+    0x1d, 0xa3, 0x6f, 0xe7, 0xc3, 0x57, 0xa1, 0xfa, 0x9f, 0x49, 0x7c, 0x11,
+    0x27, 0x05, 0xa0, 0x7f, 0xff, 0xf9, 0xe0, 0xe7, 0x92, 0xdd, 0x9c, 0x24,
+    0x8e, 0xc7, 0xb9, 0x52, 0x71, 0x3f, 0xbc, 0x7f, 0x6a, 0x9f, 0x35, 0x70,
+    0xe1, 0x27, 0xd5, 0x35, 0x8a, 0x13, 0xfa, 0xa8, 0x33, 0x3e, 0xd4, 0x73,
+    0x1c, 0x14, 0x58, 0x9e, 0xc7, 0x0a, 0x87, 0x65, 0x8d, 0x02, 0x11, 0x04,
+    0x5a, 0x75, 0xc0, 0xc1, 0x72, 0x28, 0xeb, 0xd9, 0xb1, 0x69, 0xa1, 0x0e,
+    0x34, 0xa2, 0x21, 0x01
+};
+
+/*-
+ * Test two random 256-bit explicit parameters curves with absent cofactor.
+ * The two curves are chosen to roughly straddle the bounds at which the lib
+ * can compute the cofactor automatically, roughly 4*sqrt(p). So test that:
+ *
+ * - params_cf_pass: order is sufficiently close to p to compute cofactor
+ * - params_cf_fail: order is too far away from p to compute cofactor
+ *
+ * For standards-compliant curves, cofactor is chosen as small as possible.
+ * So you can see neither of these curves are fit for cryptographic use.
+ *
+ * Some standards even mandate an upper bound on the cofactor, e.g. SECG1 v2:
+ * h <= 2**(t/8) where t is the security level of the curve, for which the lib
+ * will always succeed in computing the cofactor. Neither of these curves
+ * conform to that -- this is just robustness testing.
+ */
+static int cofactor_range_test(void)
+{
+    EC_GROUP *group = NULL;
+    BIGNUM *cf = NULL;
+    int ret = 0;
+    const unsigned char *b1 = (const unsigned char *)params_cf_fail;
+    const unsigned char *b2 = (const unsigned char *)params_cf_pass;
+
+    if (!TEST_ptr(group = d2i_ECPKParameters(NULL, &b1, sizeof(params_cf_fail)))
+        || !TEST_BN_eq_zero(EC_GROUP_get0_cofactor(group))
+        || !TEST_ptr(group = d2i_ECPKParameters(&group, &b2,
+                                                sizeof(params_cf_pass)))
+        || !TEST_int_gt(BN_hex2bn(&cf, "12bc94785251297abfafddf1565100da"), 0)
+        || !TEST_BN_eq(cf, EC_GROUP_get0_cofactor(group)))
+        goto err;
+    ret = 1;
+ err:
+    BN_free(cf);
+    EC_GROUP_free(group);
+    return ret;
+}
+
 /*-
  * For named curves, test that:
  * - the lib correctly computes the cofactor if passed a NULL or zero cofactor
@@ -2258,6 +2286,106 @@ err:
     EC_KEY_free(key);
     return ret;
 }
+
+/*
+ * Helper for ec_point_hex2point_test
+ *
+ * Self-tests EC_POINT_point2hex() against EC_POINT_hex2point() for the given
+ * (group,P) pair.
+ *
+ * If P is NULL use point at infinity.
+ */
+static ossl_inline
+int ec_point_hex2point_test_helper(const EC_GROUP *group, const EC_POINT *P,
+                                   point_conversion_form_t form,
+                                   BN_CTX *bnctx)
+{
+    int ret = 0;
+    EC_POINT *Q = NULL, *Pinf = NULL;
+    char *hex = NULL;
+
+    if (P == NULL) {
+        /* If P is NULL use point at infinity. */
+        if (!TEST_ptr(Pinf = EC_POINT_new(group))
+                || !TEST_true(EC_POINT_set_to_infinity(group, Pinf)))
+            goto err;
+        P = Pinf;
+    }
+
+    if (!TEST_ptr(hex = EC_POINT_point2hex(group, P, form, bnctx))
+            || !TEST_ptr(Q = EC_POINT_hex2point(group, hex, NULL, bnctx))
+            || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, bnctx)))
+        goto err;
+
+    /*
+     * The next check is most likely superfluous, as EC_POINT_cmp should already
+     * cover this.
+     * Nonetheless it increases the test coverage for EC_POINT_is_at_infinity,
+     * so we include it anyway!
+     */
+    if (Pinf != NULL
+            && !TEST_true(EC_POINT_is_at_infinity(group, Q)))
+        goto err;
+
+    ret = 1;
+
+ err:
+    EC_POINT_free(Pinf);
+    OPENSSL_free(hex);
+    EC_POINT_free(Q);
+
+    return ret;
+}
+
+/*
+ * This test self-validates EC_POINT_hex2point() and EC_POINT_point2hex()
+ */
+static int ec_point_hex2point_test(int id)
+{
+    int ret = 0, nid;
+    EC_GROUP *group = NULL;
+    const EC_POINT *G = NULL;
+    EC_POINT *P = NULL;
+    BN_CTX * bnctx = NULL;
+
+    /* Do some setup */
+    nid = curves[id].nid;
+    if (!TEST_ptr(bnctx = BN_CTX_new())
+            || !TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))
+            || !TEST_ptr(G = EC_GROUP_get0_generator(group))
+            || !TEST_ptr(P = EC_POINT_dup(G, group)))
+        goto err;
+
+    if (!TEST_true(ec_point_hex2point_test_helper(group, P,
+                                                  POINT_CONVERSION_COMPRESSED,
+                                                  bnctx))
+            || !TEST_true(ec_point_hex2point_test_helper(group, NULL,
+                                                         POINT_CONVERSION_COMPRESSED,
+                                                         bnctx))
+            || !TEST_true(ec_point_hex2point_test_helper(group, P,
+                                                         POINT_CONVERSION_UNCOMPRESSED,
+                                                         bnctx))
+            || !TEST_true(ec_point_hex2point_test_helper(group, NULL,
+                                                         POINT_CONVERSION_UNCOMPRESSED,
+                                                         bnctx))
+            || !TEST_true(ec_point_hex2point_test_helper(group, P,
+                                                         POINT_CONVERSION_HYBRID,
+                                                         bnctx))
+            || !TEST_true(ec_point_hex2point_test_helper(group, NULL,
+                                                         POINT_CONVERSION_HYBRID,
+                                                         bnctx)))
+        goto err;
+
+    ret = 1;
+
+ err:
+    EC_POINT_free(P);
+    EC_GROUP_free(group);
+    BN_CTX_free(bnctx);
+
+    return ret;
+}
+
 #endif /* OPENSSL_NO_EC */
 
 int setup_tests(void)
@@ -2269,6 +2397,7 @@ int setup_tests(void)
         return 0;
 
     ADD_TEST(parameter_test);
+    ADD_TEST(cofactor_range_test);
     ADD_ALL_TESTS(cardinality_test, crv_len);
     ADD_TEST(prime_field_tests);
 # ifndef OPENSSL_NO_EC2M
@@ -2277,7 +2406,6 @@ int setup_tests(void)
 # endif
 # ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
     ADD_ALL_TESTS(nistp_single_test, OSSL_NELEM(nistp_tests_params));
-    ADD_TEST(underflow_test);
 # endif
     ADD_ALL_TESTS(internal_curve_test, crv_len);
     ADD_ALL_TESTS(internal_curve_test_method, crv_len);
@@ -2286,6 +2414,7 @@ int setup_tests(void)
     ADD_ALL_TESTS(check_named_curve_lookup_test, crv_len);
     ADD_ALL_TESTS(check_ec_key_field_public_range_test, crv_len);
     ADD_ALL_TESTS(check_named_curve_from_ecparameters, crv_len);
+    ADD_ALL_TESTS(ec_point_hex2point_test, crv_len);
 #endif /* OPENSSL_NO_EC */
     return 1;
 }