Fixed range of random produced in BN_is_prime_fasttest_ex() to be 1 < rand < w-1...
[openssl.git] / test / ectest.c
index 8e311e5d715273c27b934ba4ca26ff245e9ce7f9..73e8aa8732bdd14dbd46f584dcb89f0e121bddf5 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -7,21 +8,7 @@
  * https://www.openssl.org/source/license.html
  */
 
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- *
- * Portions of the attached software ("Contribution") are developed by
- * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
- *
- * The Contribution is licensed pursuant to the OpenSSL open source
- * license provided above.
- *
- * The elliptic curve binary polynomial software is originally written by
- * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
- *
- */
-
-#include "e_os.h"
+#include "internal/nelem.h"
 #include "testutil.h"
 
 #ifndef OPENSSL_NO_EC
 # include <openssl/bn.h>
 # include <openssl/opensslconf.h>
 
-# if defined(_MSC_VER) && defined(_MIPS_) && (_MSC_VER/100==12)
-/* suppress "too big too optimize" warning */
-#  pragma warning(disable:4959)
-# endif
-
 static size_t crv_len = 0;
 static EC_builtin_curve *curves = NULL;
 
@@ -161,7 +143,7 @@ static int prime_field_tests(void)
     const EC_POINT *points[4];
     const BIGNUM *scalars[4];
     unsigned char buf[100];
-    size_t i, len, r = 0;
+    size_t len, r = 0;
     int k;
 
     if (!TEST_ptr(ctx = BN_CTX_new())
@@ -187,15 +169,11 @@ static int prime_field_tests(void)
     if (!TEST_true(EC_GROUP_get_curve_GFp(group, p, a, b, ctx)))
         goto err;
 
-    BIO_printf(bio_out,
-            "Curve defined by Weierstrass equation\n"
-            "     y^2 = x^3 + a*x + b  (mod 0x");
-    BN_print(bio_out, p);
-    BIO_printf(bio_out, ")\n     a = 0x");
-    BN_print(bio_out, a);
-    BIO_printf(bio_out, "\n     b = 0x");
-    BN_print(bio_out, b);
-    BIO_printf(bio_out, "\n");
+    TEST_info("Curve defined by Weierstrass equation");
+    TEST_note("     y^2 = x^3 + a*x + b (mod p)");
+    test_output_bignum("a", a);
+    test_output_bignum("b", b);
+    test_output_bignum("p", p);
 
     buf[0] = 0;
     if (!TEST_ptr(P = EC_POINT_new(group))
@@ -219,32 +197,27 @@ static int prime_field_tests(void)
         if (!TEST_true(EC_POINT_get_affine_coordinates_GFp(group, Q, x, y,
                                                            ctx)))
             goto err;
-        BIO_printf(bio_err, "Point is not on curve: x = 0x");
-        BN_print_fp(stderr, x);
-        BIO_printf(bio_err, ", y = 0x");
-        BN_print_fp(stderr, y);
-        BIO_printf(bio_err, "\n");
+        TEST_info("Point is not on curve");
+        test_output_bignum("x", x);
+        test_output_bignum("y", y);
         goto err;
     }
 
-    BIO_printf(bio_out, "A cyclic subgroup:\n");
+    TEST_note("A cyclic subgroup:");
     k = 100;
     do {
         if (!TEST_int_ne(k--, 0))
             goto err;
 
         if (EC_POINT_is_at_infinity(group, P)) {
-            BIO_printf(bio_out, "     point at infinity\n");
+            TEST_note("     point at infinity");
         } else {
             if (!TEST_true(EC_POINT_get_affine_coordinates_GFp(group, P, x, y,
                                                                ctx)))
                 goto err;
 
-            BIO_printf(bio_out, "     x = 0x");
-            BN_print(bio_out, x);
-            BIO_printf(bio_out, ", y = 0x");
-            BN_print(bio_out, y);
-            BIO_printf(bio_out, "\n");
+            test_output_bignum("x", x);
+            test_output_bignum("y", y);
         }
 
         if (!TEST_true(EC_POINT_copy(R, P))
@@ -259,49 +232,40 @@ static int prime_field_tests(void)
 
     len =
         EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf,
-                           sizeof buf, ctx);
+                           sizeof(buf), ctx);
     if (!TEST_size_t_ne(len, 0)
         || !TEST_true(EC_POINT_oct2point(group, P, buf, len, ctx))
         || !TEST_int_eq(0, EC_POINT_cmp(group, P, Q, ctx)))
         goto err;
-    BIO_printf(bio_out, "Generator as octet string, compressed form:\n     ");
-    for (i = 0; i < len; i++)
-        BIO_printf(bio_out, "%02X", buf[i]);
+    test_output_memory("Generator as octet string, compressed form:",
+                       buf, len);
 
     len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED,
-                             buf, sizeof buf, ctx);
+                             buf, sizeof(buf), ctx);
     if (!TEST_size_t_ne(len, 0)
         || !TEST_true(EC_POINT_oct2point(group, P, buf, len, ctx))
         || !TEST_int_eq(0, EC_POINT_cmp(group, P, Q, ctx)))
         goto err;
-    BIO_printf(bio_out, "\nGenerator as octet string, uncompressed form:\n"
-                        "     ");
-    for (i = 0; i < len; i++)
-        BIO_printf(bio_out, "%02X", buf[i]);
+    test_output_memory("Generator as octet string, uncompressed form:",
+                       buf, len);
 
     len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID,
-                             buf, sizeof buf, ctx);
+                             buf, sizeof(buf), ctx);
     if (!TEST_size_t_ne(len, 0)
         || !TEST_true(EC_POINT_oct2point(group, P, buf, len, ctx))
         || !TEST_int_eq(0, EC_POINT_cmp(group, P, Q, ctx)))
         goto err;
-    BIO_printf(bio_out, "\nGenerator as octet string, hybrid form:\n     ");
-    for (i = 0; i < len; i++)
-        BIO_printf(bio_out, "%02X", buf[i]);
+    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;
-    BIO_printf(bio_out,
-               "\nA representation of the inverse of that generator in\n"
-               "Jacobian projective coordinates:\n"
-               "     X = 0x");
-    BN_print(bio_out, x);
-    BIO_printf(bio_out, ", Y = 0x");
-    BN_print(bio_out, y);
-    BIO_printf(bio_out, ", Z = 0x");
-    BN_print(bio_out, z);
-    BIO_printf(bio_out, "\n");
+    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))
@@ -337,11 +301,9 @@ static int prime_field_tests(void)
         || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
         || !TEST_true(EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)))
         goto err;
-    BIO_printf(bio_out, "\nSEC2 curve secp160r1 -- Generator:\n     x = 0x");
-    BN_print(bio_out, x);
-    BIO_printf(bio_out, "\n     y = 0x");
-    BN_print(bio_out, y);
-    BIO_printf(bio_out, "\n");
+    TEST_info("SEC2 curve secp160r1 -- Generator");
+    test_output_bignum("x", x);
+    test_output_bignum("y", y);
     /* G_y value taken from the standard: */
     if (!TEST_true(BN_hex2bn(&z,                         "23a62855"
                                  "3168947d59dcc912042351377ac5fb32"))
@@ -372,11 +334,9 @@ static int prime_field_tests(void)
         || !TEST_true(EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)))
         goto err;
 
-    BIO_printf(bio_out, "\nNIST curve P-192 -- Generator:\n     x = 0x");
-    BN_print(bio_out, x);
-    BIO_printf(bio_out, "\n     y = 0x");
-    BN_print(bio_out, y);
-    BIO_printf(bio_out, "\n");
+    TEST_info("NIST curve P-192 -- Generator");
+    test_output_bignum("x", x);
+    test_output_bignum("y", y);
     /* G_y value taken from the standard: */
     if (!TEST_true(BN_hex2bn(&z,                 "07192B95FFC8DA78"
                                  "631011ED6B24CDD573F977A11E794811"))
@@ -414,11 +374,9 @@ static int prime_field_tests(void)
         || !TEST_true(EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)))
         goto err;
 
-    BIO_printf(bio_out, "\nNIST curve P-224 -- Generator:\n     x = 0x");
-    BN_print(bio_out, x);
-    BIO_printf(bio_out, "\n     y = 0x");
-    BN_print(bio_out, y);
-    BIO_printf(bio_out, "\n");
+    TEST_info("NIST curve P-224 -- Generator");
+    test_output_bignum("x", x);
+    test_output_bignum("y", y);
     /* G_y value taken from the standard: */
     if (!TEST_true(BN_hex2bn(&z,         "BD376388B5F723FB4C22DFE6"
                                  "CD4375A05A07476444D5819985007E34"))
@@ -457,11 +415,9 @@ static int prime_field_tests(void)
         || !TEST_true(EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)))
         goto err;
 
-    BIO_printf(bio_out, "\nNIST curve P-256 -- Generator:\n     x = 0x");
-    BN_print(bio_out, x);
-    BIO_printf(bio_out, "\n     y = 0x");
-    BN_print(bio_out, y);
-    BIO_printf(bio_out, "\n");
+    TEST_info("NIST curve P-256 -- Generator");
+    test_output_bignum("x", x);
+    test_output_bignum("y", y);
     /* G_y value taken from the standard: */
     if (!TEST_true(BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E16"
                                  "2BCE33576B315ECECBB6406837BF51F5"))
@@ -505,11 +461,9 @@ static int prime_field_tests(void)
         || !TEST_true(EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)))
         goto err;
 
-    BIO_printf(bio_out, "\nNIST curve P-384 -- Generator:\n     x = 0x");
-    BN_print(bio_out, x);
-    BIO_printf(bio_out, "\n     y = 0x");
-    BN_print(bio_out, y);
-    BIO_printf(bio_out, "\n");
+    TEST_info("NIST curve P-384 -- Generator");
+    test_output_bignum("x", x);
+    test_output_bignum("y", y);
     /* G_y value taken from the standard: */
     if (!TEST_true(BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29"
                                  "F8F41DBD289A147CE9DA3113B5F0B8C0"
@@ -562,11 +516,9 @@ static int prime_field_tests(void)
         || !TEST_true(EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)))
         goto err;
 
-    BIO_printf(bio_out, "\nNIST curve P-521 -- Generator:\n     x = 0x");
-    BN_print(bio_out, x);
-    BIO_printf(bio_out, "\n     y = 0x");
-    BN_print(bio_out, y);
-    BIO_printf(bio_out, "\n");
+    TEST_info("NIST curve P-521 -- Generator");
+    test_output_bignum("x", x);
+    test_output_bignum("y", y);
     /* G_y value taken from the standard: */
     if (!TEST_true(BN_hex2bn(&z,                              "118"
                                  "39296A789A3BC0045C8A5FB42C7D1BD9"
@@ -613,14 +565,14 @@ static int prime_field_tests(void)
     scalars[0] = y;         /* (group order + 1)/2, so y*Q + y*Q = Q */
     scalars[1] = y;
 
-    BIO_printf(bio_out, "combined multiplication ...");
+    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))
         || !TEST_int_eq(0, EC_POINT_cmp(group, P, R, ctx))
         || !TEST_int_eq(0, EC_POINT_cmp(group, R, Q, ctx))
-        || !TEST_true(BN_pseudo_rand(y, BN_num_bits(y), 0, 0))
+        || !TEST_true(BN_rand(y, BN_num_bits(y), 0, 0))
         || !TEST_true(BN_add(z, z, y)))
         goto err;
     BN_set_negative(z, 1);
@@ -629,7 +581,7 @@ static int prime_field_tests(void)
 
     if (!TEST_true(EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))
         || !TEST_true(EC_POINT_is_at_infinity(group, P))
-        || !TEST_true(BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0))
+        || !TEST_true(BN_rand(x, BN_num_bits(y) - 1, 0, 0))
         || !TEST_true(BN_add(z, x, y)))
         goto err;
     BN_set_negative(z, 1);
@@ -646,7 +598,7 @@ static int prime_field_tests(void)
         || !TEST_true(EC_POINT_is_at_infinity(group, P)))
         goto err;
 
-    BIO_printf(bio_out, " ok\n\n");
+    TEST_note(" ok\n");
 
 
     r = 1;
@@ -898,11 +850,9 @@ static int char2_curve_test(int n)
         || !TEST_true(EC_POINT_get_affine_coordinates_GF2m(group, P, x, y,
                                                            ctx)))
         goto err;
-    BIO_printf(bio_out, "\n%s -- Generator:\n     x = 0x", test->name);
-    BN_print(bio_out, x);
-    BIO_printf(bio_out, "\n     y = 0x");
-    BN_print(bio_out, y);
-    BIO_printf(bio_out, "\n");
+    TEST_info("%s -- Generator", test->name);
+    test_output_bignum("x", x);
+    test_output_bignum("y", y);
     /* G_y value taken from the standard: */
     if (!TEST_true(BN_hex2bn(&z, test->y))
         || !TEST_BN_eq(y, z))
@@ -920,11 +870,9 @@ static int char2_curve_test(int n)
         || !TEST_true(BN_hex2bn(&cof, test->cof))
         || !TEST_true(EC_GROUP_set_generator(group, P, z, cof)))
         goto err;
-    BIO_printf(bio_out, "\n%s -- Generator:\n     x = 0x", test->name); \
-    BN_print(bio_out, x); \
-    BIO_printf(bio_out, "\n     y = 0x"); \
-    BN_print(bio_out, y); \
-    BIO_printf(bio_out, "\n");
+    TEST_info("%s -- Generator:", test->name);
+    test_output_bignum("x", x);
+    test_output_bignum("y", y);
 # endif
 
     if (!TEST_int_eq(EC_GROUP_get_degree(group), test->degree)
@@ -959,7 +907,7 @@ static int char2_curve_test(int n)
         scalars[0] = y;         /* (group order + 1)/2, so y*Q + y*Q = Q */
         scalars[1] = y;
 
-        BIO_printf(bio_out, "combined multiplication ...");
+        TEST_note("combined multiplication ...");
 
         /* z is still the group order */
         if (!TEST_true(EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))
@@ -968,7 +916,7 @@ static int char2_curve_test(int n)
             || !TEST_int_eq(0, EC_POINT_cmp(group, R, Q, ctx)))
             goto err;
 
-        if (!TEST_true(BN_pseudo_rand(y, BN_num_bits(y), 0, 0))
+        if (!TEST_true(BN_rand(y, BN_num_bits(y), 0, 0))
             || !TEST_true(BN_add(z, z, y)))
             goto err;
         BN_set_negative(z, 1);
@@ -979,7 +927,7 @@ static int char2_curve_test(int n)
             || !TEST_true(EC_POINT_is_at_infinity(group, P)))
             goto err;
 
-        if (!TEST_true(BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0))
+        if (!TEST_true(BN_rand(x, BN_num_bits(y) - 1, 0, 0))
             || !TEST_true(BN_add(z, x, y)))
             goto err;
         BN_set_negative(z, 1);
@@ -1019,7 +967,7 @@ static int char2_field_tests(void)
     EC_POINT *P = NULL, *Q = NULL, *R = NULL;
     BIGNUM *x = NULL, *y = NULL, *z = NULL, *cof = NULL, *yplusone = NULL;
     unsigned char buf[100];
-    size_t i, len;
+    size_t len;
     int k, r = 0;
 
     if (!TEST_ptr(ctx = BN_CTX_new())
@@ -1047,15 +995,11 @@ static int char2_field_tests(void)
     if (!TEST_true(EC_GROUP_get_curve_GF2m(group, p, a, b, ctx)))
         goto err;
 
-    BIO_printf(bio_out,
-            "Curve defined by Weierstrass equation\n"
-            "     y^2 + x*y = x^3 + a*x^2 + b  (mod 0x");
-    BN_print(bio_out, p);
-    BIO_printf(bio_out, ")\n     a = 0x");
-    BN_print(bio_out, a);
-    BIO_printf(bio_out, "\n     b = 0x");
-    BN_print(bio_out, b);
-    BIO_printf(bio_out, "\n(0x... means binary polynomial)\n");
+    TEST_info("Curve defined by Weierstrass equation");
+    TEST_note("     y^2 + x*y = x^3 + a*x^2 + b (mod p)");
+    test_output_bignum("a", a);
+    test_output_bignum("b", b);
+    test_output_bignum("p", p);
 
      if (!TEST_ptr(P = EC_POINT_new(group))
         || !TEST_ptr(Q = EC_POINT_new(group))
@@ -1091,32 +1035,27 @@ static int char2_field_tests(void)
                                                             ctx)))
             goto err;
 #  endif
-        BIO_printf(bio_err, "Point is not on curve: x = 0x");
-        BN_print_fp(stderr, x);
-        BIO_printf(bio_err, ", y = 0x");
-        BN_print_fp(stderr, y);
-        BIO_printf(bio_err, "\n");
+        TEST_info("Point is not on curve");
+        test_output_bignum("x", x);
+        test_output_bignum("y", y);
         goto err;
     }
 
-    BIO_printf(bio_out, "A cyclic subgroup:\n");
+    TEST_note("A cyclic subgroup:");
     k = 100;
     do {
         if (!TEST_int_ne(k--, 0))
             goto err;
 
         if (EC_POINT_is_at_infinity(group, P))
-            BIO_printf(bio_out, "     point at infinity\n");
+            TEST_note("     point at infinity");
         else {
             if (!TEST_true(EC_POINT_get_affine_coordinates_GF2m(group, P, x, y,
                                                                 ctx)))
                 goto err;
 
-            BIO_printf(bio_out, "     x = 0x");
-            BN_print(bio_out, x);
-            BIO_printf(bio_out, ", y = 0x");
-            BN_print(bio_out, y);
-            BIO_printf(bio_out, "\n");
+            test_output_bignum("x", x);
+            test_output_bignum("y", y);
         }
 
         if (!TEST_true(EC_POINT_copy(R, P))
@@ -1132,50 +1071,42 @@ static int char2_field_tests(void)
 /* Change test based on whether binary point compression is enabled or not. */
 #  ifdef OPENSSL_EC_BIN_PT_COMP
     len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED,
-                             buf, sizeof buf, ctx);
+                             buf, sizeof(buf), ctx);
     if (!TEST_size_t_ne(len, 0)
         || !TEST_true(EC_POINT_oct2point(group, P, buf, len, ctx))
         || !TEST_int_eq(0, EC_POINT_cmp(group, P, Q, ctx)))
         goto err;
-    BIO_printf(bio_out, "Generator as octet string, compressed form:\n     ");
-    for (i = 0; i < len; i++)
-        BIO_printf(bio_out, "%02X", buf[i]);
+    test_output_memory("Generator as octet string, compressed form:",
+                       buf, len);
 #  endif
 
     len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED,
-                             buf, sizeof buf, ctx);
+                             buf, sizeof(buf), ctx);
     if (!TEST_size_t_ne(len, 0)
         || !TEST_true(EC_POINT_oct2point(group, P, buf, len, ctx))
         || !TEST_int_eq(0, EC_POINT_cmp(group, P, Q, ctx)))
         goto err;
-    BIO_printf(bio_out, "\nGenerator as octet string, uncompressed form:\n"
-                        "     ");
-    for (i = 0; i < len; i++)
-        BIO_printf(bio_out, "%02X", buf[i]);
+    test_output_memory("Generator as octet string, uncompressed form:",
+                       buf, len);
 
 /* Change test based on whether binary point compression is enabled or not. */
 #  ifdef OPENSSL_EC_BIN_PT_COMP
     len =
-        EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf,
+        EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof(buf),
                            ctx);
     if (!TEST_size_t_ne(len, 0)
         || !TEST_true(EC_POINT_oct2point(group, P, buf, len, ctx))
         || !TEST_int_eq(0, EC_POINT_cmp(group, P, Q, ctx)))
         goto err;
-    BIO_printf(bio_out, "\nGenerator as octet string, hybrid form:\n     ");
-    for (i = 0; i < len; i++)
-        BIO_printf(bio_out, "%02X", buf[i]);
+    test_output_memory("Generator as octet string, hybrid form:",
+                       buf, len);
 #  endif
-    BIO_printf(bio_out, "\n");
 
     if (!TEST_true(EC_POINT_invert(group, P, ctx))
         || !TEST_int_eq(0, EC_POINT_cmp(group, P, R, ctx)))
         goto err;
 
-
-#if 0
-#endif
-    BIO_printf(bio_out, "\n\n");
+    TEST_note("\n");
 
     r = 1;
 err:
@@ -1221,12 +1152,6 @@ static int internal_curve_test_method(int n)
     int r, nid = curves[n].nid;
     EC_GROUP *group;
 
-    /*
-     * Skip for X25519 because low level operations such as EC_POINT_mul()
-     * are not supported for this curve
-     */
-    if (nid == NID_X25519)
-        return 1;
     if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))) {
         TEST_info("Curve %s failed\n", OBJ_nid2sn(nid));
         return 0;
@@ -1352,8 +1277,8 @@ static int nistp_single_test(int idx)
     EC_POINT *G = NULL, *P = NULL, *Q = NULL, *Q_CHECK = NULL;
     int r = 0;
 
-    BIO_printf(bio_out, "\nNIST curve P-%d (optimised implementation):\n",
-            test->degree);
+    TEST_note("NIST curve P-%d (optimised implementation):",
+              test->degree);
     if (!TEST_ptr(ctx = BN_CTX_new())
         || !TEST_ptr(p = BN_new())
         || !TEST_ptr(a = BN_new())
@@ -1394,7 +1319,7 @@ static int nistp_single_test(int idx)
         || !TEST_int_eq(EC_GROUP_get_degree(NISTP), test->degree))
         goto err;
 
-    BIO_printf(bio_out, "NIST test vectors ... ");
+    TEST_note("NIST test vectors ... ");
     if (!TEST_true(BN_hex2bn(&n, test->d)))
         goto err;
     /* fixed point multiplication */
@@ -1452,6 +1377,15 @@ static int nistp_single_test(int idx)
     if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
         goto err;
 
+    /* regression test for felem_neg bug */
+    if (!TEST_true(BN_set_word(m, 32))
+        || !TEST_true(BN_set_word(n, 31))
+        || !TEST_true(EC_POINT_copy(P, G))
+        || !TEST_true(EC_POINT_invert(NISTP, P, ctx))
+        || !TEST_true(EC_POINT_mul(NISTP, Q, m, P, n, ctx))
+        || !TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, G, ctx)))
+      goto err;
+
     r = group_order_tests(NISTP);
 err:
     EC_GROUP_free(NISTP);
@@ -1473,38 +1407,102 @@ err:
 }
 # endif
 
+static const unsigned char p521_named[] = {
+    0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23,
+};
+
+static const unsigned char p521_explicit[] = {
+    0x30, 0x82, 0x01, 0xc3, 0x02, 0x01, 0x01, 0x30, 0x4d, 0x06, 0x07, 0x2a,
+    0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x42, 0x01, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0x30, 0x81, 0x9f, 0x04, 0x42, 0x01, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xfc, 0x04, 0x42, 0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, 0x9a,
+    0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85, 0x40, 0xee, 0xa2, 0xda, 0x72,
+    0x5b, 0x99, 0xb3, 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1, 0x09,
+    0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e, 0x93, 0x7b, 0x16, 0x52, 0xc0,
+    0xbd, 0x3b, 0xb1, 0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, 0x34,
+    0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50, 0x3f, 0x00, 0x03, 0x15, 0x00,
+    0xd0, 0x9e, 0x88, 0x00, 0x29, 0x1c, 0xb8, 0x53, 0x96, 0xcc, 0x67, 0x17,
+    0x39, 0x32, 0x84, 0xaa, 0xa0, 0xda, 0x64, 0xba, 0x04, 0x81, 0x85, 0x04,
+    0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd, 0x9e, 0x3e,
+    0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f,
+    0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba, 0xa1, 0x4b,
+    0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff,
+    0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, 0xf9, 0x7e,
+    0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66, 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78,
+    0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9,
+    0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17,
+    0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40,
+    0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86,
+    0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,
+    0x02, 0x42, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa,
+    0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, 0x7f, 0xcc, 0x01, 0x48,
+    0xf7, 0x09, 0xa5, 0xd0, 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae,
+    0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09, 0x02, 0x01, 0x01,
+};
+
 static int parameter_test(void)
 {
     EC_GROUP *group = NULL, *group2 = NULL;
     ECPARAMETERS *ecparameters = NULL;
-    int r;
+    unsigned char *buf = NULL;
+    int r = 0, len;
+
+    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_secp112r1))
+        || !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))
+        goto err;
 
-    r = TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_secp112r1))
-        && 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);
+    EC_GROUP_free(group);
+    group = NULL;
+
+    /* Test the named curve encoding, which should be default. */
+    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_secp521r1))
+        || !TEST_true((len = i2d_ECPKParameters(group, &buf)) >= 0)
+        || !TEST_mem_eq(buf, len, p521_named, sizeof(p521_named)))
+        goto err;
+
+    OPENSSL_free(buf);
+    buf = NULL;
+
+    /*
+     * Test the explicit encoding. P-521 requires correctly zero-padding the
+     * curve coefficients.
+     */
+    EC_GROUP_set_asn1_flag(group, OPENSSL_EC_EXPLICIT_CURVE);
+    if (!TEST_true((len = i2d_ECPKParameters(group, &buf)) >= 0)
+        || !TEST_mem_eq(buf, len, p521_explicit, sizeof(p521_explicit)))
+        goto err;
 
+    r = 1;
+err:
     EC_GROUP_free(group);
     EC_GROUP_free(group2);
     ECPARAMETERS_free(ecparameters);
+    OPENSSL_free(buf);
     return r;
 }
-
-static const char rnd_seed[] =
-    "string to make the random number generator think it has entropy";
 #endif
 
-int test_main(int argc, char *argv[])
+int setup_tests(void)
 {
-    int result = EXIT_SUCCESS;
 #ifndef OPENSSL_NO_EC
-
     crv_len = EC_get_builtin_curves(NULL, 0);
     if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len))
         || !TEST_true(EC_get_builtin_curves(curves, crv_len)))
-        return EXIT_FAILURE;
-
-    RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_generate_prime may fail */
+        return 0;
 
     ADD_TEST(parameter_test);
     ADD_TEST(prime_field_tests);
@@ -1517,9 +1515,13 @@ int test_main(int argc, char *argv[])
 # endif
     ADD_ALL_TESTS(internal_curve_test, crv_len);
     ADD_ALL_TESTS(internal_curve_test_method, crv_len);
+#endif
+    return 1;
+}
 
-    result = run_tests(argv[0]);
+void cleanup_tests(void)
+{
+#ifndef OPENSSL_NO_EC
     OPENSSL_free(curves);
 #endif
-    return result;
 }