Blame SOURCES/ectest.c

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