Blame SOURCES/ectest.c

2871ff
/*
2871ff
 * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
2871ff
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
2871ff
 *
2871ff
 * Licensed under the Apache License 2.0 (the "License").  You may not use
2871ff
 * this file except in compliance with the License.  You can obtain a copy
2871ff
 * in the file LICENSE in the source distribution or at
2871ff
 * https://www.openssl.org/source/license.html
2871ff
 */
2871ff
2871ff
/*
2871ff
 * EC_KEY low level APIs are deprecated for public use, but still ok for
2871ff
 * internal use.
2871ff
 */
2871ff
#include "internal/deprecated.h"
2871ff
2871ff
#include <string.h>
2871ff
#include "internal/nelem.h"
2871ff
#include "testutil.h"
2871ff
2871ff
#include <openssl/ec.h>
2871ff
#ifndef OPENSSL_NO_ENGINE
2871ff
# include <openssl/engine.h>
2871ff
#endif
2871ff
#include <openssl/err.h>
2871ff
#include <openssl/obj_mac.h>
2871ff
#include <openssl/objects.h>
2871ff
#include <openssl/rand.h>
2871ff
#include <openssl/bn.h>
2871ff
#include <openssl/opensslconf.h>
2871ff
#include <openssl/core_names.h>
2871ff
#include <openssl/param_build.h>
2871ff
#include <openssl/evp.h>
2871ff
2871ff
static size_t crv_len = 0;
2871ff
static EC_builtin_curve *curves = NULL;
2871ff
2871ff
/* test multiplication with group order, long and negative scalars */
2871ff
static int group_order_tests(EC_GROUP *group)
2871ff
{
2871ff
    BIGNUM *n1 = NULL, *n2 = NULL, *order = NULL;
2871ff
    EC_POINT *P = NULL, *Q = NULL, *R = NULL, *S = NULL;
2871ff
    const EC_POINT *G = NULL;
2871ff
    BN_CTX *ctx = NULL;
2871ff
    int i = 0, r = 0;
2871ff
2871ff
    if (!TEST_ptr(n1 = BN_new())
2871ff
        || !TEST_ptr(n2 = BN_new())
2871ff
        || !TEST_ptr(order = BN_new())
2871ff
        || !TEST_ptr(ctx = BN_CTX_new())
2871ff
        || !TEST_ptr(G = EC_GROUP_get0_generator(group))
2871ff
        || !TEST_ptr(P = EC_POINT_new(group))
2871ff
        || !TEST_ptr(Q = EC_POINT_new(group))
2871ff
        || !TEST_ptr(R = EC_POINT_new(group))
2871ff
        || !TEST_ptr(S = EC_POINT_new(group)))
2871ff
        goto err;
2871ff
2871ff
    if (!TEST_true(EC_GROUP_get_order(group, order, ctx))
2871ff
        || !TEST_true(EC_POINT_mul(group, Q, order, NULL, NULL, ctx))
2871ff
        || !TEST_true(EC_POINT_is_at_infinity(group, Q))
2871ff
#ifndef OPENSSL_NO_DEPRECATED_3_0
2871ff
        || !TEST_true(EC_GROUP_precompute_mult(group, ctx))
2871ff
#endif
2871ff
        || !TEST_true(EC_POINT_mul(group, Q, order, NULL, NULL, ctx))
2871ff
        || !TEST_true(EC_POINT_is_at_infinity(group, Q))
2871ff
        || !TEST_true(EC_POINT_copy(P, G))
2871ff
        || !TEST_true(BN_one(n1))
2871ff
        || !TEST_true(EC_POINT_mul(group, Q, n1, NULL, NULL, ctx))
2871ff
        || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx))
2871ff
        || !TEST_true(BN_sub(n1, order, n1))
2871ff
        || !TEST_true(EC_POINT_mul(group, Q, n1, NULL, NULL, ctx))
2871ff
        || !TEST_true(EC_POINT_invert(group, Q, ctx))
2871ff
        || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx)))
2871ff
        goto err;
2871ff
2871ff
    for (i = 1; i <= 2; i++) {
2871ff
#ifndef OPENSSL_NO_DEPRECATED_3_0
2871ff
        const BIGNUM *scalars[6];
2871ff
        const EC_POINT *points[6];
2871ff
#endif
2871ff
2871ff
        if (!TEST_true(BN_set_word(n1, i))
2871ff
            /*
2871ff
             * If i == 1, P will be the predefined generator for which
2871ff
             * EC_GROUP_precompute_mult has set up precomputation.
2871ff
             */
2871ff
            || !TEST_true(EC_POINT_mul(group, P, n1, NULL, NULL, ctx))
2871ff
            || (i == 1 && !TEST_int_eq(0, EC_POINT_cmp(group, P, G, ctx)))
2871ff
            || !TEST_true(BN_one(n1))
2871ff
            /* n1 = 1 - order */
2871ff
            || !TEST_true(BN_sub(n1, n1, order))
2871ff
            || !TEST_true(EC_POINT_mul(group, Q, NULL, P, n1, ctx))
2871ff
            || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx))
2871ff
2871ff
            /* n2 = 1 + order */
2871ff
            || !TEST_true(BN_add(n2, order, BN_value_one()))
2871ff
            || !TEST_true(EC_POINT_mul(group, Q, NULL, P, n2, ctx))
2871ff
            || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx))
2871ff
2871ff
            /* n2 = (1 - order) * (1 + order) = 1 - order^2 */
2871ff
            || !TEST_true(BN_mul(n2, n1, n2, ctx))
2871ff
            || !TEST_true(EC_POINT_mul(group, Q, NULL, P, n2, ctx))
2871ff
            || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx)))
2871ff
            goto err;
2871ff
2871ff
        /* n2 = order^2 - 1 */
2871ff
        BN_set_negative(n2, 0);
2871ff
        if (!TEST_true(EC_POINT_mul(group, Q, NULL, P, n2, ctx))
2871ff
            /* Add P to verify the result. */
2871ff
            || !TEST_true(EC_POINT_add(group, Q, Q, P, ctx))
2871ff
            || !TEST_true(EC_POINT_is_at_infinity(group, Q))
2871ff
            || !TEST_false(EC_POINT_is_at_infinity(group, P)))
2871ff
            goto err;
2871ff
2871ff
#ifndef OPENSSL_NO_DEPRECATED_3_0
2871ff
        /* Exercise EC_POINTs_mul, including corner cases. */
2871ff
        scalars[0] = scalars[1] = BN_value_one();
2871ff
        points[0]  = points[1]  = P;
2871ff
2871ff
        if (!TEST_true(EC_POINTs_mul(group, R, NULL, 2, points, scalars, ctx))
2871ff
            || !TEST_true(EC_POINT_dbl(group, S, points[0], ctx))
2871ff
            || !TEST_int_eq(0, EC_POINT_cmp(group, R, S, ctx)))
2871ff
            goto err;
2871ff
2871ff
        scalars[0] = n1;
2871ff
        points[0] = Q;          /* => infinity */
2871ff
        scalars[1] = n2;
2871ff
        points[1] = P;          /* => -P */
2871ff
        scalars[2] = n1;
2871ff
        points[2] = Q;          /* => infinity */
2871ff
        scalars[3] = n2;
2871ff
        points[3] = Q;          /* => infinity */
2871ff
        scalars[4] = n1;
2871ff
        points[4] = P;          /* => P */
2871ff
        scalars[5] = n2;
2871ff
        points[5] = Q;          /* => infinity */
2871ff
        if (!TEST_true(EC_POINTs_mul(group, P, NULL, 6, points, scalars, ctx))
2871ff
            || !TEST_true(EC_POINT_is_at_infinity(group, P)))
2871ff
            goto err;
2871ff
#endif
2871ff
    }
2871ff
2871ff
    r = 1;
2871ff
err:
2871ff
    if (r == 0 && i != 0)
2871ff
        TEST_info(i == 1 ? "allowing precomputation" :
2871ff
                           "without precomputation");
2871ff
    EC_POINT_free(P);
2871ff
    EC_POINT_free(Q);
2871ff
    EC_POINT_free(R);
2871ff
    EC_POINT_free(S);
2871ff
    BN_free(n1);
2871ff
    BN_free(n2);
2871ff
    BN_free(order);
2871ff
    BN_CTX_free(ctx);
2871ff
    return r;
2871ff
}
2871ff
2871ff
static int prime_field_tests(void)
2871ff
{
2871ff
    BN_CTX *ctx = NULL;
2871ff
    BIGNUM *p = NULL, *a = NULL, *b = NULL, *scalar3 = NULL;
2871ff
    EC_GROUP *group = NULL;
2871ff
    EC_POINT *P = NULL, *Q = NULL, *R = NULL;
2871ff
    BIGNUM *x = NULL, *y = NULL, *z = NULL, *yplusone = NULL;
2871ff
#ifndef OPENSSL_NO_DEPRECATED_3_0
2871ff
    const EC_POINT *points[4];
2871ff
    const BIGNUM *scalars[4];
2871ff
#endif
2871ff
    unsigned char buf[100];
2871ff
    size_t len, r = 0;
2871ff
    int k;
2871ff
2871ff
    if (!TEST_ptr(ctx = BN_CTX_new())
2871ff
        || !TEST_ptr(p = BN_new())
2871ff
        || !TEST_ptr(a = BN_new())
2871ff
        || !TEST_ptr(b = BN_new())
2871ff
        /*
2871ff
         * applications should use EC_GROUP_new_curve_GFp so
2871ff
         * that the library gets to choose the EC_METHOD
2871ff
         */
2871ff
        || !TEST_ptr(group = EC_GROUP_new(EC_GFp_mont_method())))
2871ff
        goto err;
2871ff
2871ff
    buf[0] = 0;
2871ff
    if (!TEST_ptr(P = EC_POINT_new(group))
2871ff
        || !TEST_ptr(Q = EC_POINT_new(group))
2871ff
        || !TEST_ptr(R = EC_POINT_new(group))
2871ff
        || !TEST_ptr(x = BN_new())
2871ff
        || !TEST_ptr(y = BN_new())
2871ff
        || !TEST_ptr(z = BN_new())
2871ff
        || !TEST_ptr(yplusone = BN_new()))
2871ff
        goto err;
2871ff
2871ff
    /* Curve P-224 (FIPS PUB 186-2, App. 6) */
2871ff
2871ff
    if (!TEST_true(BN_hex2bn(&p,         "FFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                                    "FFFFFFFF000000000000000000000001"))
2871ff
        || !TEST_int_eq(1, BN_check_prime(p, ctx, NULL))
2871ff
        || !TEST_true(BN_hex2bn(&a,         "FFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                                    "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE"))
2871ff
        || !TEST_true(BN_hex2bn(&b,         "B4050A850C04B3ABF5413256"
2871ff
                                    "5044B0B7D7BFD8BA270B39432355FFB4"))
2871ff
        || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
2871ff
        || !TEST_true(BN_hex2bn(&x,         "B70E0CBD6BB4BF7F321390B9"
2871ff
                                    "4A03C1D356C21122343280D6115C1D21"))
2871ff
        || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, 0, ctx))
2871ff
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
2871ff
        || !TEST_true(BN_hex2bn(&z,         "FFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                                    "FFFF16A2E0B8F03E13DD29455C5C2A3D"))
2871ff
        || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
2871ff
        || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx)))
2871ff
        goto err;
2871ff
2871ff
    TEST_info("NIST curve P-224 -- Generator");
2871ff
    test_output_bignum("x", x);
2871ff
    test_output_bignum("y", y);
2871ff
    /* G_y value taken from the standard: */
2871ff
    if (!TEST_true(BN_hex2bn(&z,         "BD376388B5F723FB4C22DFE6"
2871ff
                                 "CD4375A05A07476444D5819985007E34"))
2871ff
        || !TEST_BN_eq(y, z)
2871ff
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
2871ff
    /*
2871ff
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
2871ff
     * and therefore setting the coordinates should fail.
2871ff
     */
2871ff
        || !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
2871ff
                                                       ctx))
2871ff
        || !TEST_int_eq(EC_GROUP_get_degree(group), 224)
2871ff
        || !group_order_tests(group)
2871ff
2871ff
    /* Curve P-256 (FIPS PUB 186-2, App. 6) */
2871ff
2871ff
        || !TEST_true(BN_hex2bn(&p, "FFFFFFFF000000010000000000000000"
2871ff
                                    "00000000FFFFFFFFFFFFFFFFFFFFFFFF"))
2871ff
        || !TEST_int_eq(1, BN_check_prime(p, ctx, NULL))
2871ff
        || !TEST_true(BN_hex2bn(&a, "FFFFFFFF000000010000000000000000"
2871ff
                                    "00000000FFFFFFFFFFFFFFFFFFFFFFFC"))
2871ff
        || !TEST_true(BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC"
2871ff
                                    "651D06B0CC53B0F63BCE3C3E27D2604B"))
2871ff
        || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
2871ff
2871ff
        || !TEST_true(BN_hex2bn(&x, "6B17D1F2E12C4247F8BCE6E563A440F2"
2871ff
                                    "77037D812DEB33A0F4A13945D898C296"))
2871ff
        || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, 1, ctx))
2871ff
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
2871ff
        || !TEST_true(BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFF"
2871ff
                                    "BCE6FAADA7179E84F3B9CAC2FC632551"))
2871ff
        || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
2871ff
        || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx)))
2871ff
        goto err;
2871ff
2871ff
    TEST_info("NIST curve P-256 -- Generator");
2871ff
    test_output_bignum("x", x);
2871ff
    test_output_bignum("y", y);
2871ff
    /* G_y value taken from the standard: */
2871ff
    if (!TEST_true(BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E16"
2871ff
                                 "2BCE33576B315ECECBB6406837BF51F5"))
2871ff
        || !TEST_BN_eq(y, z)
2871ff
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
2871ff
    /*
2871ff
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
2871ff
     * and therefore setting the coordinates should fail.
2871ff
     */
2871ff
        || !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
2871ff
                                                       ctx))
2871ff
        || !TEST_int_eq(EC_GROUP_get_degree(group), 256)
2871ff
        || !group_order_tests(group)
2871ff
2871ff
    /* Curve P-384 (FIPS PUB 186-2, App. 6) */
2871ff
2871ff
        || !TEST_true(BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
2871ff
                                    "FFFFFFFF0000000000000000FFFFFFFF"))
2871ff
        || !TEST_int_eq(1, BN_check_prime(p, ctx, NULL))
2871ff
        || !TEST_true(BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
2871ff
                                    "FFFFFFFF0000000000000000FFFFFFFC"))
2871ff
        || !TEST_true(BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19"
2871ff
                                    "181D9C6EFE8141120314088F5013875A"
2871ff
                                    "C656398D8A2ED19D2A85C8EDD3EC2AEF"))
2871ff
        || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
2871ff
2871ff
        || !TEST_true(BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD74"
2871ff
                                    "6E1D3B628BA79B9859F741E082542A38"
2871ff
                                    "5502F25DBF55296C3A545E3872760AB7"))
2871ff
        || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, 1, ctx))
2871ff
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
2871ff
        || !TEST_true(BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                                    "FFFFFFFFFFFFFFFFC7634D81F4372DDF"
2871ff
                                    "581A0DB248B0A77AECEC196ACCC52973"))
2871ff
        || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
2871ff
        || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx)))
2871ff
        goto err;
2871ff
2871ff
    TEST_info("NIST curve P-384 -- Generator");
2871ff
    test_output_bignum("x", x);
2871ff
    test_output_bignum("y", y);
2871ff
    /* G_y value taken from the standard: */
2871ff
    if (!TEST_true(BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29"
2871ff
                                 "F8F41DBD289A147CE9DA3113B5F0B8C0"
2871ff
                                 "0A60B1CE1D7E819D7A431D7C90EA0E5F"))
2871ff
        || !TEST_BN_eq(y, z)
2871ff
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
2871ff
    /*
2871ff
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
2871ff
     * and therefore setting the coordinates should fail.
2871ff
     */
2871ff
        || !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
2871ff
                                                       ctx))
2871ff
        || !TEST_int_eq(EC_GROUP_get_degree(group), 384)
2871ff
        || !group_order_tests(group)
2871ff
2871ff
    /* Curve P-521 (FIPS PUB 186-2, App. 6) */
2871ff
        || !TEST_true(BN_hex2bn(&p,                              "1FF"
2871ff
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"))
2871ff
        || !TEST_int_eq(1, BN_check_prime(p, ctx, NULL))
2871ff
        || !TEST_true(BN_hex2bn(&a,                              "1FF"
2871ff
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC"))
2871ff
        || !TEST_true(BN_hex2bn(&b,                              "051"
2871ff
                                    "953EB9618E1C9A1F929A21A0B68540EE"
2871ff
                                    "A2DA725B99B315F3B8B489918EF109E1"
2871ff
                                    "56193951EC7E937B1652C0BD3BB1BF07"
2871ff
                                    "3573DF883D2C34F1EF451FD46B503F00"))
2871ff
        || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
2871ff
        || !TEST_true(BN_hex2bn(&x,                               "C6"
2871ff
                                    "858E06B70404E9CD9E3ECB662395B442"
2871ff
                                    "9C648139053FB521F828AF606B4D3DBA"
2871ff
                                    "A14B5E77EFE75928FE1DC127A2FFA8DE"
2871ff
                                    "3348B3C1856A429BF97E7E31C2E5BD66"))
2871ff
        || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, 0, ctx))
2871ff
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
2871ff
        || !TEST_true(BN_hex2bn(&z,                              "1FF"
2871ff
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA"
2871ff
                                    "51868783BF2F966B7FCC0148F709A5D0"
2871ff
                                    "3BB5C9B8899C47AEBB6FB71E91386409"))
2871ff
        || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
2871ff
        || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx)))
2871ff
        goto err;
2871ff
2871ff
    TEST_info("NIST curve P-521 -- Generator");
2871ff
    test_output_bignum("x", x);
2871ff
    test_output_bignum("y", y);
2871ff
    /* G_y value taken from the standard: */
2871ff
    if (!TEST_true(BN_hex2bn(&z,                              "118"
2871ff
                                 "39296A789A3BC0045C8A5FB42C7D1BD9"
2871ff
                                 "98F54449579B446817AFBD17273E662C"
2871ff
                                 "97EE72995EF42640C550B9013FAD0761"
2871ff
                                 "353C7086A272C24088BE94769FD16650"))
2871ff
        || !TEST_BN_eq(y, z)
2871ff
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
2871ff
    /*
2871ff
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
2871ff
     * and therefore setting the coordinates should fail.
2871ff
     */
2871ff
        || !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
2871ff
                                                       ctx))
2871ff
        || !TEST_int_eq(EC_GROUP_get_degree(group), 521)
2871ff
        || !group_order_tests(group)
2871ff
2871ff
    /* more tests using the last curve */
2871ff
2871ff
    /* Restore the point that got mangled in the (x, y + 1) test. */
2871ff
        || !TEST_true(EC_POINT_set_affine_coordinates(group, P, x, y, ctx))
2871ff
        || !TEST_true(EC_POINT_copy(Q, P))
2871ff
        || !TEST_false(EC_POINT_is_at_infinity(group, Q))
2871ff
        || !TEST_true(EC_POINT_dbl(group, P, P, ctx))
2871ff
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
2871ff
        || !TEST_true(EC_POINT_invert(group, Q, ctx))       /* P = -2Q */
2871ff
        || !TEST_true(EC_POINT_add(group, R, P, Q, ctx))
2871ff
        || !TEST_true(EC_POINT_add(group, R, R, Q, ctx))
2871ff
        || !TEST_true(EC_POINT_is_at_infinity(group, R))    /* R = P + 2Q */
2871ff
        || !TEST_false(EC_POINT_is_at_infinity(group, Q)))
2871ff
        goto err;
2871ff
2871ff
#ifndef OPENSSL_NO_DEPRECATED_3_0
2871ff
    TEST_note("combined multiplication ...");
2871ff
    points[0] = Q;
2871ff
    points[1] = Q;
2871ff
    points[2] = Q;
2871ff
    points[3] = Q;
2871ff
2871ff
    if (!TEST_true(EC_GROUP_get_order(group, z, ctx))
2871ff
        || !TEST_true(BN_add(y, z, BN_value_one()))
2871ff
        || !TEST_BN_even(y)
2871ff
        || !TEST_true(BN_rshift1(y, y)))
2871ff
        goto err;
2871ff
2871ff
    scalars[0] = y;         /* (group order + 1)/2, so y*Q + y*Q = Q */
2871ff
    scalars[1] = y;
2871ff
2871ff
    /* z is still the group order */
2871ff
    if (!TEST_true(EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))
2871ff
        || !TEST_true(EC_POINTs_mul(group, R, z, 2, points, scalars, ctx))
2871ff
        || !TEST_int_eq(0, EC_POINT_cmp(group, P, R, ctx))
2871ff
        || !TEST_int_eq(0, EC_POINT_cmp(group, R, Q, ctx))
2871ff
        || !TEST_true(BN_rand(y, BN_num_bits(y), 0, 0))
2871ff
        || !TEST_true(BN_add(z, z, y)))
2871ff
        goto err;
2871ff
    BN_set_negative(z, 1);
2871ff
    scalars[0] = y;
2871ff
    scalars[1] = z;         /* z = -(order + y) */
2871ff
2871ff
    if (!TEST_true(EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))
2871ff
        || !TEST_true(EC_POINT_is_at_infinity(group, P))
2871ff
        || !TEST_true(BN_rand(x, BN_num_bits(y) - 1, 0, 0))
2871ff
        || !TEST_true(BN_add(z, x, y)))
2871ff
        goto err;
2871ff
    BN_set_negative(z, 1);
2871ff
    scalars[0] = x;
2871ff
    scalars[1] = y;
2871ff
    scalars[2] = z;         /* z = -(x+y) */
2871ff
2871ff
    if (!TEST_ptr(scalar3 = BN_new()))
2871ff
        goto err;
2871ff
    BN_zero(scalar3);
2871ff
    scalars[3] = scalar3;
2871ff
2871ff
    if (!TEST_true(EC_POINTs_mul(group, P, NULL, 4, points, scalars, ctx))
2871ff
        || !TEST_true(EC_POINT_is_at_infinity(group, P)))
2871ff
        goto err;
2871ff
#endif
2871ff
    TEST_note(" ok\n");
2871ff
    r = 1;
2871ff
err:
2871ff
    BN_CTX_free(ctx);
2871ff
    BN_free(p);
2871ff
    BN_free(a);
2871ff
    BN_free(b);
2871ff
    EC_GROUP_free(group);
2871ff
    EC_POINT_free(P);
2871ff
    EC_POINT_free(Q);
2871ff
    EC_POINT_free(R);
2871ff
    BN_free(x);
2871ff
    BN_free(y);
2871ff
    BN_free(z);
2871ff
    BN_free(yplusone);
2871ff
    BN_free(scalar3);
2871ff
    return r;
2871ff
}
2871ff
2871ff
static int internal_curve_test(int n)
2871ff
{
2871ff
    EC_GROUP *group = NULL;
2871ff
    int nid = curves[n].nid;
2871ff
2871ff
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))) {
2871ff
        TEST_info("EC_GROUP_new_curve_name() failed with curve %s\n",
2871ff
                  OBJ_nid2sn(nid));
2871ff
        return 0;
2871ff
    }
2871ff
    if (!TEST_true(EC_GROUP_check(group, NULL))) {
2871ff
        TEST_info("EC_GROUP_check() failed with curve %s\n", OBJ_nid2sn(nid));
2871ff
        EC_GROUP_free(group);
2871ff
        return 0;
2871ff
    }
2871ff
    EC_GROUP_free(group);
2871ff
    return 1;
2871ff
}
2871ff
2871ff
static int internal_curve_test_method(int n)
2871ff
{
2871ff
    int r, nid = curves[n].nid;
2871ff
    EC_GROUP *group;
2871ff
2871ff
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))) {
2871ff
        TEST_info("Curve %s failed\n", OBJ_nid2sn(nid));
2871ff
        return 0;
2871ff
    }
2871ff
    r = group_order_tests(group);
2871ff
    EC_GROUP_free(group);
2871ff
    return r;
2871ff
}
2871ff
2871ff
static int group_field_test(void)
2871ff
{
2871ff
    int r = 1;
2871ff
    BIGNUM *secp521r1_field = NULL;
2871ff
    BIGNUM *sect163r2_field = NULL;
2871ff
    EC_GROUP *secp521r1_group = NULL;
2871ff
    EC_GROUP *sect163r2_group = NULL;
2871ff
2871ff
    BN_hex2bn(&secp521r1_field,
2871ff
                "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2871ff
                "FFFF");
2871ff
2871ff
2871ff
    BN_hex2bn(&sect163r2_field,
2871ff
                "08000000000000000000000000000000"
2871ff
                "00000000C9");
2871ff
2871ff
    secp521r1_group = EC_GROUP_new_by_curve_name(NID_secp521r1);
2871ff
    if (BN_cmp(secp521r1_field, EC_GROUP_get0_field(secp521r1_group)))
2871ff
      r = 0;
2871ff
2871ff
    # ifndef OPENSSL_NO_EC2M
2871ff
    sect163r2_group = EC_GROUP_new_by_curve_name(NID_sect163r2);
2871ff
    if (BN_cmp(sect163r2_field, EC_GROUP_get0_field(sect163r2_group)))
2871ff
      r = 0;
2871ff
    # endif
2871ff
2871ff
    EC_GROUP_free(secp521r1_group);
2871ff
    EC_GROUP_free(sect163r2_group);
2871ff
    BN_free(secp521r1_field);
2871ff
    BN_free(sect163r2_field);
2871ff
    return r;
2871ff
}
2871ff
/*
2871ff
 * nistp_test_params contains magic numbers for testing
2871ff
 * several NIST curves with characteristic > 3.
2871ff
 */
2871ff
struct nistp_test_params {
2871ff
    const int nid;
2871ff
    int degree;
2871ff
    /*
2871ff
     * Qx, Qy and D are taken from
2871ff
     * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf
2871ff
     * Otherwise, values are standard curve parameters from FIPS 180-3
2871ff
     */
2871ff
    const char *p, *a, *b, *Qx, *Qy, *Gx, *Gy, *order, *d;
2871ff
};
2871ff
2871ff
static const struct nistp_test_params nistp_tests_params[] = {
2871ff
    {
2871ff
     /* P-224 */
2871ff
     NID_secp224r1,
2871ff
     224,
2871ff
     /* p */
2871ff
     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
2871ff
     /* a */
2871ff
     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
2871ff
     /* b */
2871ff
     "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
2871ff
     /* Qx */
2871ff
     "E84FB0B8E7000CB657D7973CF6B42ED78B301674276DF744AF130B3E",
2871ff
     /* Qy */
2871ff
     "4376675C6FC5612C21A0FF2D2A89D2987DF7A2BC52183B5982298555",
2871ff
     /* Gx */
2871ff
     "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
2871ff
     /* Gy */
2871ff
     "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
2871ff
     /* order */
2871ff
     "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
2871ff
     /* d */
2871ff
     "3F0C488E987C80BE0FEE521F8D90BE6034EC69AE11CA72AA777481E8",
2871ff
     },
2871ff
    {
2871ff
     /* P-256 */
2871ff
     NID_X9_62_prime256v1,
2871ff
     256,
2871ff
     /* p */
2871ff
     "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
2871ff
     /* a */
2871ff
     "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
2871ff
     /* b */
2871ff
     "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
2871ff
     /* Qx */
2871ff
     "b7e08afdfe94bad3f1dc8c734798ba1c62b3a0ad1e9ea2a38201cd0889bc7a19",
2871ff
     /* Qy */
2871ff
     "3603f747959dbf7a4bb226e41928729063adc7ae43529e61b563bbc606cc5e09",
2871ff
     /* Gx */
2871ff
     "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
2871ff
     /* Gy */
2871ff
     "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
2871ff
     /* order */
2871ff
     "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
2871ff
     /* d */
2871ff
     "c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96",
2871ff
     },
2871ff
    {
2871ff
     /* P-521 */
2871ff
     NID_secp521r1,
2871ff
     521,
2871ff
     /* p */
2871ff
                                                                  "1ff"
2871ff
     "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
2871ff
     "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
2871ff
     /* a */
2871ff
                                                                  "1ff"
2871ff
     "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
2871ff
     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
2871ff
     /* b */
2871ff
                                                                  "051"
2871ff
     "953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e1"
2871ff
     "56193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
2871ff
     /* Qx */
2871ff
                                                                 "0098"
2871ff
     "e91eef9a68452822309c52fab453f5f117c1da8ed796b255e9ab8f6410cca16e"
2871ff
     "59df403a6bdc6ca467a37056b1e54b3005d8ac030decfeb68df18b171885d5c4",
2871ff
     /* Qy */
2871ff
                                                                 "0164"
2871ff
     "350c321aecfc1cca1ba4364c9b15656150b4b78d6a48d7d28e7f31985ef17be8"
2871ff
     "554376b72900712c4b83ad668327231526e313f5f092999a4632fd50d946bc2e",
2871ff
     /* Gx */
2871ff
                                                                   "c6"
2871ff
     "858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dba"
2871ff
     "a14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
2871ff
     /* Gy */
2871ff
                                                                  "118"
2871ff
     "39296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c"
2871ff
     "97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
2871ff
     /* order */
2871ff
                                                                  "1ff"
2871ff
     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"
2871ff
     "51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
2871ff
     /* d */
2871ff
                                                                 "0100"
2871ff
     "085f47b8e1b8b11b7eb33028c0b2888e304bfc98501955b45bba1478dc184eee"
2871ff
     "df09b86a5f7c21994406072787205e69a63709fe35aa93ba333514b24f961722",
2871ff
     },
2871ff
};
2871ff
2871ff
static int nistp_single_test(int idx)
2871ff
{
2871ff
    const struct nistp_test_params *test = nistp_tests_params + idx;
2871ff
    BN_CTX *ctx = NULL;
2871ff
    BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL;
2871ff
    BIGNUM *n = NULL, *m = NULL, *order = NULL, *yplusone = NULL;
2871ff
    EC_GROUP *NISTP = NULL;
2871ff
    EC_POINT *G = NULL, *P = NULL, *Q = NULL, *Q_CHECK = NULL;
2871ff
    int r = 0;
2871ff
2871ff
    TEST_note("NIST curve P-%d (optimised implementation):",
2871ff
              test->degree);
2871ff
    if (!TEST_ptr(ctx = BN_CTX_new())
2871ff
        || !TEST_ptr(p = BN_new())
2871ff
        || !TEST_ptr(a = BN_new())
2871ff
        || !TEST_ptr(b = BN_new())
2871ff
        || !TEST_ptr(x = BN_new())
2871ff
        || !TEST_ptr(y = BN_new())
2871ff
        || !TEST_ptr(m = BN_new())
2871ff
        || !TEST_ptr(n = BN_new())
2871ff
        || !TEST_ptr(order = BN_new())
2871ff
        || !TEST_ptr(yplusone = BN_new())
2871ff
2871ff
        || !TEST_ptr(NISTP = EC_GROUP_new_by_curve_name(test->nid))
2871ff
        || !TEST_true(BN_hex2bn(&p, test->p))
2871ff
        || !TEST_int_eq(1, BN_check_prime(p, ctx, NULL))
2871ff
        || !TEST_true(BN_hex2bn(&a, test->a))
2871ff
        || !TEST_true(BN_hex2bn(&b, test->b))
2871ff
        || !TEST_true(EC_GROUP_set_curve(NISTP, p, a, b, ctx))
2871ff
        || !TEST_ptr(G = EC_POINT_new(NISTP))
2871ff
        || !TEST_ptr(P = EC_POINT_new(NISTP))
2871ff
        || !TEST_ptr(Q = EC_POINT_new(NISTP))
2871ff
        || !TEST_ptr(Q_CHECK = EC_POINT_new(NISTP))
2871ff
        || !TEST_true(BN_hex2bn(&x, test->Qx))
2871ff
        || !TEST_true(BN_hex2bn(&y, test->Qy))
2871ff
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
2871ff
    /*
2871ff
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
2871ff
     * and therefore setting the coordinates should fail.
2871ff
     */
2871ff
        || !TEST_false(EC_POINT_set_affine_coordinates(NISTP, Q_CHECK, x,
2871ff
                                                       yplusone, ctx))
2871ff
        || !TEST_true(EC_POINT_set_affine_coordinates(NISTP, Q_CHECK, x, y,
2871ff
                                                      ctx))
2871ff
        || !TEST_true(BN_hex2bn(&x, test->Gx))
2871ff
        || !TEST_true(BN_hex2bn(&y, test->Gy))
2871ff
        || !TEST_true(EC_POINT_set_affine_coordinates(NISTP, G, x, y, ctx))
2871ff
        || !TEST_true(BN_hex2bn(&order, test->order))
2871ff
        || !TEST_true(EC_GROUP_set_generator(NISTP, G, order, BN_value_one()))
2871ff
        || !TEST_int_eq(EC_GROUP_get_degree(NISTP), test->degree))
2871ff
        goto err;
2871ff
2871ff
    TEST_note("NIST test vectors ... ");
2871ff
    if (!TEST_true(BN_hex2bn(&n, test->d)))
2871ff
        goto err;
2871ff
    /* fixed point multiplication */
2871ff
    EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx);
2871ff
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
2871ff
        goto err;
2871ff
    /* random point multiplication */
2871ff
    EC_POINT_mul(NISTP, Q, NULL, G, n, ctx);
2871ff
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx))
2871ff
2871ff
        /* set generator to P = 2*G, where G is the standard generator */
2871ff
        || !TEST_true(EC_POINT_dbl(NISTP, P, G, ctx))
2871ff
        || !TEST_true(EC_GROUP_set_generator(NISTP, P, order, BN_value_one()))
2871ff
        /* set the scalar to m=n/2, where n is the NIST test scalar */
2871ff
        || !TEST_true(BN_rshift(m, n, 1)))
2871ff
        goto err;
2871ff
2871ff
    /* test the non-standard generator */
2871ff
    /* fixed point multiplication */
2871ff
    EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx);
2871ff
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
2871ff
        goto err;
2871ff
    /* random point multiplication */
2871ff
    EC_POINT_mul(NISTP, Q, NULL, P, m, ctx);
2871ff
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx))
2871ff
#ifndef OPENSSL_NO_DEPRECATED_3_0
2871ff
        /* We have not performed precomp so this should be false */
2871ff
        || !TEST_false(EC_GROUP_have_precompute_mult(NISTP))
2871ff
        /* now repeat all tests with precomputation */
2871ff
        || !TEST_true(EC_GROUP_precompute_mult(NISTP, ctx))
2871ff
#endif
2871ff
        )
2871ff
        goto err;
2871ff
2871ff
    /* fixed point multiplication */
2871ff
    EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx);
2871ff
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
2871ff
        goto err;
2871ff
    /* random point multiplication */
2871ff
    EC_POINT_mul(NISTP, Q, NULL, P, m, ctx);
2871ff
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx))
2871ff
2871ff
    /* reset generator */
2871ff
        || !TEST_true(EC_GROUP_set_generator(NISTP, G, order, BN_value_one())))
2871ff
        goto err;
2871ff
    /* fixed point multiplication */
2871ff
    EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx);
2871ff
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
2871ff
        goto err;
2871ff
    /* random point multiplication */
2871ff
    EC_POINT_mul(NISTP, Q, NULL, G, n, ctx);
2871ff
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
2871ff
        goto err;
2871ff
2871ff
    /* regression test for felem_neg bug */
2871ff
    if (!TEST_true(BN_set_word(m, 32))
2871ff
        || !TEST_true(BN_set_word(n, 31))
2871ff
        || !TEST_true(EC_POINT_copy(P, G))
2871ff
        || !TEST_true(EC_POINT_invert(NISTP, P, ctx))
2871ff
        || !TEST_true(EC_POINT_mul(NISTP, Q, m, P, n, ctx))
2871ff
        || !TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, G, ctx)))
2871ff
      goto err;
2871ff
2871ff
    r = 1;
2871ff
err:
2871ff
    EC_GROUP_free(NISTP);
2871ff
    EC_POINT_free(G);
2871ff
    EC_POINT_free(P);
2871ff
    EC_POINT_free(Q);
2871ff
    EC_POINT_free(Q_CHECK);
2871ff
    BN_free(n);
2871ff
    BN_free(m);
2871ff
    BN_free(p);
2871ff
    BN_free(a);
2871ff
    BN_free(b);
2871ff
    BN_free(x);
2871ff
    BN_free(y);
2871ff
    BN_free(order);
2871ff
    BN_free(yplusone);
2871ff
    BN_CTX_free(ctx);
2871ff
    return r;
2871ff
}
2871ff
2871ff
static const unsigned char p521_named[] = {
2871ff
    0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23,
2871ff
};
2871ff
2871ff
static const unsigned char p521_explicit[] = {
2871ff
    0x30, 0x82, 0x01, 0xc3, 0x02, 0x01, 0x01, 0x30, 0x4d, 0x06, 0x07, 0x2a,
2871ff
    0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x42, 0x01, 0xff, 0xff, 0xff,
2871ff
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2871ff
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2871ff
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2871ff
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2871ff
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2871ff
    0xff, 0xff, 0x30, 0x81, 0x9f, 0x04, 0x42, 0x01, 0xff, 0xff, 0xff, 0xff,
2871ff
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2871ff
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2871ff
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2871ff
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2871ff
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2871ff
    0xfc, 0x04, 0x42, 0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, 0x9a,
2871ff
    0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85, 0x40, 0xee, 0xa2, 0xda, 0x72,
2871ff
    0x5b, 0x99, 0xb3, 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1, 0x09,
2871ff
    0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e, 0x93, 0x7b, 0x16, 0x52, 0xc0,
2871ff
    0xbd, 0x3b, 0xb1, 0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, 0x34,
2871ff
    0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50, 0x3f, 0x00, 0x03, 0x15, 0x00,
2871ff
    0xd0, 0x9e, 0x88, 0x00, 0x29, 0x1c, 0xb8, 0x53, 0x96, 0xcc, 0x67, 0x17,
2871ff
    0x39, 0x32, 0x84, 0xaa, 0xa0, 0xda, 0x64, 0xba, 0x04, 0x81, 0x85, 0x04,
2871ff
    0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd, 0x9e, 0x3e,
2871ff
    0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f,
2871ff
    0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba, 0xa1, 0x4b,
2871ff
    0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff,
2871ff
    0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, 0xf9, 0x7e,
2871ff
    0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66, 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78,
2871ff
    0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9,
2871ff
    0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17,
2871ff
    0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40,
2871ff
    0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86,
2871ff
    0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,
2871ff
    0x02, 0x42, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2871ff
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2871ff
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa,
2871ff
    0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, 0x7f, 0xcc, 0x01, 0x48,
2871ff
    0xf7, 0x09, 0xa5, 0xd0, 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae,
2871ff
    0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09, 0x02, 0x01, 0x01,
2871ff
};
2871ff
2871ff
/*
2871ff
 * This test validates a named curve's group parameters using
2871ff
 * EC_GROUP_check_named_curve(). It also checks that modifying any of the
2871ff
 * group parameters results in the curve not being valid.
2871ff
 */
2871ff
static int check_named_curve_test(int id)
2871ff
{
2871ff
    int ret = 0, nid, field_nid, has_seed;
2871ff
    EC_GROUP *group = NULL, *gtest = NULL;
2871ff
    const EC_POINT *group_gen = NULL;
2871ff
    EC_POINT *other_gen = NULL;
2871ff
    BIGNUM *group_p = NULL, *group_a = NULL, *group_b = NULL;
2871ff
    BIGNUM *other_p = NULL, *other_a = NULL, *other_b = NULL;
2871ff
    BIGNUM *group_cofactor = NULL, *other_cofactor = NULL;
2871ff
    BIGNUM *other_order = NULL;
2871ff
    const BIGNUM *group_order = NULL;
2871ff
    BN_CTX *bn_ctx = NULL;
2871ff
    static const unsigned char invalid_seed[] = "THIS IS NOT A VALID SEED";
2871ff
    static size_t invalid_seed_len = sizeof(invalid_seed);
2871ff
2871ff
    /* Do some setup */
2871ff
    nid = curves[id].nid;
2871ff
    if (!TEST_ptr(bn_ctx = BN_CTX_new())
2871ff
        || !TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))
2871ff
        || !TEST_ptr(gtest = EC_GROUP_dup(group))
2871ff
        || !TEST_ptr(group_p = BN_new())
2871ff
        || !TEST_ptr(group_a = BN_new())
2871ff
        || !TEST_ptr(group_b = BN_new())
2871ff
        || !TEST_ptr(group_cofactor = BN_new())
2871ff
        || !TEST_ptr(group_gen = EC_GROUP_get0_generator(group))
2871ff
        || !TEST_ptr(group_order = EC_GROUP_get0_order(group))
2871ff
        || !TEST_true(EC_GROUP_get_cofactor(group, group_cofactor, NULL))
2871ff
        || !TEST_true(EC_GROUP_get_curve(group, group_p, group_a, group_b, NULL))
2871ff
        || !TEST_ptr(other_gen = EC_POINT_dup(group_gen, group))
2871ff
        || !TEST_true(EC_POINT_add(group, other_gen, group_gen, group_gen, NULL))
2871ff
        || !TEST_ptr(other_order = BN_dup(group_order))
2871ff
        || !TEST_true(BN_add_word(other_order, 1))
2871ff
        || !TEST_ptr(other_a = BN_dup(group_a))
2871ff
        || !TEST_true(BN_add_word(other_a, 1))
2871ff
        || !TEST_ptr(other_b = BN_dup(group_b))
2871ff
        || !TEST_true(BN_add_word(other_b, 1))
2871ff
        || !TEST_ptr(other_cofactor = BN_dup(group_cofactor))
2871ff
        || !TEST_true(BN_add_word(other_cofactor, 1)))
2871ff
        goto err;
2871ff
2871ff
    /* Determine if the built-in curve has a seed field set */
2871ff
    has_seed = (EC_GROUP_get_seed_len(group) > 0);
2871ff
    field_nid = EC_GROUP_get_field_type(group);
2871ff
    if (field_nid == NID_X9_62_characteristic_two_field) {
2871ff
        if (!TEST_ptr(other_p = BN_dup(group_p))
2871ff
            || !TEST_true(BN_lshift1(other_p, other_p)))
2871ff
            goto err;
2871ff
    } else {
2871ff
        if (!TEST_ptr(other_p = BN_dup(group_p)))
2871ff
            goto err;
2871ff
        /*
2871ff
         * Just choosing any arbitrary prime does not work..
2871ff
         * Setting p via ec_GFp_nist_group_set_curve() needs the prime to be a
2871ff
         * nist prime. So only select one of these as an alternate prime.
2871ff
         */
2871ff
        if (!TEST_ptr(BN_copy(other_p,
2871ff
                              BN_ucmp(BN_get0_nist_prime_192(), other_p) == 0 ?
2871ff
                                      BN_get0_nist_prime_256() :
2871ff
                                      BN_get0_nist_prime_192())))
2871ff
            goto err;
2871ff
    }
2871ff
2871ff
    /* Passes because this is a valid curve */
2871ff
    if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0, NULL), nid)
2871ff
        /* Only NIST curves pass */
2871ff
        || !TEST_int_eq(EC_GROUP_check_named_curve(group, 1, NULL),
2871ff
                        EC_curve_nid2nist(nid) != NULL ? nid : NID_undef))
2871ff
        goto err;
2871ff
2871ff
    /* Fail if the curve name doesn't match the parameters */
2871ff
    EC_GROUP_set_curve_name(group, nid + 1);
2871ff
    ERR_set_mark();
2871ff
    if (!TEST_int_le(EC_GROUP_check_named_curve(group, 0, NULL), 0))
2871ff
        goto err;
2871ff
    ERR_pop_to_mark();
2871ff
2871ff
    /* Restore curve name and ensure it's passing */
2871ff
    EC_GROUP_set_curve_name(group, nid);
2871ff
    if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0, NULL), nid))
2871ff
        goto err;
2871ff
2871ff
    if (!TEST_int_eq(EC_GROUP_set_seed(group, invalid_seed, invalid_seed_len),
2871ff
                     invalid_seed_len))
2871ff
        goto err;
2871ff
2871ff
    if (has_seed) {
2871ff
        /*
2871ff
         * If the built-in curve has a seed and we set the seed to another value
2871ff
         * then it will fail the check.
2871ff
         */
2871ff
        if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0, NULL), 0))
2871ff
            goto err;
2871ff
    } else {
2871ff
        /*
2871ff
         * If the built-in curve does not have a seed then setting the seed will
2871ff
         * pass the check (as the seed is optional).
2871ff
         */
2871ff
        if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0, NULL), nid))
2871ff
            goto err;
2871ff
    }
2871ff
    /* Pass if the seed is unknown (as it is optional) */
2871ff
    if (!TEST_int_eq(EC_GROUP_set_seed(group, NULL, 0), 1)
2871ff
        || !TEST_int_eq(EC_GROUP_check_named_curve(group, 0, NULL), nid))
2871ff
        goto err;
2871ff
2871ff
    /* Check that a duped group passes */
2871ff
    if (!TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), nid))
2871ff
        goto err;
2871ff
2871ff
    /* check that changing any generator parameter fails */
2871ff
    if (!TEST_true(EC_GROUP_set_generator(gtest, other_gen, group_order,
2871ff
                                          group_cofactor))
2871ff
        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), 0)
2871ff
        || !TEST_true(EC_GROUP_set_generator(gtest, group_gen, other_order,
2871ff
                                             group_cofactor))
2871ff
        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), 0)
2871ff
        /* The order is not an optional field, so this should fail */
2871ff
        || !TEST_false(EC_GROUP_set_generator(gtest, group_gen, NULL,
2871ff
                                              group_cofactor))
2871ff
        || !TEST_true(EC_GROUP_set_generator(gtest, group_gen, group_order,
2871ff
                                             other_cofactor))
2871ff
        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), 0)
2871ff
        /* Check that if the cofactor is not set then it still passes */
2871ff
        || !TEST_true(EC_GROUP_set_generator(gtest, group_gen, group_order,
2871ff
                                             NULL))
2871ff
        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), nid)
2871ff
        /* check that restoring the generator passes */
2871ff
        || !TEST_true(EC_GROUP_set_generator(gtest, group_gen, group_order,
2871ff
                                             group_cofactor))
2871ff
        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), nid))
2871ff
        goto err;
2871ff
2871ff
    /*
2871ff
     * check that changing any curve parameter fails
2871ff
     *
2871ff
     * Setting arbitrary p, a or b might fail for some EC_GROUPs
2871ff
     * depending on the internal EC_METHOD implementation, hence run
2871ff
     * these tests conditionally to the success of EC_GROUP_set_curve().
2871ff
     */
2871ff
    ERR_set_mark();
2871ff
    if (EC_GROUP_set_curve(gtest, other_p, group_a, group_b, NULL)) {
2871ff
        if (!TEST_int_le(EC_GROUP_check_named_curve(gtest, 0, NULL), 0))
2871ff
            goto err;
2871ff
    } else {
2871ff
        /* clear the error stack if EC_GROUP_set_curve() failed */
2871ff
        ERR_pop_to_mark();
2871ff
        ERR_set_mark();
2871ff
    }
2871ff
    if (EC_GROUP_set_curve(gtest, group_p, other_a, group_b, NULL)) {
2871ff
        if (!TEST_int_le(EC_GROUP_check_named_curve(gtest, 0, NULL), 0))
2871ff
            goto err;
2871ff
    } else {
2871ff
        /* clear the error stack if EC_GROUP_set_curve() failed */
2871ff
        ERR_pop_to_mark();
2871ff
        ERR_set_mark();
2871ff
    }
2871ff
    if (EC_GROUP_set_curve(gtest, group_p, group_a, other_b, NULL)) {
2871ff
        if (!TEST_int_le(EC_GROUP_check_named_curve(gtest, 0, NULL), 0))
2871ff
            goto err;
2871ff
    } else {
2871ff
        /* clear the error stack if EC_GROUP_set_curve() failed */
2871ff
        ERR_pop_to_mark();
2871ff
        ERR_set_mark();
2871ff
    }
2871ff
    ERR_pop_to_mark();
2871ff
2871ff
    /* Check that restoring the curve parameters passes */
2871ff
    if (!TEST_true(EC_GROUP_set_curve(gtest, group_p, group_a, group_b, NULL))
2871ff
        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), nid))
2871ff
        goto err;
2871ff
2871ff
    ret = 1;
2871ff
err:
2871ff
    BN_free(group_p);
2871ff
    BN_free(other_p);
2871ff
    BN_free(group_a);
2871ff
    BN_free(other_a);
2871ff
    BN_free(group_b);
2871ff
    BN_free(other_b);
2871ff
    BN_free(group_cofactor);
2871ff
    BN_free(other_cofactor);
2871ff
    BN_free(other_order);
2871ff
    EC_POINT_free(other_gen);
2871ff
    EC_GROUP_free(gtest);
2871ff
    EC_GROUP_free(group);
2871ff
    BN_CTX_free(bn_ctx);
2871ff
    return ret;
2871ff
}
2871ff
2871ff
/*
2871ff
 * This checks the lookup capability of EC_GROUP_check_named_curve()
2871ff
 * when the given group was created with explicit parameters.
2871ff
 *
2871ff
 * It is possible to retrieve an alternative alias that does not match
2871ff
 * the original nid in this case.
2871ff
 */
2871ff
static int check_named_curve_lookup_test(int id)
2871ff
{
2871ff
    int ret = 0, nid, rv = 0;
2871ff
    EC_GROUP *g = NULL , *ga = NULL;
2871ff
    ECPARAMETERS *p = NULL, *pa = NULL;
2871ff
    BN_CTX *ctx = NULL;
2871ff
2871ff
    /* Do some setup */
2871ff
    nid = curves[id].nid;
2871ff
    if (!TEST_ptr(ctx = BN_CTX_new())
2871ff
        || !TEST_ptr(g = EC_GROUP_new_by_curve_name(nid))
2871ff
        || !TEST_ptr(p = EC_GROUP_get_ecparameters(g, NULL)))
2871ff
        goto err;
2871ff
2871ff
    /* replace with group from explicit parameters */
2871ff
    EC_GROUP_free(g);
2871ff
    if (!TEST_ptr(g = EC_GROUP_new_from_ecparameters(p)))
2871ff
        goto err;
2871ff
2871ff
    if (!TEST_int_gt(rv = EC_GROUP_check_named_curve(g, 0, NULL), 0))
2871ff
        goto err;
2871ff
    if (rv != nid) {
2871ff
        /*
2871ff
         * Found an alias:
2871ff
         * fail if the returned nid is not an alias of the original group.
2871ff
         *
2871ff
         * The comparison here is done by comparing two explicit
2871ff
         * parameter EC_GROUPs with EC_GROUP_cmp(), to ensure the
2871ff
         * comparison happens with unnamed EC_GROUPs using the same
2871ff
         * EC_METHODs.
2871ff
         */
2871ff
        if (!TEST_ptr(ga = EC_GROUP_new_by_curve_name(rv))
2871ff
                || !TEST_ptr(pa = EC_GROUP_get_ecparameters(ga, NULL)))
2871ff
            goto err;
2871ff
2871ff
        /* replace with group from explicit parameters, then compare */
2871ff
        EC_GROUP_free(ga);
2871ff
        if (!TEST_ptr(ga = EC_GROUP_new_from_ecparameters(pa))
2871ff
                || !TEST_int_eq(EC_GROUP_cmp(g, ga, ctx), 0))
2871ff
            goto err;
2871ff
    }
2871ff
2871ff
    ret = 1;
2871ff
2871ff
 err:
2871ff
    EC_GROUP_free(g);
2871ff
    EC_GROUP_free(ga);
2871ff
    ECPARAMETERS_free(p);
2871ff
    ECPARAMETERS_free(pa);
2871ff
    BN_CTX_free(ctx);
2871ff
2871ff
    return ret;
2871ff
}
2871ff
2871ff
/*
2871ff
 * Sometime we cannot compare nids for equality, as the built-in curve table
2871ff
 * includes aliases with different names for the same curve.
2871ff
 *
2871ff
 * This function returns TRUE (1) if the checked nids are identical, or if they
2871ff
 * alias to the same curve. FALSE (0) otherwise.
2871ff
 */
2871ff
static ossl_inline
2871ff
int are_ec_nids_compatible(int n1d, int n2d)
2871ff
{
2871ff
    int ret = 0;
2871ff
    switch (n1d) {
2871ff
#ifndef OPENSSL_NO_EC2M
2871ff
        case NID_sect113r1:
2871ff
        case NID_wap_wsg_idm_ecid_wtls4:
2871ff
            ret = (n2d == NID_sect113r1 || n2d == NID_wap_wsg_idm_ecid_wtls4);
2871ff
            break;
2871ff
        case NID_sect163k1:
2871ff
        case NID_wap_wsg_idm_ecid_wtls3:
2871ff
            ret = (n2d == NID_sect163k1 || n2d == NID_wap_wsg_idm_ecid_wtls3);
2871ff
            break;
2871ff
        case NID_sect233k1:
2871ff
        case NID_wap_wsg_idm_ecid_wtls10:
2871ff
            ret = (n2d == NID_sect233k1 || n2d == NID_wap_wsg_idm_ecid_wtls10);
2871ff
            break;
2871ff
        case NID_sect233r1:
2871ff
        case NID_wap_wsg_idm_ecid_wtls11:
2871ff
            ret = (n2d == NID_sect233r1 || n2d == NID_wap_wsg_idm_ecid_wtls11);
2871ff
            break;
2871ff
        case NID_X9_62_c2pnb163v1:
2871ff
        case NID_wap_wsg_idm_ecid_wtls5:
2871ff
            ret = (n2d == NID_X9_62_c2pnb163v1
2871ff
                   || n2d == NID_wap_wsg_idm_ecid_wtls5);
2871ff
            break;
2871ff
#endif /* OPENSSL_NO_EC2M */
2871ff
        case NID_secp112r1:
2871ff
        case NID_wap_wsg_idm_ecid_wtls6:
2871ff
            ret = (n2d == NID_secp112r1 || n2d == NID_wap_wsg_idm_ecid_wtls6);
2871ff
            break;
2871ff
        case NID_secp160r2:
2871ff
        case NID_wap_wsg_idm_ecid_wtls7:
2871ff
            ret = (n2d == NID_secp160r2 || n2d == NID_wap_wsg_idm_ecid_wtls7);
2871ff
            break;
2871ff
#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128
2871ff
        case NID_secp224r1:
2871ff
        case NID_wap_wsg_idm_ecid_wtls12:
2871ff
            ret = (n2d == NID_secp224r1 || n2d == NID_wap_wsg_idm_ecid_wtls12);
2871ff
            break;
2871ff
#else
2871ff
        /*
2871ff
         * For SEC P-224 we want to ensure that the SECP nid is returned, as
2871ff
         * that is associated with a specialized method.
2871ff
         */
2871ff
        case NID_wap_wsg_idm_ecid_wtls12:
2871ff
            ret = (n2d == NID_secp224r1);
2871ff
            break;
2871ff
#endif /* def(OPENSSL_NO_EC_NISTP_64_GCC_128) */
2871ff
2871ff
        default:
2871ff
            ret = (n1d == n2d);
2871ff
    }
2871ff
    return ret;
2871ff
}
2871ff
2871ff
/*
2871ff
 * This checks that EC_GROUP_bew_from_ecparameters() returns a "named"
2871ff
 * EC_GROUP for built-in curves.
2871ff
 *
2871ff
 * Note that it is possible to retrieve an alternative alias that does not match
2871ff
 * the original nid.
2871ff
 *
2871ff
 * Ensure that the OPENSSL_EC_EXPLICIT_CURVE ASN1 flag is set.
2871ff
 */
2871ff
static int check_named_curve_from_ecparameters(int id)
2871ff
{
2871ff
    int ret = 0, nid, tnid;
2871ff
    EC_GROUP *group = NULL, *tgroup = NULL, *tmpg = NULL;
2871ff
    const EC_POINT *group_gen = NULL;
2871ff
    EC_POINT *other_gen = NULL;
2871ff
    BIGNUM *group_cofactor = NULL, *other_cofactor = NULL;
2871ff
    BIGNUM *other_gen_x = NULL, *other_gen_y = NULL;
2871ff
    const BIGNUM *group_order = NULL;
2871ff
    BIGNUM *other_order = NULL;
2871ff
    BN_CTX *bn_ctx = NULL;
2871ff
    static const unsigned char invalid_seed[] = "THIS IS NOT A VALID SEED";
2871ff
    static size_t invalid_seed_len = sizeof(invalid_seed);
2871ff
    ECPARAMETERS *params = NULL, *other_params = NULL;
2871ff
    EC_GROUP *g_ary[8] = {NULL};
2871ff
    EC_GROUP **g_next = &g_ary[0];
2871ff
    ECPARAMETERS *p_ary[8] = {NULL};
2871ff
    ECPARAMETERS **p_next = &p_ary[0];
2871ff
2871ff
    /* Do some setup */
2871ff
    nid = curves[id].nid;
2871ff
    TEST_note("Curve %s", OBJ_nid2sn(nid));
2871ff
    if (!TEST_ptr(bn_ctx = BN_CTX_new()))
2871ff
        return ret;
2871ff
    BN_CTX_start(bn_ctx);
2871ff
2871ff
    if (/* Allocations */
2871ff
        !TEST_ptr(group_cofactor = BN_CTX_get(bn_ctx))
2871ff
        || !TEST_ptr(other_gen_x = BN_CTX_get(bn_ctx))
2871ff
        || !TEST_ptr(other_gen_y = BN_CTX_get(bn_ctx))
2871ff
        || !TEST_ptr(other_order = BN_CTX_get(bn_ctx))
2871ff
        || !TEST_ptr(other_cofactor = BN_CTX_get(bn_ctx))
2871ff
        /* Generate reference group and params */
2871ff
        || !TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))
2871ff
        || !TEST_ptr(params = EC_GROUP_get_ecparameters(group, NULL))
2871ff
        || !TEST_ptr(group_gen = EC_GROUP_get0_generator(group))
2871ff
        || !TEST_ptr(group_order = EC_GROUP_get0_order(group))
2871ff
        || !TEST_true(EC_GROUP_get_cofactor(group, group_cofactor, NULL))
2871ff
        /* compute `other_*` values */
2871ff
        || !TEST_ptr(tmpg = EC_GROUP_dup(group))
2871ff
        || !TEST_ptr(other_gen = EC_POINT_dup(group_gen, group))
2871ff
        || !TEST_true(EC_POINT_add(group, other_gen, group_gen, group_gen, NULL))
2871ff
        || !TEST_true(EC_POINT_get_affine_coordinates(group, other_gen,
2871ff
                      other_gen_x, other_gen_y, bn_ctx))
2871ff
        || !TEST_true(BN_copy(other_order, group_order))
2871ff
        || !TEST_true(BN_add_word(other_order, 1))
2871ff
        || !TEST_true(BN_copy(other_cofactor, group_cofactor))
2871ff
        || !TEST_true(BN_add_word(other_cofactor, 1)))
2871ff
        goto err;
2871ff
2871ff
    EC_POINT_free(other_gen);
2871ff
    other_gen = NULL;
2871ff
2871ff
    if (!TEST_ptr(other_gen = EC_POINT_new(tmpg))
2871ff
        || !TEST_true(EC_POINT_set_affine_coordinates(tmpg, other_gen,
2871ff
                                                      other_gen_x, other_gen_y,
2871ff
                                                      bn_ctx)))
2871ff
        goto err;
2871ff
2871ff
    /*
2871ff
     * ###########################
2871ff
     * # Actual tests start here #
2871ff
     * ###########################
2871ff
     */
2871ff
2871ff
    /*
2871ff
     * Creating a group from built-in explicit parameters returns a
2871ff
     * "named" EC_GROUP
2871ff
     */
2871ff
    if (!TEST_ptr(tgroup = *g_next++ = EC_GROUP_new_from_ecparameters(params))
2871ff
        || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef))
2871ff
        goto err;
2871ff
    /*
2871ff
     * We cannot always guarantee the names match, as the built-in table
2871ff
     * contains aliases for the same curve with different names.
2871ff
     */
2871ff
    if (!TEST_true(are_ec_nids_compatible(nid, tnid))) {
2871ff
        TEST_info("nid = %s, tnid = %s", OBJ_nid2sn(nid), OBJ_nid2sn(tnid));
2871ff
        goto err;
2871ff
    }
2871ff
    /* Ensure that the OPENSSL_EC_EXPLICIT_CURVE ASN1 flag is set. */
2871ff
    if (!TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup), OPENSSL_EC_EXPLICIT_CURVE))
2871ff
        goto err;
2871ff
2871ff
    /*
2871ff
     * An invalid seed in the parameters should be ignored: expect a "named"
2871ff
     * group.
2871ff
     */
2871ff
    if (!TEST_int_eq(EC_GROUP_set_seed(tmpg, invalid_seed, invalid_seed_len),
2871ff
                     invalid_seed_len)
2871ff
            || !TEST_ptr(other_params = *p_next++ =
2871ff
                         EC_GROUP_get_ecparameters(tmpg, NULL))
2871ff
            || !TEST_ptr(tgroup = *g_next++ =
2871ff
                          EC_GROUP_new_from_ecparameters(other_params))
2871ff
            || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
2871ff
            || !TEST_true(are_ec_nids_compatible(nid, tnid))
2871ff
            || !TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup),
2871ff
                            OPENSSL_EC_EXPLICIT_CURVE)) {
2871ff
        TEST_info("nid = %s, tnid = %s", OBJ_nid2sn(nid), OBJ_nid2sn(tnid));
2871ff
        goto err;
2871ff
    }
2871ff
2871ff
    /*
2871ff
     * A null seed in the parameters should be ignored, as it is optional:
2871ff
     * expect a "named" group.
2871ff
     */
2871ff
    if (!TEST_int_eq(EC_GROUP_set_seed(tmpg, NULL, 0), 1)
2871ff
            || !TEST_ptr(other_params = *p_next++ =
2871ff
                         EC_GROUP_get_ecparameters(tmpg, NULL))
2871ff
            || !TEST_ptr(tgroup = *g_next++ =
2871ff
                          EC_GROUP_new_from_ecparameters(other_params))
2871ff
            || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
2871ff
            || !TEST_true(are_ec_nids_compatible(nid, tnid))
2871ff
            || !TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup),
2871ff
                            OPENSSL_EC_EXPLICIT_CURVE)) {
2871ff
        TEST_info("nid = %s, tnid = %s", OBJ_nid2sn(nid), OBJ_nid2sn(tnid));
2871ff
        goto err;
2871ff
    }
2871ff
2871ff
    /*
2871ff
     * Check that changing any of the generator parameters does not yield a
2871ff
     * match with the built-in curves
2871ff
     */
2871ff
    if (/* Other gen, same group order & cofactor */
2871ff
        !TEST_true(EC_GROUP_set_generator(tmpg, other_gen, group_order,
2871ff
                                          group_cofactor))
2871ff
        || !TEST_ptr(other_params = *p_next++ =
2871ff
                     EC_GROUP_get_ecparameters(tmpg, NULL))
2871ff
        || !TEST_ptr(tgroup = *g_next++ =
2871ff
                      EC_GROUP_new_from_ecparameters(other_params))
2871ff
        || !TEST_int_eq((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
2871ff
        /* Same gen & cofactor, different order */
2871ff
        || !TEST_true(EC_GROUP_set_generator(tmpg, group_gen, other_order,
2871ff
                                             group_cofactor))
2871ff
        || !TEST_ptr(other_params = *p_next++ =
2871ff
                     EC_GROUP_get_ecparameters(tmpg, NULL))
2871ff
        || !TEST_ptr(tgroup = *g_next++ =
2871ff
                      EC_GROUP_new_from_ecparameters(other_params))
2871ff
        || !TEST_int_eq((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
2871ff
        /* The order is not an optional field, so this should fail */
2871ff
        || !TEST_false(EC_GROUP_set_generator(tmpg, group_gen, NULL,
2871ff
                                              group_cofactor))
2871ff
        /* Check that a wrong cofactor is ignored, and we still match */
2871ff
        || !TEST_true(EC_GROUP_set_generator(tmpg, group_gen, group_order,
2871ff
                                             other_cofactor))
2871ff
        || !TEST_ptr(other_params = *p_next++ =
2871ff
                     EC_GROUP_get_ecparameters(tmpg, NULL))
2871ff
        || !TEST_ptr(tgroup = *g_next++ =
2871ff
                      EC_GROUP_new_from_ecparameters(other_params))
2871ff
        || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
2871ff
        || !TEST_true(are_ec_nids_compatible(nid, tnid))
2871ff
        || !TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup),
2871ff
                        OPENSSL_EC_EXPLICIT_CURVE)
2871ff
        /* Check that if the cofactor is not set then it still matches */
2871ff
        || !TEST_true(EC_GROUP_set_generator(tmpg, group_gen, group_order,
2871ff
                                             NULL))
2871ff
        || !TEST_ptr(other_params = *p_next++ =
2871ff
                     EC_GROUP_get_ecparameters(tmpg, NULL))
2871ff
        || !TEST_ptr(tgroup = *g_next++ =
2871ff
                      EC_GROUP_new_from_ecparameters(other_params))
2871ff
        || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
2871ff
        || !TEST_true(are_ec_nids_compatible(nid, tnid))
2871ff
        || !TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup),
2871ff
                        OPENSSL_EC_EXPLICIT_CURVE)
2871ff
        /* check that restoring the generator passes */
2871ff
        || !TEST_true(EC_GROUP_set_generator(tmpg, group_gen, group_order,
2871ff
                                             group_cofactor))
2871ff
        || !TEST_ptr(other_params = *p_next++ =
2871ff
                     EC_GROUP_get_ecparameters(tmpg, NULL))
2871ff
        || !TEST_ptr(tgroup = *g_next++ =
2871ff
                      EC_GROUP_new_from_ecparameters(other_params))
2871ff
        || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
2871ff
        || !TEST_true(are_ec_nids_compatible(nid, tnid))
2871ff
        || !TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup),
2871ff
                        OPENSSL_EC_EXPLICIT_CURVE))
2871ff
        goto err;
2871ff
2871ff
    ret = 1;
2871ff
err:
2871ff
    for (g_next = &g_ary[0]; g_next < g_ary + OSSL_NELEM(g_ary); g_next++)
2871ff
        EC_GROUP_free(*g_next);
2871ff
    for (p_next = &p_ary[0]; p_next < p_ary + OSSL_NELEM(g_ary); p_next++)
2871ff
        ECPARAMETERS_free(*p_next);
2871ff
    ECPARAMETERS_free(params);
2871ff
    EC_POINT_free(other_gen);
2871ff
    EC_GROUP_free(tmpg);
2871ff
    EC_GROUP_free(group);
2871ff
    BN_CTX_end(bn_ctx);
2871ff
    BN_CTX_free(bn_ctx);
2871ff
    return ret;
2871ff
}
2871ff
2871ff
2871ff
static int parameter_test(void)
2871ff
{
2871ff
    EC_GROUP *group = NULL, *group2 = NULL;
2871ff
    ECPARAMETERS *ecparameters = NULL;
2871ff
    unsigned char *buf = NULL;
2871ff
    int r = 0, len;
2871ff
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_secp384r1))
2871ff
        || !TEST_ptr(ecparameters = EC_GROUP_get_ecparameters(group, NULL))
2871ff
        || !TEST_ptr(group2 = EC_GROUP_new_from_ecparameters(ecparameters))
2871ff
        || !TEST_int_eq(EC_GROUP_cmp(group, group2, NULL), 0))
2871ff
        goto err;
2871ff
2871ff
    EC_GROUP_free(group);
2871ff
    group = NULL;
2871ff
2871ff
    /* Test the named curve encoding, which should be default. */
2871ff
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_secp521r1))
2871ff
        || !TEST_true((len = i2d_ECPKParameters(group, &buf)) >= 0)
2871ff
        || !TEST_mem_eq(buf, len, p521_named, sizeof(p521_named)))
2871ff
        goto err;
2871ff
2871ff
    OPENSSL_free(buf);
2871ff
    buf = NULL;
2871ff
2871ff
    /*
2871ff
     * Test the explicit encoding. P-521 requires correctly zero-padding the
2871ff
     * curve coefficients.
2871ff
     */
2871ff
    EC_GROUP_set_asn1_flag(group, OPENSSL_EC_EXPLICIT_CURVE);
2871ff
    if (!TEST_true((len = i2d_ECPKParameters(group, &buf)) >= 0)
2871ff
        || !TEST_mem_eq(buf, len, p521_explicit, sizeof(p521_explicit)))
2871ff
        goto err;
2871ff
2871ff
    r = 1;
2871ff
err:
2871ff
    EC_GROUP_free(group);
2871ff
    EC_GROUP_free(group2);
2871ff
    ECPARAMETERS_free(ecparameters);
2871ff
    OPENSSL_free(buf);
2871ff
    return r;
2871ff
}
2871ff
2871ff
/*-
2871ff
 * random 256-bit explicit parameters curve, cofactor absent
2871ff
 * order:    0x0c38d96a9f892b88772ec2e39614a82f4f (132 bit)
2871ff
 * cofactor:   0x12bc94785251297abfafddf1565100da (125 bit)
2871ff
 */
2871ff
static const unsigned char params_cf_pass[] = {
2871ff
    0x30, 0x81, 0xcd, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86,
2871ff
    0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xe5, 0x00, 0x1f, 0xc5,
2871ff
    0xca, 0x71, 0x9d, 0x8e, 0xf7, 0x07, 0x4b, 0x48, 0x37, 0xf9, 0x33, 0x2d,
2871ff
    0x71, 0xbf, 0x79, 0xe7, 0xdc, 0x91, 0xc2, 0xff, 0xb6, 0x7b, 0xc3, 0x93,
2871ff
    0x44, 0x88, 0xe6, 0x91, 0x30, 0x44, 0x04, 0x20, 0xe5, 0x00, 0x1f, 0xc5,
2871ff
    0xca, 0x71, 0x9d, 0x8e, 0xf7, 0x07, 0x4b, 0x48, 0x37, 0xf9, 0x33, 0x2d,
2871ff
    0x71, 0xbf, 0x79, 0xe7, 0xdc, 0x91, 0xc2, 0xff, 0xb6, 0x7b, 0xc3, 0x93,
2871ff
    0x44, 0x88, 0xe6, 0x8e, 0x04, 0x20, 0x18, 0x8c, 0x59, 0x57, 0xc4, 0xbc,
2871ff
    0x85, 0x57, 0xc3, 0x66, 0x9f, 0x89, 0xd5, 0x92, 0x0d, 0x7e, 0x42, 0x27,
2871ff
    0x07, 0x64, 0xaa, 0x26, 0xed, 0x89, 0xc4, 0x09, 0x05, 0x4d, 0xc7, 0x23,
2871ff
    0x47, 0xda, 0x04, 0x41, 0x04, 0x1b, 0x6b, 0x41, 0x0b, 0xf9, 0xfb, 0x77,
2871ff
    0xfd, 0x50, 0xb7, 0x3e, 0x23, 0xa3, 0xec, 0x9a, 0x3b, 0x09, 0x31, 0x6b,
2871ff
    0xfa, 0xf6, 0xce, 0x1f, 0xff, 0xeb, 0x57, 0x93, 0x24, 0x70, 0xf3, 0xf4,
2871ff
    0xba, 0x7e, 0xfa, 0x86, 0x6e, 0x19, 0x89, 0xe3, 0x55, 0x6d, 0x5a, 0xe9,
2871ff
    0xc0, 0x3d, 0xbc, 0xfb, 0xaf, 0xad, 0xd4, 0x7e, 0xa6, 0xe5, 0xfa, 0x1a,
2871ff
    0x58, 0x07, 0x9e, 0x8f, 0x0d, 0x3b, 0xf7, 0x38, 0xca, 0x02, 0x11, 0x0c,
2871ff
    0x38, 0xd9, 0x6a, 0x9f, 0x89, 0x2b, 0x88, 0x77, 0x2e, 0xc2, 0xe3, 0x96,
2871ff
    0x14, 0xa8, 0x2f, 0x4f
2871ff
};
2871ff
2871ff
/*-
2871ff
 * random 256-bit explicit parameters curve, cofactor absent
2871ff
 * order:    0x045a75c0c17228ebd9b169a10e34a22101 (131 bit)
2871ff
 * cofactor:   0x2e134b4ede82649f67a2e559d361e5fe (126 bit)
2871ff
 */
2871ff
static const unsigned char params_cf_fail[] = {
2871ff
    0x30, 0x81, 0xcd, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86,
2871ff
    0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xc8, 0x95, 0x27, 0x37,
2871ff
    0xe8, 0xe1, 0xfd, 0xcc, 0xf9, 0x6e, 0x0c, 0xa6, 0x21, 0xc1, 0x7d, 0x6b,
2871ff
    0x9d, 0x44, 0x42, 0xea, 0x73, 0x4e, 0x04, 0xb6, 0xac, 0x62, 0x50, 0xd0,
2871ff
    0x33, 0xc2, 0xea, 0x13, 0x30, 0x44, 0x04, 0x20, 0xc8, 0x95, 0x27, 0x37,
2871ff
    0xe8, 0xe1, 0xfd, 0xcc, 0xf9, 0x6e, 0x0c, 0xa6, 0x21, 0xc1, 0x7d, 0x6b,
2871ff
    0x9d, 0x44, 0x42, 0xea, 0x73, 0x4e, 0x04, 0xb6, 0xac, 0x62, 0x50, 0xd0,
2871ff
    0x33, 0xc2, 0xea, 0x10, 0x04, 0x20, 0xbf, 0xa6, 0xa8, 0x05, 0x1d, 0x09,
2871ff
    0xac, 0x70, 0x39, 0xbb, 0x4d, 0xb2, 0x90, 0x8a, 0x15, 0x41, 0x14, 0x1d,
2871ff
    0x11, 0x86, 0x9f, 0x13, 0xa2, 0x63, 0x1a, 0xda, 0x95, 0x22, 0x4d, 0x02,
2871ff
    0x15, 0x0a, 0x04, 0x41, 0x04, 0xaf, 0x16, 0x71, 0xf9, 0xc4, 0xc8, 0x59,
2871ff
    0x1d, 0xa3, 0x6f, 0xe7, 0xc3, 0x57, 0xa1, 0xfa, 0x9f, 0x49, 0x7c, 0x11,
2871ff
    0x27, 0x05, 0xa0, 0x7f, 0xff, 0xf9, 0xe0, 0xe7, 0x92, 0xdd, 0x9c, 0x24,
2871ff
    0x8e, 0xc7, 0xb9, 0x52, 0x71, 0x3f, 0xbc, 0x7f, 0x6a, 0x9f, 0x35, 0x70,
2871ff
    0xe1, 0x27, 0xd5, 0x35, 0x8a, 0x13, 0xfa, 0xa8, 0x33, 0x3e, 0xd4, 0x73,
2871ff
    0x1c, 0x14, 0x58, 0x9e, 0xc7, 0x0a, 0x87, 0x65, 0x8d, 0x02, 0x11, 0x04,
2871ff
    0x5a, 0x75, 0xc0, 0xc1, 0x72, 0x28, 0xeb, 0xd9, 0xb1, 0x69, 0xa1, 0x0e,
2871ff
    0x34, 0xa2, 0x21, 0x01
2871ff
};
2871ff
2871ff
/*-
2871ff
 * Test two random 256-bit explicit parameters curves with absent cofactor.
2871ff
 * The two curves are chosen to roughly straddle the bounds at which the lib
2871ff
 * can compute the cofactor automatically, roughly 4*sqrt(p). So test that:
2871ff
 *
2871ff
 * - params_cf_pass: order is sufficiently close to p to compute cofactor
2871ff
 * - params_cf_fail: order is too far away from p to compute cofactor
2871ff
 *
2871ff
 * For standards-compliant curves, cofactor is chosen as small as possible.
2871ff
 * So you can see neither of these curves are fit for cryptographic use.
2871ff
 *
2871ff
 * Some standards even mandate an upper bound on the cofactor, e.g. SECG1 v2:
2871ff
 * h <= 2**(t/8) where t is the security level of the curve, for which the lib
2871ff
 * will always succeed in computing the cofactor. Neither of these curves
2871ff
 * conform to that -- this is just robustness testing.
2871ff
 */
2871ff
static int cofactor_range_test(void)
2871ff
{
2871ff
    EC_GROUP *group = NULL;
2871ff
    BIGNUM *cf = NULL;
2871ff
    int ret = 0;
2871ff
    const unsigned char *b1 = (const unsigned char *)params_cf_fail;
2871ff
    const unsigned char *b2 = (const unsigned char *)params_cf_pass;
2871ff
2871ff
    if (!TEST_ptr(group = d2i_ECPKParameters(NULL, &b1, sizeof(params_cf_fail)))
2871ff
        || !TEST_BN_eq_zero(EC_GROUP_get0_cofactor(group))
2871ff
        || !TEST_ptr(group = d2i_ECPKParameters(&group, &b2,
2871ff
                                                sizeof(params_cf_pass)))
2871ff
        || !TEST_int_gt(BN_hex2bn(&cf, "12bc94785251297abfafddf1565100da"), 0)
2871ff
        || !TEST_BN_eq(cf, EC_GROUP_get0_cofactor(group)))
2871ff
        goto err;
2871ff
    ret = 1;
2871ff
 err:
2871ff
    BN_free(cf);
2871ff
    EC_GROUP_free(group);
2871ff
    return ret;
2871ff
}
2871ff
2871ff
/*-
2871ff
 * For named curves, test that:
2871ff
 * - the lib correctly computes the cofactor if passed a NULL or zero cofactor
2871ff
 * - a nonsensical cofactor throws an error (negative test)
2871ff
 * - nonsensical orders throw errors (negative tests)
2871ff
 */
2871ff
static int cardinality_test(int n)
2871ff
{
2871ff
    int ret = 0, is_binary = 0;
2871ff
    int nid = curves[n].nid;
2871ff
    BN_CTX *ctx = NULL;
2871ff
    EC_GROUP *g1 = NULL, *g2 = NULL;
2871ff
    EC_POINT *g2_gen = NULL;
2871ff
    BIGNUM *g1_p = NULL, *g1_a = NULL, *g1_b = NULL, *g1_x = NULL, *g1_y = NULL,
2871ff
           *g1_order = NULL, *g1_cf = NULL, *g2_cf = NULL;
2871ff
2871ff
    TEST_info("Curve %s cardinality test", OBJ_nid2sn(nid));
2871ff
2871ff
    if (!TEST_ptr(ctx = BN_CTX_new())
2871ff
        || !TEST_ptr(g1 = EC_GROUP_new_by_curve_name(nid))) {
2871ff
        BN_CTX_free(ctx);
2871ff
        return 0;
2871ff
    }
2871ff
2871ff
    is_binary = (EC_GROUP_get_field_type(g1) == NID_X9_62_characteristic_two_field);
2871ff
2871ff
    BN_CTX_start(ctx);
2871ff
    g1_p = BN_CTX_get(ctx);
2871ff
    g1_a = BN_CTX_get(ctx);
2871ff
    g1_b = BN_CTX_get(ctx);
2871ff
    g1_x = BN_CTX_get(ctx);
2871ff
    g1_y = BN_CTX_get(ctx);
2871ff
    g1_order = BN_CTX_get(ctx);
2871ff
    g1_cf = BN_CTX_get(ctx);
2871ff
2871ff
    if (!TEST_ptr(g2_cf = BN_CTX_get(ctx))
2871ff
        /* pull out the explicit curve parameters */
2871ff
        || !TEST_true(EC_GROUP_get_curve(g1, g1_p, g1_a, g1_b, ctx))
2871ff
        || !TEST_true(EC_POINT_get_affine_coordinates(g1,
2871ff
                      EC_GROUP_get0_generator(g1), g1_x, g1_y, ctx))
2871ff
        || !TEST_true(BN_copy(g1_order, EC_GROUP_get0_order(g1)))
2871ff
        || !TEST_true(EC_GROUP_get_cofactor(g1, g1_cf, ctx))
2871ff
        /* construct g2 manually with g1 parameters */
2871ff
#ifndef OPENSSL_NO_EC2M
2871ff
        || !TEST_ptr(g2 = (is_binary) ?
2871ff
                           EC_GROUP_new_curve_GF2m(g1_p, g1_a, g1_b, ctx) :
2871ff
                           EC_GROUP_new_curve_GFp(g1_p, g1_a, g1_b, ctx))
2871ff
#else
2871ff
        || !TEST_int_eq(0, is_binary)
2871ff
        || !TEST_ptr(g2 = EC_GROUP_new_curve_GFp(g1_p, g1_a, g1_b, ctx))
2871ff
#endif
2871ff
        || !TEST_ptr(g2_gen = EC_POINT_new(g2))
2871ff
        || !TEST_true(EC_POINT_set_affine_coordinates(g2, g2_gen, g1_x, g1_y, ctx))
2871ff
        /* pass NULL cofactor: lib should compute it */
2871ff
        || !TEST_true(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL))
2871ff
        || !TEST_true(EC_GROUP_get_cofactor(g2, g2_cf, ctx))
2871ff
        || !TEST_BN_eq(g1_cf, g2_cf)
2871ff
        /* pass zero cofactor: lib should compute it */
2871ff
        || !TEST_true(BN_set_word(g2_cf, 0))
2871ff
        || !TEST_true(EC_GROUP_set_generator(g2, g2_gen, g1_order, g2_cf))
2871ff
        || !TEST_true(EC_GROUP_get_cofactor(g2, g2_cf, ctx))
2871ff
        || !TEST_BN_eq(g1_cf, g2_cf)
2871ff
        /* negative test for invalid cofactor */
2871ff
        || !TEST_true(BN_set_word(g2_cf, 0))
2871ff
        || !TEST_true(BN_sub(g2_cf, g2_cf, BN_value_one()))
2871ff
        || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, g1_order, g2_cf))
2871ff
        /* negative test for NULL order */
2871ff
        || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, NULL, NULL))
2871ff
        /* negative test for zero order */
2871ff
        || !TEST_true(BN_set_word(g1_order, 0))
2871ff
        || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL))
2871ff
        /* negative test for negative order */
2871ff
        || !TEST_true(BN_set_word(g2_cf, 0))
2871ff
        || !TEST_true(BN_sub(g2_cf, g2_cf, BN_value_one()))
2871ff
        || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL))
2871ff
        /* negative test for too large order */
2871ff
        || !TEST_true(BN_lshift(g1_order, g1_p, 2))
2871ff
        || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL)))
2871ff
        goto err;
2871ff
    ret = 1;
2871ff
 err:
2871ff
    EC_POINT_free(g2_gen);
2871ff
    EC_GROUP_free(g1);
2871ff
    EC_GROUP_free(g2);
2871ff
    BN_CTX_end(ctx);
2871ff
    BN_CTX_free(ctx);
2871ff
    return ret;
2871ff
}
2871ff
2871ff
static int check_ec_key_field_public_range_test(int id)
2871ff
{
2871ff
    int ret = 0, type = 0;
2871ff
    const EC_POINT *pub = NULL;
2871ff
    const EC_GROUP *group = NULL;
2871ff
    const BIGNUM *field = NULL;
2871ff
    BIGNUM *x = NULL, *y = NULL;
2871ff
    EC_KEY *key = NULL;
2871ff
2871ff
    if (!TEST_ptr(x = BN_new())
2871ff
            || !TEST_ptr(y = BN_new())
2871ff
            || !TEST_ptr(key = EC_KEY_new_by_curve_name(curves[id].nid))
2871ff
            || !TEST_ptr(group = EC_KEY_get0_group(key))
2871ff
            || !TEST_ptr(field = EC_GROUP_get0_field(group))
2871ff
            || !TEST_int_gt(EC_KEY_generate_key(key), 0)
2871ff
            || !TEST_int_gt(EC_KEY_check_key(key), 0)
2871ff
            || !TEST_ptr(pub = EC_KEY_get0_public_key(key))
2871ff
            || !TEST_int_gt(EC_POINT_get_affine_coordinates(group, pub, x, y,
2871ff
                                                            NULL), 0))
2871ff
        goto err;
2871ff
2871ff
    /*
2871ff
     * Make the public point out of range by adding the field (which will still
2871ff
     * be the same point on the curve). The add is different for char2 fields.
2871ff
     */
2871ff
    type = EC_GROUP_get_field_type(group);
2871ff
#ifndef OPENSSL_NO_EC2M
2871ff
    if (type == NID_X9_62_characteristic_two_field) {
2871ff
        /* test for binary curves */
2871ff
        if (!TEST_true(BN_GF2m_add(x, x, field)))
2871ff
            goto err;
2871ff
    } else
2871ff
#endif
2871ff
    if (type == NID_X9_62_prime_field) {
2871ff
        /* test for prime curves */
2871ff
        if (!TEST_true(BN_add(x, x, field)))
2871ff
            goto err;
2871ff
    } else {
2871ff
        /* this should never happen */
2871ff
        TEST_error("Unsupported EC_METHOD field_type");
2871ff
        goto err;
2871ff
    }
2871ff
    if (!TEST_int_le(EC_KEY_set_public_key_affine_coordinates(key, x, y), 0))
2871ff
        goto err;
2871ff
2871ff
    ret = 1;
2871ff
err:
2871ff
    BN_free(x);
2871ff
    BN_free(y);
2871ff
    EC_KEY_free(key);
2871ff
    return ret;
2871ff
}
2871ff
2871ff
/*
2871ff
 * Helper for ec_point_hex2point_test
2871ff
 *
2871ff
 * Self-tests EC_POINT_point2hex() against EC_POINT_hex2point() for the given
2871ff
 * (group,P) pair.
2871ff
 *
2871ff
 * If P is NULL use point at infinity.
2871ff
 */
2871ff
static ossl_inline
2871ff
int ec_point_hex2point_test_helper(const EC_GROUP *group, const EC_POINT *P,
2871ff
                                   point_conversion_form_t form,
2871ff
                                   BN_CTX *bnctx)
2871ff
{
2871ff
    int ret = 0;
2871ff
    EC_POINT *Q = NULL, *Pinf = NULL;
2871ff
    char *hex = NULL;
2871ff
2871ff
    if (P == NULL) {
2871ff
        /* If P is NULL use point at infinity. */
2871ff
        if (!TEST_ptr(Pinf = EC_POINT_new(group))
2871ff
                || !TEST_true(EC_POINT_set_to_infinity(group, Pinf)))
2871ff
            goto err;
2871ff
        P = Pinf;
2871ff
    }
2871ff
2871ff
    if (!TEST_ptr(hex = EC_POINT_point2hex(group, P, form, bnctx))
2871ff
            || !TEST_ptr(Q = EC_POINT_hex2point(group, hex, NULL, bnctx))
2871ff
            || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, bnctx)))
2871ff
        goto err;
2871ff
2871ff
    /*
2871ff
     * The next check is most likely superfluous, as EC_POINT_cmp should already
2871ff
     * cover this.
2871ff
     * Nonetheless it increases the test coverage for EC_POINT_is_at_infinity,
2871ff
     * so we include it anyway!
2871ff
     */
2871ff
    if (Pinf != NULL
2871ff
            && !TEST_true(EC_POINT_is_at_infinity(group, Q)))
2871ff
        goto err;
2871ff
2871ff
    ret = 1;
2871ff
2871ff
 err:
2871ff
    EC_POINT_free(Pinf);
2871ff
    OPENSSL_free(hex);
2871ff
    EC_POINT_free(Q);
2871ff
2871ff
    return ret;
2871ff
}
2871ff
2871ff
/*
2871ff
 * This test self-validates EC_POINT_hex2point() and EC_POINT_point2hex()
2871ff
 */
2871ff
static int ec_point_hex2point_test(int id)
2871ff
{
2871ff
    int ret = 0, nid;
2871ff
    EC_GROUP *group = NULL;
2871ff
    const EC_POINT *G = NULL;
2871ff
    EC_POINT *P = NULL;
2871ff
    BN_CTX * bnctx = NULL;
2871ff
2871ff
    /* Do some setup */
2871ff
    nid = curves[id].nid;
2871ff
    if (!TEST_ptr(bnctx = BN_CTX_new())
2871ff
            || !TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))
2871ff
            || !TEST_ptr(G = EC_GROUP_get0_generator(group))
2871ff
            || !TEST_ptr(P = EC_POINT_dup(G, group)))
2871ff
        goto err;
2871ff
2871ff
    if (!TEST_true(ec_point_hex2point_test_helper(group, P,
2871ff
                                                  POINT_CONVERSION_COMPRESSED,
2871ff
                                                  bnctx))
2871ff
            || !TEST_true(ec_point_hex2point_test_helper(group, NULL,
2871ff
                                                         POINT_CONVERSION_COMPRESSED,
2871ff
                                                         bnctx))
2871ff
            || !TEST_true(ec_point_hex2point_test_helper(group, P,
2871ff
                                                         POINT_CONVERSION_UNCOMPRESSED,
2871ff
                                                         bnctx))
2871ff
            || !TEST_true(ec_point_hex2point_test_helper(group, NULL,
2871ff
                                                         POINT_CONVERSION_UNCOMPRESSED,
2871ff
                                                         bnctx))
2871ff
            || !TEST_true(ec_point_hex2point_test_helper(group, P,
2871ff
                                                         POINT_CONVERSION_HYBRID,
2871ff
                                                         bnctx))
2871ff
            || !TEST_true(ec_point_hex2point_test_helper(group, NULL,
2871ff
                                                         POINT_CONVERSION_HYBRID,
2871ff
                                                         bnctx)))
2871ff
        goto err;
2871ff
2871ff
    ret = 1;
2871ff
2871ff
 err:
2871ff
    EC_POINT_free(P);
2871ff
    EC_GROUP_free(group);
2871ff
    BN_CTX_free(bnctx);
2871ff
2871ff
    return ret;
2871ff
}
2871ff
2871ff
static int do_test_custom_explicit_fromdata(EC_GROUP *group, BN_CTX *ctx,
2871ff
                                            unsigned char *gen, int gen_size)
2871ff
{
2871ff
    int ret = 0, i_out;
2871ff
    EVP_PKEY_CTX *pctx = NULL;
2871ff
    EVP_PKEY *pkeyparam = NULL;
2871ff
    OSSL_PARAM_BLD *bld = NULL;
2871ff
    const char *field_name;
2871ff
    OSSL_PARAM *params = NULL;
2871ff
    const OSSL_PARAM *gettable;
2871ff
    BIGNUM *p, *a, *b;
2871ff
    BIGNUM *p_out = NULL, *a_out = NULL, *b_out = NULL;
2871ff
    BIGNUM *order_out = NULL, *cofactor_out = NULL;
2871ff
    char name[80];
2871ff
    unsigned char buf[1024];
2871ff
    size_t buf_len, name_len;
2871ff
#ifndef OPENSSL_NO_EC2M
2871ff
    unsigned int k1 = 0, k2 = 0, k3 = 0;
2871ff
    const char *basis_name = NULL;
2871ff
#endif
2871ff
2871ff
    p = BN_CTX_get(ctx);
2871ff
    a = BN_CTX_get(ctx);
2871ff
    b = BN_CTX_get(ctx);
2871ff
2871ff
    if (!TEST_ptr(b)
2871ff
        || !TEST_ptr(bld = OSSL_PARAM_BLD_new()))
2871ff
        goto err;
2871ff
2871ff
    if (EC_GROUP_get_field_type(group) == NID_X9_62_prime_field) {
2871ff
        field_name = SN_X9_62_prime_field;
2871ff
    } else {
2871ff
        field_name = SN_X9_62_characteristic_two_field;
2871ff
#ifndef OPENSSL_NO_EC2M
2871ff
        if (EC_GROUP_get_basis_type(group) == NID_X9_62_tpBasis) {
2871ff
            basis_name = SN_X9_62_tpBasis;
2871ff
            if (!TEST_true(EC_GROUP_get_trinomial_basis(group, &k1)))
2871ff
                goto err;
2871ff
        } else {
2871ff
            basis_name = SN_X9_62_ppBasis;
2871ff
            if (!TEST_true(EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3)))
2871ff
                goto err;
2871ff
        }
2871ff
#endif /* OPENSSL_NO_EC2M */
2871ff
    }
2871ff
    if (!TEST_true(EC_GROUP_get_curve(group, p, a, b, ctx))
2871ff
        || !TEST_true(OSSL_PARAM_BLD_push_utf8_string(bld,
2871ff
                          OSSL_PKEY_PARAM_EC_FIELD_TYPE, field_name, 0))
2871ff
        || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_P, p))
2871ff
        || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_A, a))
2871ff
        || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_B, b)))
2871ff
        goto err;
2871ff
2871ff
    if (EC_GROUP_get0_seed(group) != NULL) {
2871ff
        if (!TEST_true(OSSL_PARAM_BLD_push_octet_string(bld,
2871ff
                           OSSL_PKEY_PARAM_EC_SEED, EC_GROUP_get0_seed(group),
2871ff
                           EC_GROUP_get_seed_len(group))))
2871ff
            goto err;
2871ff
    }
2871ff
    if (EC_GROUP_get0_cofactor(group) != NULL) {
2871ff
        if (!TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_COFACTOR,
2871ff
                                              EC_GROUP_get0_cofactor(group))))
2871ff
            goto err;
2871ff
    }
2871ff
2871ff
    if (!TEST_true(OSSL_PARAM_BLD_push_octet_string(bld,
2871ff
                       OSSL_PKEY_PARAM_EC_GENERATOR, gen, gen_size))
2871ff
        || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_ORDER,
2871ff
                                             EC_GROUP_get0_order(group))))
2871ff
        goto err;
2871ff
2871ff
    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
2871ff
        || !TEST_ptr(pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL))
2871ff
        || !TEST_int_gt(EVP_PKEY_fromdata_init(pctx), 0)
2871ff
        || !TEST_int_gt(EVP_PKEY_fromdata(pctx, &pkeyparam,
2871ff
                                          EVP_PKEY_KEY_PARAMETERS, params), 0))
2871ff
        goto err;
2871ff
2871ff
    /*- Check that all the set values are retrievable -*/
2871ff
2871ff
    /* There should be no match to a group name since the generator changed */
2871ff
    if (!TEST_false(EVP_PKEY_get_utf8_string_param(pkeyparam,
2871ff
                        OSSL_PKEY_PARAM_GROUP_NAME, name, sizeof(name),
2871ff
                        &name_len)))
2871ff
        goto err;
2871ff
2871ff
    /* The encoding should be explicit as it has no group */
2871ff
    if (!TEST_true(EVP_PKEY_get_utf8_string_param(pkeyparam,
2871ff
                       OSSL_PKEY_PARAM_EC_ENCODING,
2871ff
                       name, sizeof(name), &name_len))
2871ff
        || !TEST_str_eq(name, OSSL_PKEY_EC_ENCODING_EXPLICIT))
2871ff
        goto err;
2871ff
2871ff
    if (!TEST_true(EVP_PKEY_get_utf8_string_param(pkeyparam,
2871ff
                       OSSL_PKEY_PARAM_EC_FIELD_TYPE, name, sizeof(name),
2871ff
                       &name_len))
2871ff
        || !TEST_str_eq(name, field_name))
2871ff
        goto err;
2871ff
2871ff
    if (!TEST_true(EVP_PKEY_get_octet_string_param(pkeyparam,
2871ff
                       OSSL_PKEY_PARAM_EC_GENERATOR, buf, sizeof(buf), &buf_len))
2871ff
        || !TEST_mem_eq(buf, (int)buf_len, gen, gen_size))
2871ff
        goto err;
2871ff
2871ff
    if (!TEST_true(EVP_PKEY_get_bn_param(pkeyparam, OSSL_PKEY_PARAM_EC_P, &p_out))
2871ff
        || !TEST_BN_eq(p_out, p)
2871ff
        || !TEST_true(EVP_PKEY_get_bn_param(pkeyparam, OSSL_PKEY_PARAM_EC_A,
2871ff
                                            &a_out))
2871ff
        || !TEST_BN_eq(a_out, a)
2871ff
        || !TEST_true(EVP_PKEY_get_bn_param(pkeyparam, OSSL_PKEY_PARAM_EC_B,
2871ff
                                            &b_out))
2871ff
        || !TEST_BN_eq(b_out, b)
2871ff
        || !TEST_true(EVP_PKEY_get_bn_param(pkeyparam, OSSL_PKEY_PARAM_EC_ORDER,
2871ff
                                            &order_out))
2871ff
        || !TEST_BN_eq(order_out, EC_GROUP_get0_order(group)))
2871ff
        goto err;
2871ff
2871ff
    if (EC_GROUP_get0_cofactor(group) != NULL) {
2871ff
        if (!TEST_true(EVP_PKEY_get_bn_param(pkeyparam,
2871ff
                           OSSL_PKEY_PARAM_EC_COFACTOR, &cofactor_out))
2871ff
            || !TEST_BN_eq(cofactor_out, EC_GROUP_get0_cofactor(group)))
2871ff
            goto err;
2871ff
    }
2871ff
    if (EC_GROUP_get0_seed(group) != NULL) {
2871ff
        if (!TEST_true(EVP_PKEY_get_octet_string_param(pkeyparam,
2871ff
                           OSSL_PKEY_PARAM_EC_SEED, buf, sizeof(buf), &buf_len))
2871ff
            || !TEST_mem_eq(buf, buf_len, EC_GROUP_get0_seed(group),
2871ff
                            EC_GROUP_get_seed_len(group)))
2871ff
            goto err;
2871ff
    }
2871ff
2871ff
    if (EC_GROUP_get_field_type(group) == NID_X9_62_prime_field) {
2871ff
        /* No extra fields should be set for a prime field */
2871ff
        if (!TEST_false(EVP_PKEY_get_int_param(pkeyparam,
2871ff
                            OSSL_PKEY_PARAM_EC_CHAR2_M, &i_out))
2871ff
            || !TEST_false(EVP_PKEY_get_int_param(pkeyparam,
2871ff
                               OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS, &i_out))
2871ff
            || !TEST_false(EVP_PKEY_get_int_param(pkeyparam,
2871ff
                               OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, &i_out))
2871ff
            || !TEST_false(EVP_PKEY_get_int_param(pkeyparam,
2871ff
                               OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, &i_out))
2871ff
            || !TEST_false(EVP_PKEY_get_int_param(pkeyparam,
2871ff
                               OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, &i_out))
2871ff
            || !TEST_false(EVP_PKEY_get_utf8_string_param(pkeyparam,
2871ff
                               OSSL_PKEY_PARAM_EC_CHAR2_TYPE, name, sizeof(name),
2871ff
                               &name_len)))
2871ff
            goto err;
2871ff
    } else {
2871ff
#ifndef OPENSSL_NO_EC2M
2871ff
        if (!TEST_true(EVP_PKEY_get_int_param(pkeyparam,
2871ff
                           OSSL_PKEY_PARAM_EC_CHAR2_M, &i_out))
2871ff
            || !TEST_int_eq(EC_GROUP_get_degree(group), i_out)
2871ff
            || !TEST_true(EVP_PKEY_get_utf8_string_param(pkeyparam,
2871ff
                              OSSL_PKEY_PARAM_EC_CHAR2_TYPE, name, sizeof(name),
2871ff
                              &name_len))
2871ff
            || !TEST_str_eq(name, basis_name))
2871ff
            goto err;
2871ff
2871ff
        if (EC_GROUP_get_basis_type(group) == NID_X9_62_tpBasis) {
2871ff
            if (!TEST_true(EVP_PKEY_get_int_param(pkeyparam,
2871ff
                               OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS, &i_out))
2871ff
                || !TEST_int_eq(k1, i_out)
2871ff
                || !TEST_false(EVP_PKEY_get_int_param(pkeyparam,
2871ff
                                   OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, &i_out))
2871ff
                || !TEST_false(EVP_PKEY_get_int_param(pkeyparam,
2871ff
                                   OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, &i_out))
2871ff
                || !TEST_false(EVP_PKEY_get_int_param(pkeyparam,
2871ff
                                   OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, &i_out)))
2871ff
                goto err;
2871ff
        } else {
2871ff
            if (!TEST_false(EVP_PKEY_get_int_param(pkeyparam,
2871ff
                                OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS, &i_out))
2871ff
                || !TEST_true(EVP_PKEY_get_int_param(pkeyparam,
2871ff
                                  OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, &i_out))
2871ff
                || !TEST_int_eq(k1, i_out)
2871ff
                || !TEST_true(EVP_PKEY_get_int_param(pkeyparam,
2871ff
                                  OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, &i_out))
2871ff
                || !TEST_int_eq(k2, i_out)
2871ff
                || !TEST_true(EVP_PKEY_get_int_param(pkeyparam,
2871ff
                                  OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, &i_out))
2871ff
                || !TEST_int_eq(k3, i_out))
2871ff
                goto err;
2871ff
        }
2871ff
#endif /* OPENSSL_NO_EC2M */
2871ff
    }
2871ff
    if (!TEST_ptr(gettable = EVP_PKEY_gettable_params(pkeyparam))
2871ff
        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_GROUP_NAME))
2871ff
        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_ENCODING))
2871ff
        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_FIELD_TYPE))
2871ff
        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_P))
2871ff
        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_A))
2871ff
        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_B))
2871ff
        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_GENERATOR))
2871ff
        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_ORDER))
2871ff
        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_COFACTOR))
2871ff
        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_SEED))
2871ff
#ifndef OPENSSL_NO_EC2M
2871ff
        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_CHAR2_M))
2871ff
        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_CHAR2_TYPE))
2871ff
        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS))
2871ff
        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_CHAR2_PP_K1))
2871ff
        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_CHAR2_PP_K2))
2871ff
        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_CHAR2_PP_K3))
2871ff
#endif
2871ff
        )
2871ff
        goto err;
2871ff
    ret = 1;
2871ff
err:
2871ff
    BN_free(order_out);
2871ff
    BN_free(cofactor_out);
2871ff
    BN_free(a_out);
2871ff
    BN_free(b_out);
2871ff
    BN_free(p_out);
2871ff
    OSSL_PARAM_free(params);
2871ff
    OSSL_PARAM_BLD_free(bld);
2871ff
    EVP_PKEY_free(pkeyparam);
2871ff
    EVP_PKEY_CTX_free(pctx);
2871ff
    return ret;
2871ff
}
2871ff
2871ff
/*
2871ff
 * check the EC_METHOD respects the supplied EC_GROUP_set_generator G
2871ff
 */
2871ff
static int custom_generator_test(int id)
2871ff
{
2871ff
    int ret = 0, nid, bsize;
2871ff
    EC_GROUP *group = NULL;
2871ff
    EC_POINT *G2 = NULL, *Q1 = NULL, *Q2 = NULL;
2871ff
    BN_CTX *ctx = NULL;
2871ff
    BIGNUM *k = NULL;
2871ff
    unsigned char *b1 = NULL, *b2 = NULL;
2871ff
2871ff
    /* Do some setup */
2871ff
    nid = curves[id].nid;
2871ff
    TEST_note("Curve %s", OBJ_nid2sn(nid));
2871ff
    if (!TEST_ptr(ctx = BN_CTX_new()))
2871ff
        return 0;
2871ff
2871ff
    BN_CTX_start(ctx);
2871ff
2871ff
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(nid)))
2871ff
        goto err;
2871ff
2871ff
    /* expected byte length of encoded points */
2871ff
    bsize = (EC_GROUP_get_degree(group) + 7) / 8;
2871ff
    bsize = 1 + 2 * bsize; /* UNCOMPRESSED_POINT format */
2871ff
2871ff
    if (!TEST_ptr(k = BN_CTX_get(ctx))
2871ff
        /* fetch a testing scalar k != 0,1 */
2871ff
        || !TEST_true(BN_rand(k, EC_GROUP_order_bits(group) - 1,
2871ff
                              BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
2871ff
        /* make k even */
2871ff
        || !TEST_true(BN_clear_bit(k, 0))
2871ff
        || !TEST_ptr(G2 = EC_POINT_new(group))
2871ff
        || !TEST_ptr(Q1 = EC_POINT_new(group))
2871ff
        /* Q1 := kG */
2871ff
        || !TEST_true(EC_POINT_mul(group, Q1, k, NULL, NULL, ctx))
2871ff
        /* pull out the bytes of that */
2871ff
        || !TEST_int_eq(EC_POINT_point2oct(group, Q1,
2871ff
                                           POINT_CONVERSION_UNCOMPRESSED, NULL,
2871ff
                                           0, ctx), bsize)
2871ff
        || !TEST_ptr(b1 = OPENSSL_malloc(bsize))
2871ff
        || !TEST_int_eq(EC_POINT_point2oct(group, Q1,
2871ff
                                           POINT_CONVERSION_UNCOMPRESSED, b1,
2871ff
                                           bsize, ctx), bsize)
2871ff
        /* new generator is G2 := 2G */
2871ff
        || !TEST_true(EC_POINT_dbl(group, G2, EC_GROUP_get0_generator(group),
2871ff
                                   ctx))
2871ff
        || !TEST_true(EC_GROUP_set_generator(group, G2,
2871ff
                                             EC_GROUP_get0_order(group),
2871ff
                                             EC_GROUP_get0_cofactor(group)))
2871ff
        || !TEST_ptr(Q2 = EC_POINT_new(group))
2871ff
        || !TEST_true(BN_rshift1(k, k))
2871ff
        /* Q2 := k/2 G2 */
2871ff
        || !TEST_true(EC_POINT_mul(group, Q2, k, NULL, NULL, ctx))
2871ff
        || !TEST_int_eq(EC_POINT_point2oct(group, Q2,
2871ff
                                           POINT_CONVERSION_UNCOMPRESSED, NULL,
2871ff
                                           0, ctx), bsize)
2871ff
        || !TEST_ptr(b2 = OPENSSL_malloc(bsize))
2871ff
        || !TEST_int_eq(EC_POINT_point2oct(group, Q2,
2871ff
                                           POINT_CONVERSION_UNCOMPRESSED, b2,
2871ff
                                           bsize, ctx), bsize)
2871ff
        /* Q1 = kG = k/2 G2 = Q2 should hold */
2871ff
        || !TEST_mem_eq(b1, bsize, b2, bsize))
2871ff
        goto err;
2871ff
2871ff
    if (!do_test_custom_explicit_fromdata(group, ctx, b1, bsize))
2871ff
        goto err;
2871ff
2871ff
    ret = 1;
2871ff
2871ff
 err:
2871ff
    EC_POINT_free(Q1);
2871ff
    EC_POINT_free(Q2);
2871ff
    EC_POINT_free(G2);
2871ff
    EC_GROUP_free(group);
2871ff
    BN_CTX_end(ctx);
2871ff
    BN_CTX_free(ctx);
2871ff
    OPENSSL_free(b1);
2871ff
    OPENSSL_free(b2);
2871ff
2871ff
    return ret;
2871ff
}
2871ff
2871ff
/*
2871ff
 * check creation of curves from explicit params through the public API
2871ff
 */
2871ff
static int custom_params_test(int id)
2871ff
{
2871ff
    int ret = 0, nid, bsize;
2871ff
    const char *curve_name = NULL;
2871ff
    EC_GROUP *group = NULL, *altgroup = NULL;
2871ff
    EC_POINT *G2 = NULL, *Q1 = NULL, *Q2 = NULL;
2871ff
    const EC_POINT *Q = NULL;
2871ff
    BN_CTX *ctx = NULL;
2871ff
    BIGNUM *k = NULL;
2871ff
    unsigned char *buf1 = NULL, *buf2 = NULL;
2871ff
    const BIGNUM *z = NULL, *cof = NULL, *priv1 = NULL;
2871ff
    BIGNUM *p = NULL, *a = NULL, *b = NULL;
2871ff
    int is_prime = 0;
2871ff
    EC_KEY *eckey1 = NULL, *eckey2 = NULL;
2871ff
    EVP_PKEY *pkey1 = NULL, *pkey2 = NULL;
2871ff
    EVP_PKEY_CTX *pctx1 = NULL, *pctx2 = NULL;
2871ff
    size_t sslen, t;
2871ff
    unsigned char *pub1 = NULL , *pub2 = NULL;
2871ff
    OSSL_PARAM_BLD *param_bld = NULL;
2871ff
    OSSL_PARAM *params1 = NULL, *params2 = NULL;
2871ff
2871ff
    /* Do some setup */
2871ff
    nid = curves[id].nid;
2871ff
    curve_name = OBJ_nid2sn(nid);
2871ff
    TEST_note("Curve %s", curve_name);
2871ff
2871ff
    if (nid == NID_sm2)
2871ff
        return TEST_skip("custom params not supported with SM2");
2871ff
2871ff
    if (!TEST_ptr(ctx = BN_CTX_new()))
2871ff
        return 0;
2871ff
2871ff
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(nid)))
2871ff
        goto err;
2871ff
2871ff
    is_prime = EC_GROUP_get_field_type(group) == NID_X9_62_prime_field;
2871ff
#ifdef OPENSSL_NO_EC2M
2871ff
    if (!is_prime) {
2871ff
        ret = TEST_skip("binary curves not supported in this build");
2871ff
        goto err;
2871ff
    }
2871ff
#endif
2871ff
2871ff
    BN_CTX_start(ctx);
2871ff
    if (!TEST_ptr(p = BN_CTX_get(ctx))
2871ff
            || !TEST_ptr(a = BN_CTX_get(ctx))
2871ff
            || !TEST_ptr(b = BN_CTX_get(ctx))
2871ff
            || !TEST_ptr(k = BN_CTX_get(ctx)))
2871ff
        goto err;
2871ff
2871ff
    /* expected byte length of encoded points */
2871ff
    bsize = (EC_GROUP_get_degree(group) + 7) / 8;
2871ff
    bsize = 1 + 2 * bsize; /* UNCOMPRESSED_POINT format */
2871ff
2871ff
    /* extract parameters from built-in curve */
2871ff
    if (!TEST_true(EC_GROUP_get_curve(group, p, a, b, ctx))
2871ff
            || !TEST_ptr(G2 = EC_POINT_new(group))
2871ff
            /* new generator is G2 := 2G */
2871ff
            || !TEST_true(EC_POINT_dbl(group, G2,
2871ff
                                       EC_GROUP_get0_generator(group), ctx))
2871ff
            /* pull out the bytes of that */
2871ff
            || !TEST_int_eq(EC_POINT_point2oct(group, G2,
2871ff
                                               POINT_CONVERSION_UNCOMPRESSED,
2871ff
                                               NULL, 0, ctx), bsize)
2871ff
            || !TEST_ptr(buf1 = OPENSSL_malloc(bsize))
2871ff
            || !TEST_int_eq(EC_POINT_point2oct(group, G2,
2871ff
                                               POINT_CONVERSION_UNCOMPRESSED,
2871ff
                                               buf1, bsize, ctx), bsize)
2871ff
            || !TEST_ptr(z = EC_GROUP_get0_order(group))
2871ff
            || !TEST_ptr(cof = EC_GROUP_get0_cofactor(group))
2871ff
        )
2871ff
        goto err;
2871ff
2871ff
    /* create a new group using same params (but different generator) */
2871ff
    if (is_prime) {
2871ff
        if (!TEST_ptr(altgroup = EC_GROUP_new_curve_GFp(p, a, b, ctx)))
2871ff
            goto err;
2871ff
    }
2871ff
#ifndef OPENSSL_NO_EC2M
2871ff
    else {
2871ff
        if (!TEST_ptr(altgroup = EC_GROUP_new_curve_GF2m(p, a, b, ctx)))
2871ff
            goto err;
2871ff
    }
2871ff
#endif
2871ff
2871ff
    /* set 2*G as the generator of altgroup */
2871ff
    EC_POINT_free(G2); /* discard G2 as it refers to the original group */
2871ff
    if (!TEST_ptr(G2 = EC_POINT_new(altgroup))
2871ff
            || !TEST_true(EC_POINT_oct2point(altgroup, G2, buf1, bsize, ctx))
2871ff
            || !TEST_int_eq(EC_POINT_is_on_curve(altgroup, G2, ctx), 1)
2871ff
            || !TEST_true(EC_GROUP_set_generator(altgroup, G2, z, cof))
2871ff
       )
2871ff
        goto err;
2871ff
2871ff
    /* verify math checks out */
2871ff
    if (/* allocate temporary points on group and altgroup */
2871ff
            !TEST_ptr(Q1 = EC_POINT_new(group))
2871ff
            || !TEST_ptr(Q2 = EC_POINT_new(altgroup))
2871ff
            /* fetch a testing scalar k != 0,1 */
2871ff
            || !TEST_true(BN_rand(k, EC_GROUP_order_bits(group) - 1,
2871ff
                                  BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
2871ff
            /* make k even */
2871ff
            || !TEST_true(BN_clear_bit(k, 0))
2871ff
            /* Q1 := kG on group */
2871ff
            || !TEST_true(EC_POINT_mul(group, Q1, k, NULL, NULL, ctx))
2871ff
            /* pull out the bytes of that */
2871ff
            || !TEST_int_eq(EC_POINT_point2oct(group, Q1,
2871ff
                                               POINT_CONVERSION_UNCOMPRESSED,
2871ff
                                               NULL, 0, ctx), bsize)
2871ff
            || !TEST_int_eq(EC_POINT_point2oct(group, Q1,
2871ff
                                               POINT_CONVERSION_UNCOMPRESSED,
2871ff
                                               buf1, bsize, ctx), bsize)
2871ff
            /* k := k/2 */
2871ff
            || !TEST_true(BN_rshift1(k, k))
2871ff
            /* Q2 := k/2 G2 on altgroup */
2871ff
            || !TEST_true(EC_POINT_mul(altgroup, Q2, k, NULL, NULL, ctx))
2871ff
            /* pull out the bytes of that */
2871ff
            || !TEST_int_eq(EC_POINT_point2oct(altgroup, Q2,
2871ff
                                               POINT_CONVERSION_UNCOMPRESSED,
2871ff
                                               NULL, 0, ctx), bsize)
2871ff
            || !TEST_ptr(buf2 = OPENSSL_malloc(bsize))
2871ff
            || !TEST_int_eq(EC_POINT_point2oct(altgroup, Q2,
2871ff
                                               POINT_CONVERSION_UNCOMPRESSED,
2871ff
                                               buf2, bsize, ctx), bsize)
2871ff
            /* Q1 = kG = k/2 G2 = Q2 should hold */
2871ff
            || !TEST_mem_eq(buf1, bsize, buf2, bsize))
2871ff
        goto err;
2871ff
2871ff
    /* create two `EC_KEY`s on altgroup */
2871ff
    if (!TEST_ptr(eckey1 = EC_KEY_new())
2871ff
            || !TEST_true(EC_KEY_set_group(eckey1, altgroup))
2871ff
            || !TEST_true(EC_KEY_generate_key(eckey1))
2871ff
            || !TEST_ptr(eckey2 = EC_KEY_new())
2871ff
            || !TEST_true(EC_KEY_set_group(eckey2, altgroup))
2871ff
            || !TEST_true(EC_KEY_generate_key(eckey2)))
2871ff
        goto err;
2871ff
2871ff
    /* retrieve priv1 for later */
2871ff
    if (!TEST_ptr(priv1 = EC_KEY_get0_private_key(eckey1)))
2871ff
        goto err;
2871ff
2871ff
    /*
2871ff
     * retrieve bytes for pub1 for later
2871ff
     *
2871ff
     * We compute the pub key in the original group as we will later use it to
2871ff
     * define a provider key in the built-in group.
2871ff
     */
2871ff
    if (!TEST_true(EC_POINT_mul(group, Q1, priv1, NULL, NULL, ctx))
2871ff
            || !TEST_int_eq(EC_POINT_point2oct(group, Q1,
2871ff
                                               POINT_CONVERSION_UNCOMPRESSED,
2871ff
                                               NULL, 0, ctx), bsize)
2871ff
            || !TEST_ptr(pub1 = OPENSSL_malloc(bsize))
2871ff
            || !TEST_int_eq(EC_POINT_point2oct(group, Q1,
2871ff
                                               POINT_CONVERSION_UNCOMPRESSED,
2871ff
                                               pub1, bsize, ctx), bsize))
2871ff
        goto err;
2871ff
2871ff
    /* retrieve bytes for pub2 for later */
2871ff
    if (!TEST_ptr(Q = EC_KEY_get0_public_key(eckey2))
2871ff
            || !TEST_int_eq(EC_POINT_point2oct(altgroup, Q,
2871ff
                                               POINT_CONVERSION_UNCOMPRESSED,
2871ff
                                               NULL, 0, ctx), bsize)
2871ff
            || !TEST_ptr(pub2 = OPENSSL_malloc(bsize))
2871ff
            || !TEST_int_eq(EC_POINT_point2oct(altgroup, Q,
2871ff
                                               POINT_CONVERSION_UNCOMPRESSED,
2871ff
                                               pub2, bsize, ctx), bsize))
2871ff
        goto err;
2871ff
2871ff
    /* create two `EVP_PKEY`s from the `EC_KEY`s */
2871ff
    if(!TEST_ptr(pkey1 = EVP_PKEY_new())
2871ff
            || !TEST_int_eq(EVP_PKEY_assign_EC_KEY(pkey1, eckey1), 1))
2871ff
        goto err;
2871ff
    eckey1 = NULL; /* ownership passed to pkey1 */
2871ff
    if(!TEST_ptr(pkey2 = EVP_PKEY_new())
2871ff
            || !TEST_int_eq(EVP_PKEY_assign_EC_KEY(pkey2, eckey2), 1))
2871ff
        goto err;
2871ff
    eckey2 = NULL; /* ownership passed to pkey2 */
2871ff
2871ff
    /* Compute keyexchange in both directions */
2871ff
    if (!TEST_ptr(pctx1 = EVP_PKEY_CTX_new(pkey1, NULL))
2871ff
            || !TEST_int_eq(EVP_PKEY_derive_init(pctx1), 1)
2871ff
            || !TEST_int_eq(EVP_PKEY_derive_set_peer(pctx1, pkey2), 1)
2871ff
            || !TEST_int_eq(EVP_PKEY_derive(pctx1, NULL, &sslen), 1)
2871ff
            || !TEST_int_gt(bsize, sslen)
2871ff
            || !TEST_int_eq(EVP_PKEY_derive(pctx1, buf1, &sslen), 1))
2871ff
        goto err;
2871ff
    if (!TEST_ptr(pctx2 = EVP_PKEY_CTX_new(pkey2, NULL))
2871ff
            || !TEST_int_eq(EVP_PKEY_derive_init(pctx2), 1)
2871ff
            || !TEST_int_eq(EVP_PKEY_derive_set_peer(pctx2, pkey1), 1)
2871ff
            || !TEST_int_eq(EVP_PKEY_derive(pctx2, NULL, &t), 1)
2871ff
            || !TEST_int_gt(bsize, t)
2871ff
            || !TEST_int_le(sslen, t)
2871ff
            || !TEST_int_eq(EVP_PKEY_derive(pctx2, buf2, &t), 1))
2871ff
        goto err;
2871ff
2871ff
    /* Both sides should expect the same shared secret */
2871ff
    if (!TEST_mem_eq(buf1, sslen, buf2, t))
2871ff
        goto err;
2871ff
2871ff
    /* Build parameters for provider-native keys */
2871ff
    if (!TEST_ptr(param_bld = OSSL_PARAM_BLD_new())
2871ff
            || !TEST_true(OSSL_PARAM_BLD_push_utf8_string(param_bld,
2871ff
                                                          OSSL_PKEY_PARAM_GROUP_NAME,
2871ff
                                                          curve_name, 0))
2871ff
            || !TEST_true(OSSL_PARAM_BLD_push_octet_string(param_bld,
2871ff
                                                           OSSL_PKEY_PARAM_PUB_KEY,
2871ff
                                                           pub1, bsize))
2871ff
            || !TEST_true(OSSL_PARAM_BLD_push_BN(param_bld,
2871ff
                                                 OSSL_PKEY_PARAM_PRIV_KEY,
2871ff
                                                 priv1))
2871ff
            || !TEST_ptr(params1 = OSSL_PARAM_BLD_to_param(param_bld)))
2871ff
        goto err;
2871ff
2871ff
    OSSL_PARAM_BLD_free(param_bld);
2871ff
    if (!TEST_ptr(param_bld = OSSL_PARAM_BLD_new())
2871ff
            || !TEST_true(OSSL_PARAM_BLD_push_utf8_string(param_bld,
2871ff
                                                          OSSL_PKEY_PARAM_GROUP_NAME,
2871ff
                                                          curve_name, 0))
2871ff
            || !TEST_true(OSSL_PARAM_BLD_push_octet_string(param_bld,
2871ff
                                                           OSSL_PKEY_PARAM_PUB_KEY,
2871ff
                                                           pub2, bsize))
2871ff
            || !TEST_ptr(params2 = OSSL_PARAM_BLD_to_param(param_bld)))
2871ff
        goto err;
2871ff
2871ff
    /* create two new provider-native `EVP_PKEY`s */
2871ff
    EVP_PKEY_CTX_free(pctx2);
2871ff
    if (!TEST_ptr(pctx2 = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL))
2871ff
            || !TEST_true(EVP_PKEY_fromdata_init(pctx2))
2871ff
            || !TEST_true(EVP_PKEY_fromdata(pctx2, &pkey1, EVP_PKEY_KEYPAIR,
2871ff
                                            params1))
2871ff
            || !TEST_true(EVP_PKEY_fromdata(pctx2, &pkey2, EVP_PKEY_PUBLIC_KEY,
2871ff
                                            params2)))
2871ff
        goto err;
2871ff
2871ff
    /* compute keyexchange once more using the provider keys */
2871ff
    EVP_PKEY_CTX_free(pctx1);
2871ff
    if (!TEST_ptr(pctx1 = EVP_PKEY_CTX_new(pkey1, NULL))
2871ff
            || !TEST_int_eq(EVP_PKEY_derive_init(pctx1), 1)
2871ff
            || !TEST_int_eq(EVP_PKEY_derive_set_peer(pctx1, pkey2), 1)
2871ff
            || !TEST_int_eq(EVP_PKEY_derive(pctx1, NULL, &t), 1)
2871ff
            || !TEST_int_gt(bsize, t)
2871ff
            || !TEST_int_le(sslen, t)
2871ff
            || !TEST_int_eq(EVP_PKEY_derive(pctx1, buf1, &t), 1)
2871ff
            /* compare with previous result */
2871ff
            || !TEST_mem_eq(buf1, t, buf2, sslen))
2871ff
        goto err;
2871ff
2871ff
    ret = 1;
2871ff
2871ff
 err:
2871ff
    BN_CTX_end(ctx);
2871ff
    BN_CTX_free(ctx);
2871ff
    OSSL_PARAM_BLD_free(param_bld);
2871ff
    OSSL_PARAM_free(params1);
2871ff
    OSSL_PARAM_free(params2);
2871ff
    EC_POINT_free(Q1);
2871ff
    EC_POINT_free(Q2);
2871ff
    EC_POINT_free(G2);
2871ff
    EC_GROUP_free(group);
2871ff
    EC_GROUP_free(altgroup);
2871ff
    OPENSSL_free(buf1);
2871ff
    OPENSSL_free(buf2);
2871ff
    OPENSSL_free(pub1);
2871ff
    OPENSSL_free(pub2);
2871ff
    EC_KEY_free(eckey1);
2871ff
    EC_KEY_free(eckey2);
2871ff
    EVP_PKEY_free(pkey1);
2871ff
    EVP_PKEY_free(pkey2);
2871ff
    EVP_PKEY_CTX_free(pctx1);
2871ff
    EVP_PKEY_CTX_free(pctx2);
2871ff
2871ff
    return ret;
2871ff
}
2871ff
2871ff
int setup_tests(void)
2871ff
{
2871ff
    crv_len = EC_get_builtin_curves(NULL, 0);
2871ff
    if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len))
2871ff
        || !TEST_true(EC_get_builtin_curves(curves, crv_len)))
2871ff
        return 0;
2871ff
2871ff
    ADD_TEST(parameter_test);
2871ff
    ADD_TEST(cofactor_range_test);
2871ff
    ADD_ALL_TESTS(cardinality_test, crv_len);
2871ff
    ADD_TEST(prime_field_tests);
2871ff
#ifndef OPENSSL_NO_EC2M
2871ff
    ADD_TEST(char2_field_tests);
2871ff
    ADD_ALL_TESTS(char2_curve_test, OSSL_NELEM(char2_curve_tests));
2871ff
#endif
2871ff
    ADD_ALL_TESTS(nistp_single_test, OSSL_NELEM(nistp_tests_params));
2871ff
    ADD_ALL_TESTS(internal_curve_test, crv_len);
2871ff
    ADD_ALL_TESTS(internal_curve_test_method, crv_len);
2871ff
    ADD_TEST(group_field_test);
2871ff
    ADD_ALL_TESTS(check_named_curve_test, crv_len);
2871ff
    ADD_ALL_TESTS(check_named_curve_lookup_test, crv_len);
2871ff
    ADD_ALL_TESTS(check_ec_key_field_public_range_test, crv_len);
2871ff
    ADD_ALL_TESTS(check_named_curve_from_ecparameters, crv_len);
2871ff
    ADD_ALL_TESTS(ec_point_hex2point_test, crv_len);
2871ff
    ADD_ALL_TESTS(custom_generator_test, crv_len);
2871ff
    ADD_ALL_TESTS(custom_params_test, crv_len);
2871ff
    return 1;
2871ff
}
2871ff
2871ff
void cleanup_tests(void)
2871ff
{
2871ff
    OPENSSL_free(curves);
2871ff
}