Blame SOURCES/ectest.c

0bf02d
/*
0bf02d
 * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
0bf02d
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
0bf02d
 *
0bf02d
 * Licensed under the OpenSSL license (the "License").  You may not use
0bf02d
 * this file except in compliance with the License.  You can obtain a copy
0bf02d
 * in the file LICENSE in the source distribution or at
0bf02d
 * https://www.openssl.org/source/license.html
0bf02d
 */
0bf02d
0bf02d
#include "internal/nelem.h"
0bf02d
#include "testutil.h"
0bf02d
0bf02d
#ifndef OPENSSL_NO_EC
0bf02d
# include <openssl/ec.h>
0bf02d
# ifndef OPENSSL_NO_ENGINE
0bf02d
#  include <openssl/engine.h>
0bf02d
# endif
0bf02d
# include <openssl/err.h>
0bf02d
# include <openssl/obj_mac.h>
0bf02d
# include <openssl/objects.h>
0bf02d
# include <openssl/rand.h>
0bf02d
# include <openssl/bn.h>
0bf02d
# include <openssl/opensslconf.h>
0bf02d
0bf02d
static size_t crv_len = 0;
0bf02d
static EC_builtin_curve *curves = NULL;
0bf02d
0bf02d
/* test multiplication with group order, long and negative scalars */
0bf02d
static int group_order_tests(EC_GROUP *group)
0bf02d
{
0bf02d
    BIGNUM *n1 = NULL, *n2 = NULL, *order = NULL;
0bf02d
    EC_POINT *P = NULL, *Q = NULL, *R = NULL, *S = NULL;
0bf02d
    const EC_POINT *G = NULL;
0bf02d
    BN_CTX *ctx = NULL;
0bf02d
    int i = 0, r = 0;
0bf02d
0bf02d
    if (!TEST_ptr(n1 = BN_new())
0bf02d
        || !TEST_ptr(n2 = BN_new())
0bf02d
        || !TEST_ptr(order = BN_new())
0bf02d
        || !TEST_ptr(ctx = BN_CTX_new())
0bf02d
        || !TEST_ptr(G = EC_GROUP_get0_generator(group))
0bf02d
        || !TEST_ptr(P = EC_POINT_new(group))
0bf02d
        || !TEST_ptr(Q = EC_POINT_new(group))
0bf02d
        || !TEST_ptr(R = EC_POINT_new(group))
0bf02d
        || !TEST_ptr(S = EC_POINT_new(group)))
0bf02d
        goto err;
0bf02d
0bf02d
    if (!TEST_true(EC_GROUP_get_order(group, order, ctx))
0bf02d
        || !TEST_true(EC_POINT_mul(group, Q, order, NULL, NULL, ctx))
0bf02d
        || !TEST_true(EC_POINT_is_at_infinity(group, Q))
0bf02d
        || !TEST_true(EC_GROUP_precompute_mult(group, ctx))
0bf02d
        || !TEST_true(EC_POINT_mul(group, Q, order, NULL, NULL, ctx))
0bf02d
        || !TEST_true(EC_POINT_is_at_infinity(group, Q))
0bf02d
        || !TEST_true(EC_POINT_copy(P, G))
0bf02d
        || !TEST_true(BN_one(n1))
0bf02d
        || !TEST_true(EC_POINT_mul(group, Q, n1, NULL, NULL, ctx))
0bf02d
        || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx))
0bf02d
        || !TEST_true(BN_sub(n1, order, n1))
0bf02d
        || !TEST_true(EC_POINT_mul(group, Q, n1, NULL, NULL, ctx))
0bf02d
        || !TEST_true(EC_POINT_invert(group, Q, ctx))
0bf02d
        || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx)))
0bf02d
        goto err;
0bf02d
0bf02d
    for (i = 1; i <= 2; i++) {
0bf02d
        const BIGNUM *scalars[6];
0bf02d
        const EC_POINT *points[6];
0bf02d
0bf02d
        if (!TEST_true(BN_set_word(n1, i))
0bf02d
            /*
0bf02d
             * If i == 1, P will be the predefined generator for which
0bf02d
             * EC_GROUP_precompute_mult has set up precomputation.
0bf02d
             */
0bf02d
            || !TEST_true(EC_POINT_mul(group, P, n1, NULL, NULL, ctx))
0bf02d
            || (i == 1 && !TEST_int_eq(0, EC_POINT_cmp(group, P, G, ctx)))
0bf02d
            || !TEST_true(BN_one(n1))
0bf02d
            /* n1 = 1 - order */
0bf02d
            || !TEST_true(BN_sub(n1, n1, order))
0bf02d
            || !TEST_true(EC_POINT_mul(group, Q, NULL, P, n1, ctx))
0bf02d
            || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx))
0bf02d
0bf02d
            /* n2 = 1 + order */
0bf02d
            || !TEST_true(BN_add(n2, order, BN_value_one()))
0bf02d
            || !TEST_true(EC_POINT_mul(group, Q, NULL, P, n2, ctx))
0bf02d
            || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx))
0bf02d
0bf02d
            /* n2 = (1 - order) * (1 + order) = 1 - order^2 */
0bf02d
            || !TEST_true(BN_mul(n2, n1, n2, ctx))
0bf02d
            || !TEST_true(EC_POINT_mul(group, Q, NULL, P, n2, ctx))
0bf02d
            || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx)))
0bf02d
            goto err;
0bf02d
0bf02d
        /* n2 = order^2 - 1 */
0bf02d
        BN_set_negative(n2, 0);
0bf02d
        if (!TEST_true(EC_POINT_mul(group, Q, NULL, P, n2, ctx))
0bf02d
            /* Add P to verify the result. */
0bf02d
            || !TEST_true(EC_POINT_add(group, Q, Q, P, ctx))
0bf02d
            || !TEST_true(EC_POINT_is_at_infinity(group, Q))
0bf02d
0bf02d
            /* Exercise EC_POINTs_mul, including corner cases. */
0bf02d
            || !TEST_false(EC_POINT_is_at_infinity(group, P)))
0bf02d
            goto err;
0bf02d
0bf02d
        scalars[0] = scalars[1] = BN_value_one();
0bf02d
        points[0]  = points[1]  = P;
0bf02d
0bf02d
        if (!TEST_true(EC_POINTs_mul(group, R, NULL, 2, points, scalars, ctx))
0bf02d
            || !TEST_true(EC_POINT_dbl(group, S, points[0], ctx))
0bf02d
            || !TEST_int_eq(0, EC_POINT_cmp(group, R, S, ctx)))
0bf02d
            goto err;
0bf02d
0bf02d
        scalars[0] = n1;
0bf02d
        points[0] = Q;          /* => infinity */
0bf02d
        scalars[1] = n2;
0bf02d
        points[1] = P;          /* => -P */
0bf02d
        scalars[2] = n1;
0bf02d
        points[2] = Q;          /* => infinity */
0bf02d
        scalars[3] = n2;
0bf02d
        points[3] = Q;          /* => infinity */
0bf02d
        scalars[4] = n1;
0bf02d
        points[4] = P;          /* => P */
0bf02d
        scalars[5] = n2;
0bf02d
        points[5] = Q;          /* => infinity */
0bf02d
        if (!TEST_true(EC_POINTs_mul(group, P, NULL, 6, points, scalars, ctx))
0bf02d
            || !TEST_true(EC_POINT_is_at_infinity(group, P)))
0bf02d
            goto err;
0bf02d
    }
0bf02d
0bf02d
    r = 1;
0bf02d
err:
0bf02d
    if (r == 0 && i != 0)
0bf02d
        TEST_info(i == 1 ? "allowing precomputation" :
0bf02d
                           "without precomputation");
0bf02d
    EC_POINT_free(P);
0bf02d
    EC_POINT_free(Q);
0bf02d
    EC_POINT_free(R);
0bf02d
    EC_POINT_free(S);
0bf02d
    BN_free(n1);
0bf02d
    BN_free(n2);
0bf02d
    BN_free(order);
0bf02d
    BN_CTX_free(ctx);
0bf02d
    return r;
0bf02d
}
0bf02d
0bf02d
static int prime_field_tests(void)
0bf02d
{
0bf02d
    BN_CTX *ctx = NULL;
0bf02d
    BIGNUM *p = NULL, *a = NULL, *b = NULL, *scalar3 = NULL;
0bf02d
    EC_GROUP *group = NULL, *tmp = NULL;
0bf02d
    EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL,
0bf02d
             *P_256 = NULL, *P_384 = NULL, *P_521 = NULL;
0bf02d
    EC_POINT *P = NULL, *Q = NULL, *R = NULL;
0bf02d
    BIGNUM *x = NULL, *y = NULL, *z = NULL, *yplusone = NULL;
0bf02d
    const EC_POINT *points[4];
0bf02d
    const BIGNUM *scalars[4];
0bf02d
    unsigned char buf[100];
0bf02d
    size_t len, r = 0;
0bf02d
    int k;
0bf02d
0bf02d
    if (!TEST_ptr(ctx = BN_CTX_new())
0bf02d
        || !TEST_ptr(p = BN_new())
0bf02d
        || !TEST_ptr(a = BN_new())
0bf02d
        || !TEST_ptr(b = BN_new())
0bf02d
        /*
0bf02d
         * applications should use EC_GROUP_new_curve_GFp so
0bf02d
         * that the library gets to choose the EC_METHOD
0bf02d
         */
0bf02d
        || !TEST_ptr(group = EC_GROUP_new(EC_GFp_mont_method()))
0bf02d
        || !TEST_ptr(tmp = EC_GROUP_new(EC_GROUP_method_of(group)))
0bf02d
        || !TEST_true(EC_GROUP_copy(tmp, group)))
0bf02d
        goto err;
0bf02d
    EC_GROUP_free(group);
0bf02d
    group = tmp;
0bf02d
    tmp = NULL;
0bf02d
0bf02d
    buf[0] = 0;
0bf02d
    if (!TEST_ptr(P = EC_POINT_new(group))
0bf02d
        || !TEST_ptr(Q = EC_POINT_new(group))
0bf02d
        || !TEST_ptr(R = EC_POINT_new(group))
0bf02d
        || !TEST_ptr(x = BN_new())
0bf02d
        || !TEST_ptr(y = BN_new())
0bf02d
        || !TEST_ptr(z = BN_new())
0bf02d
        || !TEST_ptr(yplusone = BN_new()))
0bf02d
        goto err;
0bf02d
0bf02d
    /* Curve P-224 (FIPS PUB 186-2, App. 6) */
0bf02d
0bf02d
    if (!TEST_true(BN_hex2bn(&p,         "FFFFFFFFFFFFFFFFFFFFFFFF"
0bf02d
                                    "FFFFFFFF000000000000000000000001"))
0bf02d
        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
0bf02d
        || !TEST_true(BN_hex2bn(&a,         "FFFFFFFFFFFFFFFFFFFFFFFF"
0bf02d
                                    "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE"))
0bf02d
        || !TEST_true(BN_hex2bn(&b,         "B4050A850C04B3ABF5413256"
0bf02d
                                    "5044B0B7D7BFD8BA270B39432355FFB4"))
0bf02d
        || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
0bf02d
        || !TEST_true(BN_hex2bn(&x,         "B70E0CBD6BB4BF7F321390B9"
0bf02d
                                    "4A03C1D356C21122343280D6115C1D21"))
0bf02d
        || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, 0, ctx))
0bf02d
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
0bf02d
        || !TEST_true(BN_hex2bn(&z,         "FFFFFFFFFFFFFFFFFFFFFFFF"
0bf02d
                                    "FFFF16A2E0B8F03E13DD29455C5C2A3D"))
0bf02d
        || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
0bf02d
        || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx)))
0bf02d
        goto err;
0bf02d
0bf02d
    TEST_info("NIST curve P-224 -- Generator");
0bf02d
    test_output_bignum("x", x);
0bf02d
    test_output_bignum("y", y);
0bf02d
    /* G_y value taken from the standard: */
0bf02d
    if (!TEST_true(BN_hex2bn(&z,         "BD376388B5F723FB4C22DFE6"
0bf02d
                                 "CD4375A05A07476444D5819985007E34"))
0bf02d
        || !TEST_BN_eq(y, z)
0bf02d
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
0bf02d
    /*
0bf02d
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
0bf02d
     * and therefore setting the coordinates should fail.
0bf02d
     */
0bf02d
        || !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
0bf02d
                                                       ctx))
0bf02d
        || !TEST_int_eq(EC_GROUP_get_degree(group), 224)
0bf02d
        || !group_order_tests(group)
0bf02d
        || !TEST_ptr(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))
0bf02d
        || !TEST_true(EC_GROUP_copy(P_224, group))
0bf02d
0bf02d
    /* Curve P-256 (FIPS PUB 186-2, App. 6) */
0bf02d
0bf02d
        || !TEST_true(BN_hex2bn(&p, "FFFFFFFF000000010000000000000000"
0bf02d
                                    "00000000FFFFFFFFFFFFFFFFFFFFFFFF"))
0bf02d
        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
0bf02d
        || !TEST_true(BN_hex2bn(&a, "FFFFFFFF000000010000000000000000"
0bf02d
                                    "00000000FFFFFFFFFFFFFFFFFFFFFFFC"))
0bf02d
        || !TEST_true(BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC"
0bf02d
                                    "651D06B0CC53B0F63BCE3C3E27D2604B"))
0bf02d
        || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
0bf02d
0bf02d
        || !TEST_true(BN_hex2bn(&x, "6B17D1F2E12C4247F8BCE6E563A440F2"
0bf02d
                                    "77037D812DEB33A0F4A13945D898C296"))
0bf02d
        || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, 1, ctx))
0bf02d
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
0bf02d
        || !TEST_true(BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFF"
0bf02d
                                    "BCE6FAADA7179E84F3B9CAC2FC632551"))
0bf02d
        || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
0bf02d
        || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx)))
0bf02d
        goto err;
0bf02d
0bf02d
    TEST_info("NIST curve P-256 -- Generator");
0bf02d
    test_output_bignum("x", x);
0bf02d
    test_output_bignum("y", y);
0bf02d
    /* G_y value taken from the standard: */
0bf02d
    if (!TEST_true(BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E16"
0bf02d
                                 "2BCE33576B315ECECBB6406837BF51F5"))
0bf02d
        || !TEST_BN_eq(y, z)
0bf02d
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
0bf02d
    /*
0bf02d
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
0bf02d
     * and therefore setting the coordinates should fail.
0bf02d
     */
0bf02d
        || !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
0bf02d
                                                       ctx))
0bf02d
        || !TEST_int_eq(EC_GROUP_get_degree(group), 256)
0bf02d
        || !group_order_tests(group)
0bf02d
        || !TEST_ptr(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))
0bf02d
        || !TEST_true(EC_GROUP_copy(P_256, group))
0bf02d
0bf02d
    /* Curve P-384 (FIPS PUB 186-2, App. 6) */
0bf02d
0bf02d
        || !TEST_true(BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
0bf02d
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
0bf02d
                                    "FFFFFFFF0000000000000000FFFFFFFF"))
0bf02d
        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
0bf02d
        || !TEST_true(BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
0bf02d
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
0bf02d
                                    "FFFFFFFF0000000000000000FFFFFFFC"))
0bf02d
        || !TEST_true(BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19"
0bf02d
                                    "181D9C6EFE8141120314088F5013875A"
0bf02d
                                    "C656398D8A2ED19D2A85C8EDD3EC2AEF"))
0bf02d
        || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
0bf02d
0bf02d
        || !TEST_true(BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD74"
0bf02d
                                    "6E1D3B628BA79B9859F741E082542A38"
0bf02d
                                    "5502F25DBF55296C3A545E3872760AB7"))
0bf02d
        || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, 1, ctx))
0bf02d
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
0bf02d
        || !TEST_true(BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
0bf02d
                                    "FFFFFFFFFFFFFFFFC7634D81F4372DDF"
0bf02d
                                    "581A0DB248B0A77AECEC196ACCC52973"))
0bf02d
        || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
0bf02d
        || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx)))
0bf02d
        goto err;
0bf02d
0bf02d
    TEST_info("NIST curve P-384 -- Generator");
0bf02d
    test_output_bignum("x", x);
0bf02d
    test_output_bignum("y", y);
0bf02d
    /* G_y value taken from the standard: */
0bf02d
    if (!TEST_true(BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29"
0bf02d
                                 "F8F41DBD289A147CE9DA3113B5F0B8C0"
0bf02d
                                 "0A60B1CE1D7E819D7A431D7C90EA0E5F"))
0bf02d
        || !TEST_BN_eq(y, z)
0bf02d
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
0bf02d
    /*
0bf02d
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
0bf02d
     * and therefore setting the coordinates should fail.
0bf02d
     */
0bf02d
        || !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
0bf02d
                                                       ctx))
0bf02d
        || !TEST_int_eq(EC_GROUP_get_degree(group), 384)
0bf02d
        || !group_order_tests(group)
0bf02d
        || !TEST_ptr(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))
0bf02d
        || !TEST_true(EC_GROUP_copy(P_384, group))
0bf02d
0bf02d
    /* Curve P-521 (FIPS PUB 186-2, App. 6) */
0bf02d
        || !TEST_true(BN_hex2bn(&p,                              "1FF"
0bf02d
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
0bf02d
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
0bf02d
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
0bf02d
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"))
0bf02d
        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
0bf02d
        || !TEST_true(BN_hex2bn(&a,                              "1FF"
0bf02d
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
0bf02d
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
0bf02d
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
0bf02d
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC"))
0bf02d
        || !TEST_true(BN_hex2bn(&b,                              "051"
0bf02d
                                    "953EB9618E1C9A1F929A21A0B68540EE"
0bf02d
                                    "A2DA725B99B315F3B8B489918EF109E1"
0bf02d
                                    "56193951EC7E937B1652C0BD3BB1BF07"
0bf02d
                                    "3573DF883D2C34F1EF451FD46B503F00"))
0bf02d
        || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
0bf02d
        || !TEST_true(BN_hex2bn(&x,                               "C6"
0bf02d
                                    "858E06B70404E9CD9E3ECB662395B442"
0bf02d
                                    "9C648139053FB521F828AF606B4D3DBA"
0bf02d
                                    "A14B5E77EFE75928FE1DC127A2FFA8DE"
0bf02d
                                    "3348B3C1856A429BF97E7E31C2E5BD66"))
0bf02d
        || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, 0, ctx))
0bf02d
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
0bf02d
        || !TEST_true(BN_hex2bn(&z,                              "1FF"
0bf02d
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
0bf02d
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA"
0bf02d
                                    "51868783BF2F966B7FCC0148F709A5D0"
0bf02d
                                    "3BB5C9B8899C47AEBB6FB71E91386409"))
0bf02d
        || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
0bf02d
        || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx)))
0bf02d
        goto err;
0bf02d
0bf02d
    TEST_info("NIST curve P-521 -- Generator");
0bf02d
    test_output_bignum("x", x);
0bf02d
    test_output_bignum("y", y);
0bf02d
    /* G_y value taken from the standard: */
0bf02d
    if (!TEST_true(BN_hex2bn(&z,                              "118"
0bf02d
                                 "39296A789A3BC0045C8A5FB42C7D1BD9"
0bf02d
                                 "98F54449579B446817AFBD17273E662C"
0bf02d
                                 "97EE72995EF42640C550B9013FAD0761"
0bf02d
                                 "353C7086A272C24088BE94769FD16650"))
0bf02d
        || !TEST_BN_eq(y, z)
0bf02d
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
0bf02d
    /*
0bf02d
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
0bf02d
     * and therefore setting the coordinates should fail.
0bf02d
     */
0bf02d
        || !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
0bf02d
                                                       ctx))
0bf02d
        || !TEST_int_eq(EC_GROUP_get_degree(group), 521)
0bf02d
        || !group_order_tests(group)
0bf02d
        || !TEST_ptr(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))
0bf02d
        || !TEST_true(EC_GROUP_copy(P_521, group))
0bf02d
0bf02d
    /* more tests using the last curve */
0bf02d
0bf02d
    /* Restore the point that got mangled in the (x, y + 1) test. */
0bf02d
        || !TEST_true(EC_POINT_set_affine_coordinates(group, P, x, y, ctx))
0bf02d
        || !TEST_true(EC_POINT_copy(Q, P))
0bf02d
        || !TEST_false(EC_POINT_is_at_infinity(group, Q))
0bf02d
        || !TEST_true(EC_POINT_dbl(group, P, P, ctx))
0bf02d
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
0bf02d
        || !TEST_true(EC_POINT_invert(group, Q, ctx))       /* P = -2Q */
0bf02d
        || !TEST_true(EC_POINT_add(group, R, P, Q, ctx))
0bf02d
        || !TEST_true(EC_POINT_add(group, R, R, Q, ctx))
0bf02d
        || !TEST_true(EC_POINT_is_at_infinity(group, R))    /* R = P + 2Q */
0bf02d
        || !TEST_false(EC_POINT_is_at_infinity(group, Q)))
0bf02d
        goto err;
0bf02d
    points[0] = Q;
0bf02d
    points[1] = Q;
0bf02d
    points[2] = Q;
0bf02d
    points[3] = Q;
0bf02d
0bf02d
    if (!TEST_true(EC_GROUP_get_order(group, z, ctx))
0bf02d
        || !TEST_true(BN_add(y, z, BN_value_one()))
0bf02d
        || !TEST_BN_even(y)
0bf02d
        || !TEST_true(BN_rshift1(y, y)))
0bf02d
        goto err;
0bf02d
    scalars[0] = y;         /* (group order + 1)/2, so y*Q + y*Q = Q */
0bf02d
    scalars[1] = y;
0bf02d
0bf02d
    TEST_note("combined multiplication ...");
0bf02d
0bf02d
    /* z is still the group order */
0bf02d
    if (!TEST_true(EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))
0bf02d
        || !TEST_true(EC_POINTs_mul(group, R, z, 2, points, scalars, ctx))
0bf02d
        || !TEST_int_eq(0, EC_POINT_cmp(group, P, R, ctx))
0bf02d
        || !TEST_int_eq(0, EC_POINT_cmp(group, R, Q, ctx))
0bf02d
        || !TEST_true(BN_rand(y, BN_num_bits(y), 0, 0))
0bf02d
        || !TEST_true(BN_add(z, z, y)))
0bf02d
        goto err;
0bf02d
    BN_set_negative(z, 1);
0bf02d
    scalars[0] = y;
0bf02d
    scalars[1] = z;         /* z = -(order + y) */
0bf02d
0bf02d
    if (!TEST_true(EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))
0bf02d
        || !TEST_true(EC_POINT_is_at_infinity(group, P))
0bf02d
        || !TEST_true(BN_rand(x, BN_num_bits(y) - 1, 0, 0))
0bf02d
        || !TEST_true(BN_add(z, x, y)))
0bf02d
        goto err;
0bf02d
    BN_set_negative(z, 1);
0bf02d
    scalars[0] = x;
0bf02d
    scalars[1] = y;
0bf02d
    scalars[2] = z;         /* z = -(x+y) */
0bf02d
0bf02d
    if (!TEST_ptr(scalar3 = BN_new()))
0bf02d
        goto err;
0bf02d
    BN_zero(scalar3);
0bf02d
    scalars[3] = scalar3;
0bf02d
0bf02d
    if (!TEST_true(EC_POINTs_mul(group, P, NULL, 4, points, scalars, ctx))
0bf02d
        || !TEST_true(EC_POINT_is_at_infinity(group, P)))
0bf02d
        goto err;
0bf02d
0bf02d
    TEST_note(" ok\n");
0bf02d
0bf02d
0bf02d
    r = 1;
0bf02d
err:
0bf02d
    BN_CTX_free(ctx);
0bf02d
    BN_free(p);
0bf02d
    BN_free(a);
0bf02d
    BN_free(b);
0bf02d
    EC_GROUP_free(group);
0bf02d
    EC_GROUP_free(tmp);
0bf02d
    EC_POINT_free(P);
0bf02d
    EC_POINT_free(Q);
0bf02d
    EC_POINT_free(R);
0bf02d
    BN_free(x);
0bf02d
    BN_free(y);
0bf02d
    BN_free(z);
0bf02d
    BN_free(yplusone);
0bf02d
    BN_free(scalar3);
0bf02d
0bf02d
    EC_GROUP_free(P_224);
0bf02d
    EC_GROUP_free(P_256);
0bf02d
    EC_GROUP_free(P_384);
0bf02d
    EC_GROUP_free(P_521);
0bf02d
    return r;
0bf02d
}
0bf02d
0bf02d
static int internal_curve_test(int n)
0bf02d
{
0bf02d
    EC_GROUP *group = NULL;
0bf02d
    int nid = curves[n].nid;
0bf02d
0bf02d
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))) {
0bf02d
        TEST_info("EC_GROUP_new_curve_name() failed with curve %s\n",
0bf02d
                  OBJ_nid2sn(nid));
0bf02d
        return 0;
0bf02d
    }
0bf02d
    if (!TEST_true(EC_GROUP_check(group, NULL))) {
0bf02d
        TEST_info("EC_GROUP_check() failed with curve %s\n", OBJ_nid2sn(nid));
0bf02d
        EC_GROUP_free(group);
0bf02d
        return 0;
0bf02d
    }
0bf02d
    EC_GROUP_free(group);
0bf02d
    return 1;
0bf02d
}
0bf02d
0bf02d
static int internal_curve_test_method(int n)
0bf02d
{
0bf02d
    int r, nid = curves[n].nid;
0bf02d
    EC_GROUP *group;
0bf02d
0bf02d
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))) {
0bf02d
        TEST_info("Curve %s failed\n", OBJ_nid2sn(nid));
0bf02d
        return 0;
0bf02d
    }
0bf02d
    r = group_order_tests(group);
0bf02d
    EC_GROUP_free(group);
0bf02d
    return r;
0bf02d
}
0bf02d
0bf02d
# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
0bf02d
/*
0bf02d
 * nistp_test_params contains magic numbers for testing our optimized
0bf02d
 * implementations of several NIST curves with characteristic > 3.
0bf02d
 */
0bf02d
struct nistp_test_params {
0bf02d
    const EC_METHOD *(*meth) (void);
0bf02d
    int degree;
0bf02d
    /*
0bf02d
     * Qx, Qy and D are taken from
0bf02d
     * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf
0bf02d
     * Otherwise, values are standard curve parameters from FIPS 180-3
0bf02d
     */
0bf02d
    const char *p, *a, *b, *Qx, *Qy, *Gx, *Gy, *order, *d;
0bf02d
};
0bf02d
0bf02d
static const struct nistp_test_params nistp_tests_params[] = {
0bf02d
    {
0bf02d
     /* P-224 */
0bf02d
     EC_GFp_nistp224_method,
0bf02d
     224,
0bf02d
     /* p */
0bf02d
     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
0bf02d
     /* a */
0bf02d
     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
0bf02d
     /* b */
0bf02d
     "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
0bf02d
     /* Qx */
0bf02d
     "E84FB0B8E7000CB657D7973CF6B42ED78B301674276DF744AF130B3E",
0bf02d
     /* Qy */
0bf02d
     "4376675C6FC5612C21A0FF2D2A89D2987DF7A2BC52183B5982298555",
0bf02d
     /* Gx */
0bf02d
     "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
0bf02d
     /* Gy */
0bf02d
     "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
0bf02d
     /* order */
0bf02d
     "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
0bf02d
     /* d */
0bf02d
     "3F0C488E987C80BE0FEE521F8D90BE6034EC69AE11CA72AA777481E8",
0bf02d
     },
0bf02d
    {
0bf02d
     /* P-256 */
0bf02d
     EC_GFp_nistp256_method,
0bf02d
     256,
0bf02d
     /* p */
0bf02d
     "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
0bf02d
     /* a */
0bf02d
     "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
0bf02d
     /* b */
0bf02d
     "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
0bf02d
     /* Qx */
0bf02d
     "b7e08afdfe94bad3f1dc8c734798ba1c62b3a0ad1e9ea2a38201cd0889bc7a19",
0bf02d
     /* Qy */
0bf02d
     "3603f747959dbf7a4bb226e41928729063adc7ae43529e61b563bbc606cc5e09",
0bf02d
     /* Gx */
0bf02d
     "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
0bf02d
     /* Gy */
0bf02d
     "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
0bf02d
     /* order */
0bf02d
     "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
0bf02d
     /* d */
0bf02d
     "c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96",
0bf02d
     },
0bf02d
    {
0bf02d
     /* P-521 */
0bf02d
     EC_GFp_nistp521_method,
0bf02d
     521,
0bf02d
     /* p */
0bf02d
                                                                  "1ff"
0bf02d
     "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
0bf02d
     "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
0bf02d
     /* a */
0bf02d
                                                                  "1ff"
0bf02d
     "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
0bf02d
     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
0bf02d
     /* b */
0bf02d
                                                                  "051"
0bf02d
     "953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e1"
0bf02d
     "56193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
0bf02d
     /* Qx */
0bf02d
                                                                 "0098"
0bf02d
     "e91eef9a68452822309c52fab453f5f117c1da8ed796b255e9ab8f6410cca16e"
0bf02d
     "59df403a6bdc6ca467a37056b1e54b3005d8ac030decfeb68df18b171885d5c4",
0bf02d
     /* Qy */
0bf02d
                                                                 "0164"
0bf02d
     "350c321aecfc1cca1ba4364c9b15656150b4b78d6a48d7d28e7f31985ef17be8"
0bf02d
     "554376b72900712c4b83ad668327231526e313f5f092999a4632fd50d946bc2e",
0bf02d
     /* Gx */
0bf02d
                                                                   "c6"
0bf02d
     "858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dba"
0bf02d
     "a14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
0bf02d
     /* Gy */
0bf02d
                                                                  "118"
0bf02d
     "39296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c"
0bf02d
     "97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
0bf02d
     /* order */
0bf02d
                                                                  "1ff"
0bf02d
     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"
0bf02d
     "51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
0bf02d
     /* d */
0bf02d
                                                                 "0100"
0bf02d
     "085f47b8e1b8b11b7eb33028c0b2888e304bfc98501955b45bba1478dc184eee"
0bf02d
     "df09b86a5f7c21994406072787205e69a63709fe35aa93ba333514b24f961722",
0bf02d
     },
0bf02d
};
0bf02d
0bf02d
static int nistp_single_test(int idx)
0bf02d
{
0bf02d
    const struct nistp_test_params *test = nistp_tests_params + idx;
0bf02d
    BN_CTX *ctx = NULL;
0bf02d
    BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL;
0bf02d
    BIGNUM *n = NULL, *m = NULL, *order = NULL, *yplusone = NULL;
0bf02d
    EC_GROUP *NISTP = NULL;
0bf02d
    EC_POINT *G = NULL, *P = NULL, *Q = NULL, *Q_CHECK = NULL;
0bf02d
    int r = 0;
0bf02d
0bf02d
    TEST_note("NIST curve P-%d (optimised implementation):",
0bf02d
              test->degree);
0bf02d
    if (!TEST_ptr(ctx = BN_CTX_new())
0bf02d
        || !TEST_ptr(p = BN_new())
0bf02d
        || !TEST_ptr(a = BN_new())
0bf02d
        || !TEST_ptr(b = BN_new())
0bf02d
        || !TEST_ptr(x = BN_new())
0bf02d
        || !TEST_ptr(y = BN_new())
0bf02d
        || !TEST_ptr(m = BN_new())
0bf02d
        || !TEST_ptr(n = BN_new())
0bf02d
        || !TEST_ptr(order = BN_new())
0bf02d
        || !TEST_ptr(yplusone = BN_new())
0bf02d
0bf02d
        || !TEST_ptr(NISTP = EC_GROUP_new(test->meth()))
0bf02d
        || !TEST_true(BN_hex2bn(&p, test->p))
0bf02d
        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
0bf02d
        || !TEST_true(BN_hex2bn(&a, test->a))
0bf02d
        || !TEST_true(BN_hex2bn(&b, test->b))
0bf02d
        || !TEST_true(EC_GROUP_set_curve(NISTP, p, a, b, ctx))
0bf02d
        || !TEST_ptr(G = EC_POINT_new(NISTP))
0bf02d
        || !TEST_ptr(P = EC_POINT_new(NISTP))
0bf02d
        || !TEST_ptr(Q = EC_POINT_new(NISTP))
0bf02d
        || !TEST_ptr(Q_CHECK = EC_POINT_new(NISTP))
0bf02d
        || !TEST_true(BN_hex2bn(&x, test->Qx))
0bf02d
        || !TEST_true(BN_hex2bn(&y, test->Qy))
0bf02d
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
0bf02d
    /*
0bf02d
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
0bf02d
     * and therefore setting the coordinates should fail.
0bf02d
     */
0bf02d
        || !TEST_false(EC_POINT_set_affine_coordinates(NISTP, Q_CHECK, x,
0bf02d
                                                       yplusone, ctx))
0bf02d
        || !TEST_true(EC_POINT_set_affine_coordinates(NISTP, Q_CHECK, x, y,
0bf02d
                                                      ctx))
0bf02d
        || !TEST_true(BN_hex2bn(&x, test->Gx))
0bf02d
        || !TEST_true(BN_hex2bn(&y, test->Gy))
0bf02d
        || !TEST_true(EC_POINT_set_affine_coordinates(NISTP, G, x, y, ctx))
0bf02d
        || !TEST_true(BN_hex2bn(&order, test->order))
0bf02d
        || !TEST_true(EC_GROUP_set_generator(NISTP, G, order, BN_value_one()))
0bf02d
        || !TEST_int_eq(EC_GROUP_get_degree(NISTP), test->degree))
0bf02d
        goto err;
0bf02d
0bf02d
    TEST_note("NIST test vectors ... ");
0bf02d
    if (!TEST_true(BN_hex2bn(&n, test->d)))
0bf02d
        goto err;
0bf02d
    /* fixed point multiplication */
0bf02d
    EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx);
0bf02d
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
0bf02d
        goto err;
0bf02d
    /* random point multiplication */
0bf02d
    EC_POINT_mul(NISTP, Q, NULL, G, n, ctx);
0bf02d
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx))
0bf02d
0bf02d
        /* set generator to P = 2*G, where G is the standard generator */
0bf02d
        || !TEST_true(EC_POINT_dbl(NISTP, P, G, ctx))
0bf02d
        || !TEST_true(EC_GROUP_set_generator(NISTP, P, order, BN_value_one()))
0bf02d
        /* set the scalar to m=n/2, where n is the NIST test scalar */
0bf02d
        || !TEST_true(BN_rshift(m, n, 1)))
0bf02d
        goto err;
0bf02d
0bf02d
    /* test the non-standard generator */
0bf02d
    /* fixed point multiplication */
0bf02d
    EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx);
0bf02d
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
0bf02d
        goto err;
0bf02d
    /* random point multiplication */
0bf02d
    EC_POINT_mul(NISTP, Q, NULL, P, m, ctx);
0bf02d
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx))
0bf02d
0bf02d
    /*
0bf02d
     * We have not performed precomputation so have_precompute mult should be
0bf02d
     * false
0bf02d
     */
0bf02d
        || !TEST_false(EC_GROUP_have_precompute_mult(NISTP))
0bf02d
0bf02d
    /* now repeat all tests with precomputation */
0bf02d
        || !TEST_true(EC_GROUP_precompute_mult(NISTP, ctx))
0bf02d
        || !TEST_true(EC_GROUP_have_precompute_mult(NISTP)))
0bf02d
        goto err;
0bf02d
0bf02d
    /* fixed point multiplication */
0bf02d
    EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx);
0bf02d
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
0bf02d
        goto err;
0bf02d
    /* random point multiplication */
0bf02d
    EC_POINT_mul(NISTP, Q, NULL, P, m, ctx);
0bf02d
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx))
0bf02d
0bf02d
    /* reset generator */
0bf02d
        || !TEST_true(EC_GROUP_set_generator(NISTP, G, order, BN_value_one())))
0bf02d
        goto err;
0bf02d
    /* fixed point multiplication */
0bf02d
    EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx);
0bf02d
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
0bf02d
        goto err;
0bf02d
    /* random point multiplication */
0bf02d
    EC_POINT_mul(NISTP, Q, NULL, G, n, ctx);
0bf02d
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
0bf02d
        goto err;
0bf02d
0bf02d
    /* regression test for felem_neg bug */
0bf02d
    if (!TEST_true(BN_set_word(m, 32))
0bf02d
        || !TEST_true(BN_set_word(n, 31))
0bf02d
        || !TEST_true(EC_POINT_copy(P, G))
0bf02d
        || !TEST_true(EC_POINT_invert(NISTP, P, ctx))
0bf02d
        || !TEST_true(EC_POINT_mul(NISTP, Q, m, P, n, ctx))
0bf02d
        || !TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, G, ctx)))
0bf02d
      goto err;
0bf02d
0bf02d
    r = group_order_tests(NISTP);
0bf02d
err:
0bf02d
    EC_GROUP_free(NISTP);
0bf02d
    EC_POINT_free(G);
0bf02d
    EC_POINT_free(P);
0bf02d
    EC_POINT_free(Q);
0bf02d
    EC_POINT_free(Q_CHECK);
0bf02d
    BN_free(n);
0bf02d
    BN_free(m);
0bf02d
    BN_free(p);
0bf02d
    BN_free(a);
0bf02d
    BN_free(b);
0bf02d
    BN_free(x);
0bf02d
    BN_free(y);
0bf02d
    BN_free(order);
0bf02d
    BN_free(yplusone);
0bf02d
    BN_CTX_free(ctx);
0bf02d
    return r;
0bf02d
}
0bf02d
0bf02d
/*
0bf02d
 * Tests a point known to cause an incorrect underflow in an old version of
0bf02d
 * ecp_nist521.c
0bf02d
 */
0bf02d
static int underflow_test(void)
0bf02d
{
0bf02d
    BN_CTX *ctx = NULL;
0bf02d
    EC_GROUP *grp = NULL;
0bf02d
    EC_POINT *P = NULL, *Q = NULL, *R = NULL;
0bf02d
    BIGNUM *x1 = NULL, *y1 = NULL, *z1 = NULL, *x2 = NULL, *y2 = NULL;
0bf02d
    BIGNUM *k = NULL;
0bf02d
    int testresult = 0;
0bf02d
    const char *x1str =
0bf02d
        "1534f0077fffffe87e9adcfe000000000000000000003e05a21d2400002e031b1f4"
0bf02d
        "b80000c6fafa4f3c1288798d624a247b5e2ffffffffffffffefe099241900004";
0bf02d
    const char *p521m1 =
0bf02d
        "1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
0bf02d
        "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe";
0bf02d
0bf02d
    ctx = BN_CTX_new();
0bf02d
    if (!TEST_ptr(ctx))
0bf02d
        return 0;
0bf02d
0bf02d
    BN_CTX_start(ctx);
0bf02d
    x1 = BN_CTX_get(ctx);
0bf02d
    y1 = BN_CTX_get(ctx);
0bf02d
    z1 = BN_CTX_get(ctx);
0bf02d
    x2 = BN_CTX_get(ctx);
0bf02d
    y2 = BN_CTX_get(ctx);
0bf02d
    k = BN_CTX_get(ctx);
0bf02d
    if (!TEST_ptr(k))
0bf02d
        goto err;
0bf02d
0bf02d
    grp = EC_GROUP_new_by_curve_name(NID_secp521r1);
0bf02d
    P = EC_POINT_new(grp);
0bf02d
    Q = EC_POINT_new(grp);
0bf02d
    R = EC_POINT_new(grp);
0bf02d
    if (!TEST_ptr(grp) || !TEST_ptr(P) || !TEST_ptr(Q) || !TEST_ptr(R))
0bf02d
        goto err;
0bf02d
0bf02d
    if (!TEST_int_gt(BN_hex2bn(&x1, x1str), 0)
0bf02d
            || !TEST_int_gt(BN_hex2bn(&y1, p521m1), 0)
0bf02d
            || !TEST_int_gt(BN_hex2bn(&z1, p521m1), 0)
0bf02d
            || !TEST_int_gt(BN_hex2bn(&k, "02"), 0)
0bf02d
            || !TEST_true(EC_POINT_set_Jprojective_coordinates_GFp(grp, P, x1,
0bf02d
                                                                   y1, z1, ctx))
0bf02d
            || !TEST_true(EC_POINT_mul(grp, Q, NULL, P, k, ctx))
0bf02d
            || !TEST_true(EC_POINT_get_affine_coordinates(grp, Q, x1, y1, ctx))
0bf02d
            || !TEST_true(EC_POINT_dbl(grp, R, P, ctx))
0bf02d
            || !TEST_true(EC_POINT_get_affine_coordinates(grp, R, x2, y2, ctx)))
0bf02d
        goto err;
0bf02d
0bf02d
    if (!TEST_int_eq(BN_cmp(x1, x2), 0)
0bf02d
            || !TEST_int_eq(BN_cmp(y1, y2), 0))
0bf02d
        goto err;
0bf02d
0bf02d
    testresult = 1;
0bf02d
0bf02d
 err:
0bf02d
    BN_CTX_end(ctx);
0bf02d
    EC_POINT_free(P);
0bf02d
    EC_POINT_free(Q);
0bf02d
    EC_POINT_free(R);
0bf02d
    EC_GROUP_free(grp);
0bf02d
    BN_CTX_free(ctx);
0bf02d
0bf02d
    return testresult;
0bf02d
}
0bf02d
# endif
0bf02d
0bf02d
static const unsigned char p521_named[] = {
0bf02d
    0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23,
0bf02d
};
0bf02d
0bf02d
static const unsigned char p521_explicit[] = {
0bf02d
    0x30, 0x82, 0x01, 0xc3, 0x02, 0x01, 0x01, 0x30, 0x4d, 0x06, 0x07, 0x2a,
0bf02d
    0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x42, 0x01, 0xff, 0xff, 0xff,
0bf02d
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0bf02d
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0bf02d
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0bf02d
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0bf02d
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0bf02d
    0xff, 0xff, 0x30, 0x81, 0x9f, 0x04, 0x42, 0x01, 0xff, 0xff, 0xff, 0xff,
0bf02d
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0bf02d
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0bf02d
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0bf02d
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0bf02d
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0bf02d
    0xfc, 0x04, 0x42, 0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, 0x9a,
0bf02d
    0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85, 0x40, 0xee, 0xa2, 0xda, 0x72,
0bf02d
    0x5b, 0x99, 0xb3, 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1, 0x09,
0bf02d
    0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e, 0x93, 0x7b, 0x16, 0x52, 0xc0,
0bf02d
    0xbd, 0x3b, 0xb1, 0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, 0x34,
0bf02d
    0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50, 0x3f, 0x00, 0x03, 0x15, 0x00,
0bf02d
    0xd0, 0x9e, 0x88, 0x00, 0x29, 0x1c, 0xb8, 0x53, 0x96, 0xcc, 0x67, 0x17,
0bf02d
    0x39, 0x32, 0x84, 0xaa, 0xa0, 0xda, 0x64, 0xba, 0x04, 0x81, 0x85, 0x04,
0bf02d
    0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd, 0x9e, 0x3e,
0bf02d
    0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f,
0bf02d
    0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba, 0xa1, 0x4b,
0bf02d
    0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff,
0bf02d
    0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, 0xf9, 0x7e,
0bf02d
    0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66, 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78,
0bf02d
    0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9,
0bf02d
    0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17,
0bf02d
    0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40,
0bf02d
    0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86,
0bf02d
    0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,
0bf02d
    0x02, 0x42, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0bf02d
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0bf02d
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa,
0bf02d
    0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, 0x7f, 0xcc, 0x01, 0x48,
0bf02d
    0xf7, 0x09, 0xa5, 0xd0, 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae,
0bf02d
    0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09, 0x02, 0x01, 0x01,
0bf02d
};
0bf02d
0bf02d
/*
0bf02d
 * Sometime we cannot compare nids for equality, as the built-in curve table
0bf02d
 * includes aliases with different names for the same curve.
0bf02d
 *
0bf02d
 * This function returns TRUE (1) if the checked nids are identical, or if they
0bf02d
 * alias to the same curve. FALSE (0) otherwise.
0bf02d
 */
0bf02d
static ossl_inline
0bf02d
int are_ec_nids_compatible(int n1d, int n2d)
0bf02d
{
0bf02d
    int ret = 0;
0bf02d
    switch (n1d) {
0bf02d
# ifndef OPENSSL_NO_EC2M
0bf02d
        case NID_sect113r1:
0bf02d
        case NID_wap_wsg_idm_ecid_wtls4:
0bf02d
            ret = (n2d == NID_sect113r1 || n2d == NID_wap_wsg_idm_ecid_wtls4);
0bf02d
            break;
0bf02d
        case NID_sect163k1:
0bf02d
        case NID_wap_wsg_idm_ecid_wtls3:
0bf02d
            ret = (n2d == NID_sect163k1 || n2d == NID_wap_wsg_idm_ecid_wtls3);
0bf02d
            break;
0bf02d
        case NID_sect233k1:
0bf02d
        case NID_wap_wsg_idm_ecid_wtls10:
0bf02d
            ret = (n2d == NID_sect233k1 || n2d == NID_wap_wsg_idm_ecid_wtls10);
0bf02d
            break;
0bf02d
        case NID_sect233r1:
0bf02d
        case NID_wap_wsg_idm_ecid_wtls11:
0bf02d
            ret = (n2d == NID_sect233r1 || n2d == NID_wap_wsg_idm_ecid_wtls11);
0bf02d
            break;
0bf02d
        case NID_X9_62_c2pnb163v1:
0bf02d
        case NID_wap_wsg_idm_ecid_wtls5:
0bf02d
            ret = (n2d == NID_X9_62_c2pnb163v1
0bf02d
                   || n2d == NID_wap_wsg_idm_ecid_wtls5);
0bf02d
            break;
0bf02d
# endif /* OPENSSL_NO_EC2M */
0bf02d
        case NID_secp112r1:
0bf02d
        case NID_wap_wsg_idm_ecid_wtls6:
0bf02d
            ret = (n2d == NID_secp112r1 || n2d == NID_wap_wsg_idm_ecid_wtls6);
0bf02d
            break;
0bf02d
        case NID_secp160r2:
0bf02d
        case NID_wap_wsg_idm_ecid_wtls7:
0bf02d
            ret = (n2d == NID_secp160r2 || n2d == NID_wap_wsg_idm_ecid_wtls7);
0bf02d
            break;
0bf02d
# ifdef OPENSSL_NO_EC_NISTP_64_GCC_128
0bf02d
        case NID_secp224r1:
0bf02d
        case NID_wap_wsg_idm_ecid_wtls12:
0bf02d
            ret = (n2d == NID_secp224r1 || n2d == NID_wap_wsg_idm_ecid_wtls12);
0bf02d
            break;
0bf02d
# else
0bf02d
        /*
0bf02d
         * For SEC P-224 we want to ensure that the SECP nid is returned, as
0bf02d
         * that is associated with a specialized method.
0bf02d
         */
0bf02d
        case NID_wap_wsg_idm_ecid_wtls12:
0bf02d
            ret = (n2d == NID_secp224r1);
0bf02d
            break;
0bf02d
# endif /* def(OPENSSL_NO_EC_NISTP_64_GCC_128) */
0bf02d
0bf02d
        default:
0bf02d
            ret = (n1d == n2d);
0bf02d
    }
0bf02d
    return ret;
0bf02d
}
0bf02d
0bf02d
/*
0bf02d
 * This checks that EC_GROUP_bew_from_ecparameters() returns a "named"
0bf02d
 * EC_GROUP for built-in curves.
0bf02d
 *
0bf02d
 * Note that it is possible to retrieve an alternative alias that does not match
0bf02d
 * the original nid.
0bf02d
 *
0bf02d
 * Ensure that the OPENSSL_EC_EXPLICIT_CURVE ASN1 flag is set.
0bf02d
 */
0bf02d
static int check_named_curve_from_ecparameters(int id)
0bf02d
{
0bf02d
    int ret = 0, nid, tnid;
0bf02d
    EC_GROUP *group = NULL, *tgroup = NULL, *tmpg = NULL;
0bf02d
    const EC_POINT *group_gen = NULL;
0bf02d
    EC_POINT *other_gen = NULL;
0bf02d
    BIGNUM *group_cofactor = NULL, *other_cofactor = NULL;
0bf02d
    BIGNUM *other_gen_x = NULL, *other_gen_y = NULL;
0bf02d
    const BIGNUM *group_order = NULL;
0bf02d
    BIGNUM *other_order = NULL;
0bf02d
    BN_CTX *bn_ctx = NULL;
0bf02d
    static const unsigned char invalid_seed[] = "THIS IS NOT A VALID SEED";
0bf02d
    static size_t invalid_seed_len = sizeof(invalid_seed);
0bf02d
    ECPARAMETERS *params = NULL, *other_params = NULL;
0bf02d
    EC_GROUP *g_ary[8] = {NULL};
0bf02d
    EC_GROUP **g_next = &g_ary[0];
0bf02d
    ECPARAMETERS *p_ary[8] = {NULL};
0bf02d
    ECPARAMETERS **p_next = &p_ary[0];
0bf02d
0bf02d
    /* Do some setup */
0bf02d
    nid = curves[id].nid;
0bf02d
    TEST_note("Curve %s", OBJ_nid2sn(nid));
0bf02d
    if (!TEST_ptr(bn_ctx = BN_CTX_new()))
0bf02d
        return ret;
0bf02d
    BN_CTX_start(bn_ctx);
0bf02d
0bf02d
    if (/* Allocations */
0bf02d
        !TEST_ptr(group_cofactor = BN_CTX_get(bn_ctx))
0bf02d
        || !TEST_ptr(other_gen_x = BN_CTX_get(bn_ctx))
0bf02d
        || !TEST_ptr(other_gen_y = BN_CTX_get(bn_ctx))
0bf02d
        || !TEST_ptr(other_order = BN_CTX_get(bn_ctx))
0bf02d
        || !TEST_ptr(other_cofactor = BN_CTX_get(bn_ctx))
0bf02d
        /* Generate reference group and params */
0bf02d
        || !TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))
0bf02d
        || !TEST_ptr(params = EC_GROUP_get_ecparameters(group, NULL))
0bf02d
        || !TEST_ptr(group_gen = EC_GROUP_get0_generator(group))
0bf02d
        || !TEST_ptr(group_order = EC_GROUP_get0_order(group))
0bf02d
        || !TEST_true(EC_GROUP_get_cofactor(group, group_cofactor, NULL))
0bf02d
        /* compute `other_*` values */
0bf02d
        || !TEST_ptr(tmpg = EC_GROUP_dup(group))
0bf02d
        || !TEST_ptr(other_gen = EC_POINT_dup(group_gen, group))
0bf02d
        || !TEST_true(EC_POINT_add(group, other_gen, group_gen, group_gen, NULL))
0bf02d
        || !TEST_true(EC_POINT_get_affine_coordinates(group, other_gen,
0bf02d
                      other_gen_x, other_gen_y, bn_ctx))
0bf02d
        || !TEST_true(BN_copy(other_order, group_order))
0bf02d
        || !TEST_true(BN_add_word(other_order, 1))
0bf02d
        || !TEST_true(BN_copy(other_cofactor, group_cofactor))
0bf02d
        || !TEST_true(BN_add_word(other_cofactor, 1)))
0bf02d
        goto err;
0bf02d
0bf02d
    EC_POINT_free(other_gen);
0bf02d
    other_gen = NULL;
0bf02d
0bf02d
    if (!TEST_ptr(other_gen = EC_POINT_new(tmpg))
0bf02d
        || !TEST_true(EC_POINT_set_affine_coordinates(tmpg, other_gen,
0bf02d
                                                      other_gen_x, other_gen_y,
0bf02d
                                                      bn_ctx)))
0bf02d
        goto err;
0bf02d
0bf02d
    /*
0bf02d
     * ###########################
0bf02d
     * # Actual tests start here #
0bf02d
     * ###########################
0bf02d
     */
0bf02d
0bf02d
    /*
0bf02d
     * Creating a group from built-in explicit parameters returns a
0bf02d
     * "named" EC_GROUP
0bf02d
     */
0bf02d
    if (!TEST_ptr(tgroup = *g_next++ = EC_GROUP_new_from_ecparameters(params))
0bf02d
        || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef))
0bf02d
        goto err;
0bf02d
    /*
0bf02d
     * We cannot always guarantee the names match, as the built-in table
0bf02d
     * contains aliases for the same curve with different names.
0bf02d
     */
0bf02d
    if (!TEST_true(are_ec_nids_compatible(nid, tnid))) {
0bf02d
        TEST_info("nid = %s, tnid = %s", OBJ_nid2sn(nid), OBJ_nid2sn(tnid));
0bf02d
        goto err;
0bf02d
    }
0bf02d
    /* Ensure that the OPENSSL_EC_EXPLICIT_CURVE ASN1 flag is set. */
0bf02d
    if (!TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup), OPENSSL_EC_EXPLICIT_CURVE))
0bf02d
        goto err;
0bf02d
0bf02d
    /*
0bf02d
     * An invalid seed in the parameters should be ignored: expect a "named"
0bf02d
     * group.
0bf02d
     */
0bf02d
    if (!TEST_int_eq(EC_GROUP_set_seed(tmpg, invalid_seed, invalid_seed_len),
0bf02d
                     invalid_seed_len)
0bf02d
            || !TEST_ptr(other_params = *p_next++ =
0bf02d
                         EC_GROUP_get_ecparameters(tmpg, NULL))
0bf02d
            || !TEST_ptr(tgroup = *g_next++ =
0bf02d
                          EC_GROUP_new_from_ecparameters(other_params))
0bf02d
            || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
0bf02d
            || !TEST_true(are_ec_nids_compatible(nid, tnid))
0bf02d
            || !TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup),
0bf02d
                            OPENSSL_EC_EXPLICIT_CURVE)) {
0bf02d
        TEST_info("nid = %s, tnid = %s", OBJ_nid2sn(nid), OBJ_nid2sn(tnid));
0bf02d
        goto err;
0bf02d
    }
0bf02d
0bf02d
    /*
0bf02d
     * A null seed in the parameters should be ignored, as it is optional:
0bf02d
     * expect a "named" group.
0bf02d
     */
0bf02d
    if (!TEST_int_eq(EC_GROUP_set_seed(tmpg, NULL, 0), 1)
0bf02d
            || !TEST_ptr(other_params = *p_next++ =
0bf02d
                         EC_GROUP_get_ecparameters(tmpg, NULL))
0bf02d
            || !TEST_ptr(tgroup = *g_next++ =
0bf02d
                          EC_GROUP_new_from_ecparameters(other_params))
0bf02d
            || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
0bf02d
            || !TEST_true(are_ec_nids_compatible(nid, tnid))
0bf02d
            || !TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup),
0bf02d
                            OPENSSL_EC_EXPLICIT_CURVE)) {
0bf02d
        TEST_info("nid = %s, tnid = %s", OBJ_nid2sn(nid), OBJ_nid2sn(tnid));
0bf02d
        goto err;
0bf02d
    }
0bf02d
0bf02d
    /*
0bf02d
     * Check that changing any of the generator parameters does not yield a
0bf02d
     * match with the built-in curves
0bf02d
     */
0bf02d
    if (/* Other gen, same group order & cofactor */
0bf02d
        !TEST_true(EC_GROUP_set_generator(tmpg, other_gen, group_order,
0bf02d
                                          group_cofactor))
0bf02d
        || !TEST_ptr(other_params = *p_next++ =
0bf02d
                     EC_GROUP_get_ecparameters(tmpg, NULL))
0bf02d
        || !TEST_ptr(tgroup = *g_next++ =
0bf02d
                      EC_GROUP_new_from_ecparameters(other_params))
0bf02d
        || !TEST_int_eq((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
0bf02d
        /* Same gen & cofactor, different order */
0bf02d
        || !TEST_true(EC_GROUP_set_generator(tmpg, group_gen, other_order,
0bf02d
                                             group_cofactor))
0bf02d
        || !TEST_ptr(other_params = *p_next++ =
0bf02d
                     EC_GROUP_get_ecparameters(tmpg, NULL))
0bf02d
        || !TEST_ptr(tgroup = *g_next++ =
0bf02d
                      EC_GROUP_new_from_ecparameters(other_params))
0bf02d
        || !TEST_int_eq((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
0bf02d
        /* The order is not an optional field, so this should fail */
0bf02d
        || !TEST_false(EC_GROUP_set_generator(tmpg, group_gen, NULL,
0bf02d
                                              group_cofactor))
0bf02d
        /* Check that a wrong cofactor is ignored, and we still match */
0bf02d
        || !TEST_true(EC_GROUP_set_generator(tmpg, group_gen, group_order,
0bf02d
                                             other_cofactor))
0bf02d
        || !TEST_ptr(other_params = *p_next++ =
0bf02d
                     EC_GROUP_get_ecparameters(tmpg, NULL))
0bf02d
        || !TEST_ptr(tgroup = *g_next++ =
0bf02d
                      EC_GROUP_new_from_ecparameters(other_params))
0bf02d
        || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
0bf02d
        || !TEST_true(are_ec_nids_compatible(nid, tnid))
0bf02d
        || !TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup),
0bf02d
                        OPENSSL_EC_EXPLICIT_CURVE)
0bf02d
        /* Check that if the cofactor is not set then it still matches */
0bf02d
        || !TEST_true(EC_GROUP_set_generator(tmpg, group_gen, group_order,
0bf02d
                                             NULL))
0bf02d
        || !TEST_ptr(other_params = *p_next++ =
0bf02d
                     EC_GROUP_get_ecparameters(tmpg, NULL))
0bf02d
        || !TEST_ptr(tgroup = *g_next++ =
0bf02d
                      EC_GROUP_new_from_ecparameters(other_params))
0bf02d
        || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
0bf02d
        || !TEST_true(are_ec_nids_compatible(nid, tnid))
0bf02d
        || !TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup),
0bf02d
                        OPENSSL_EC_EXPLICIT_CURVE)
0bf02d
        /* check that restoring the generator passes */
0bf02d
        || !TEST_true(EC_GROUP_set_generator(tmpg, group_gen, group_order,
0bf02d
                                             group_cofactor))
0bf02d
        || !TEST_ptr(other_params = *p_next++ =
0bf02d
                     EC_GROUP_get_ecparameters(tmpg, NULL))
0bf02d
        || !TEST_ptr(tgroup = *g_next++ =
0bf02d
                      EC_GROUP_new_from_ecparameters(other_params))
0bf02d
        || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
0bf02d
        || !TEST_true(are_ec_nids_compatible(nid, tnid))
0bf02d
        || !TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup),
0bf02d
                        OPENSSL_EC_EXPLICIT_CURVE))
0bf02d
        goto err;
0bf02d
0bf02d
    ret = 1;
0bf02d
err:
0bf02d
    for (g_next = &g_ary[0]; g_next < g_ary + OSSL_NELEM(g_ary); g_next++)
0bf02d
        EC_GROUP_free(*g_next);
0bf02d
    for (p_next = &p_ary[0]; p_next < p_ary + OSSL_NELEM(g_ary); p_next++)
0bf02d
        ECPARAMETERS_free(*p_next);
0bf02d
    ECPARAMETERS_free(params);
0bf02d
    EC_POINT_free(other_gen);
0bf02d
    EC_GROUP_free(tmpg);
0bf02d
    EC_GROUP_free(group);
0bf02d
    BN_CTX_end(bn_ctx);
0bf02d
    BN_CTX_free(bn_ctx);
0bf02d
    return ret;
0bf02d
}
0bf02d
0bf02d
static int parameter_test(void)
0bf02d
{
0bf02d
    EC_GROUP *group = NULL, *group2 = NULL;
0bf02d
    ECPARAMETERS *ecparameters = NULL;
0bf02d
    unsigned char *buf = NULL;
0bf02d
    int r = 0, len;
0bf02d
0bf02d
    /* must use a curve without a special group method */
0bf02d
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_secp256k1))
0bf02d
        || !TEST_ptr(ecparameters = EC_GROUP_get_ecparameters(group, NULL))
0bf02d
        || !TEST_ptr(group2 = EC_GROUP_new_from_ecparameters(ecparameters))
0bf02d
        || !TEST_int_eq(EC_GROUP_cmp(group, group2, NULL), 0))
0bf02d
        goto err;
0bf02d
0bf02d
    EC_GROUP_free(group);
0bf02d
    group = NULL;
0bf02d
0bf02d
    /* Test the named curve encoding, which should be default. */
0bf02d
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_secp521r1))
0bf02d
        || !TEST_true((len = i2d_ECPKParameters(group, &buf)) >= 0)
0bf02d
        || !TEST_mem_eq(buf, len, p521_named, sizeof(p521_named)))
0bf02d
        goto err;
0bf02d
0bf02d
    OPENSSL_free(buf);
0bf02d
    buf = NULL;
0bf02d
0bf02d
    /*
0bf02d
     * Test the explicit encoding. P-521 requires correctly zero-padding the
0bf02d
     * curve coefficients.
0bf02d
     */
0bf02d
    EC_GROUP_set_asn1_flag(group, OPENSSL_EC_EXPLICIT_CURVE);
0bf02d
    if (!TEST_true((len = i2d_ECPKParameters(group, &buf)) >= 0)
0bf02d
        || !TEST_mem_eq(buf, len, p521_explicit, sizeof(p521_explicit)))
0bf02d
        goto err;
0bf02d
0bf02d
    r = 1;
0bf02d
err:
0bf02d
    EC_GROUP_free(group);
0bf02d
    EC_GROUP_free(group2);
0bf02d
    ECPARAMETERS_free(ecparameters);
0bf02d
    OPENSSL_free(buf);
0bf02d
    return r;
0bf02d
}
0bf02d
0bf02d
/*-
0bf02d
 * random 256-bit explicit parameters curve, cofactor absent
0bf02d
 * order:    0x0c38d96a9f892b88772ec2e39614a82f4f (132 bit)
0bf02d
 * cofactor:   0x12bc94785251297abfafddf1565100da (125 bit)
0bf02d
 */
0bf02d
static const unsigned char params_cf_pass[] = {
0bf02d
    0x30, 0x81, 0xcd, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86,
0bf02d
    0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xe5, 0x00, 0x1f, 0xc5,
0bf02d
    0xca, 0x71, 0x9d, 0x8e, 0xf7, 0x07, 0x4b, 0x48, 0x37, 0xf9, 0x33, 0x2d,
0bf02d
    0x71, 0xbf, 0x79, 0xe7, 0xdc, 0x91, 0xc2, 0xff, 0xb6, 0x7b, 0xc3, 0x93,
0bf02d
    0x44, 0x88, 0xe6, 0x91, 0x30, 0x44, 0x04, 0x20, 0xe5, 0x00, 0x1f, 0xc5,
0bf02d
    0xca, 0x71, 0x9d, 0x8e, 0xf7, 0x07, 0x4b, 0x48, 0x37, 0xf9, 0x33, 0x2d,
0bf02d
    0x71, 0xbf, 0x79, 0xe7, 0xdc, 0x91, 0xc2, 0xff, 0xb6, 0x7b, 0xc3, 0x93,
0bf02d
    0x44, 0x88, 0xe6, 0x8e, 0x04, 0x20, 0x18, 0x8c, 0x59, 0x57, 0xc4, 0xbc,
0bf02d
    0x85, 0x57, 0xc3, 0x66, 0x9f, 0x89, 0xd5, 0x92, 0x0d, 0x7e, 0x42, 0x27,
0bf02d
    0x07, 0x64, 0xaa, 0x26, 0xed, 0x89, 0xc4, 0x09, 0x05, 0x4d, 0xc7, 0x23,
0bf02d
    0x47, 0xda, 0x04, 0x41, 0x04, 0x1b, 0x6b, 0x41, 0x0b, 0xf9, 0xfb, 0x77,
0bf02d
    0xfd, 0x50, 0xb7, 0x3e, 0x23, 0xa3, 0xec, 0x9a, 0x3b, 0x09, 0x31, 0x6b,
0bf02d
    0xfa, 0xf6, 0xce, 0x1f, 0xff, 0xeb, 0x57, 0x93, 0x24, 0x70, 0xf3, 0xf4,
0bf02d
    0xba, 0x7e, 0xfa, 0x86, 0x6e, 0x19, 0x89, 0xe3, 0x55, 0x6d, 0x5a, 0xe9,
0bf02d
    0xc0, 0x3d, 0xbc, 0xfb, 0xaf, 0xad, 0xd4, 0x7e, 0xa6, 0xe5, 0xfa, 0x1a,
0bf02d
    0x58, 0x07, 0x9e, 0x8f, 0x0d, 0x3b, 0xf7, 0x38, 0xca, 0x02, 0x11, 0x0c,
0bf02d
    0x38, 0xd9, 0x6a, 0x9f, 0x89, 0x2b, 0x88, 0x77, 0x2e, 0xc2, 0xe3, 0x96,
0bf02d
    0x14, 0xa8, 0x2f, 0x4f
0bf02d
};
0bf02d
0bf02d
/*-
0bf02d
 * random 256-bit explicit parameters curve, cofactor absent
0bf02d
 * order:    0x045a75c0c17228ebd9b169a10e34a22101 (131 bit)
0bf02d
 * cofactor:   0x2e134b4ede82649f67a2e559d361e5fe (126 bit)
0bf02d
 */
0bf02d
static const unsigned char params_cf_fail[] = {
0bf02d
    0x30, 0x81, 0xcd, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86,
0bf02d
    0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xc8, 0x95, 0x27, 0x37,
0bf02d
    0xe8, 0xe1, 0xfd, 0xcc, 0xf9, 0x6e, 0x0c, 0xa6, 0x21, 0xc1, 0x7d, 0x6b,
0bf02d
    0x9d, 0x44, 0x42, 0xea, 0x73, 0x4e, 0x04, 0xb6, 0xac, 0x62, 0x50, 0xd0,
0bf02d
    0x33, 0xc2, 0xea, 0x13, 0x30, 0x44, 0x04, 0x20, 0xc8, 0x95, 0x27, 0x37,
0bf02d
    0xe8, 0xe1, 0xfd, 0xcc, 0xf9, 0x6e, 0x0c, 0xa6, 0x21, 0xc1, 0x7d, 0x6b,
0bf02d
    0x9d, 0x44, 0x42, 0xea, 0x73, 0x4e, 0x04, 0xb6, 0xac, 0x62, 0x50, 0xd0,
0bf02d
    0x33, 0xc2, 0xea, 0x10, 0x04, 0x20, 0xbf, 0xa6, 0xa8, 0x05, 0x1d, 0x09,
0bf02d
    0xac, 0x70, 0x39, 0xbb, 0x4d, 0xb2, 0x90, 0x8a, 0x15, 0x41, 0x14, 0x1d,
0bf02d
    0x11, 0x86, 0x9f, 0x13, 0xa2, 0x63, 0x1a, 0xda, 0x95, 0x22, 0x4d, 0x02,
0bf02d
    0x15, 0x0a, 0x04, 0x41, 0x04, 0xaf, 0x16, 0x71, 0xf9, 0xc4, 0xc8, 0x59,
0bf02d
    0x1d, 0xa3, 0x6f, 0xe7, 0xc3, 0x57, 0xa1, 0xfa, 0x9f, 0x49, 0x7c, 0x11,
0bf02d
    0x27, 0x05, 0xa0, 0x7f, 0xff, 0xf9, 0xe0, 0xe7, 0x92, 0xdd, 0x9c, 0x24,
0bf02d
    0x8e, 0xc7, 0xb9, 0x52, 0x71, 0x3f, 0xbc, 0x7f, 0x6a, 0x9f, 0x35, 0x70,
0bf02d
    0xe1, 0x27, 0xd5, 0x35, 0x8a, 0x13, 0xfa, 0xa8, 0x33, 0x3e, 0xd4, 0x73,
0bf02d
    0x1c, 0x14, 0x58, 0x9e, 0xc7, 0x0a, 0x87, 0x65, 0x8d, 0x02, 0x11, 0x04,
0bf02d
    0x5a, 0x75, 0xc0, 0xc1, 0x72, 0x28, 0xeb, 0xd9, 0xb1, 0x69, 0xa1, 0x0e,
0bf02d
    0x34, 0xa2, 0x21, 0x01
0bf02d
};
0bf02d
0bf02d
/*-
0bf02d
 * Test two random 256-bit explicit parameters curves with absent cofactor.
0bf02d
 * The two curves are chosen to roughly straddle the bounds at which the lib
0bf02d
 * can compute the cofactor automatically, roughly 4*sqrt(p). So test that:
0bf02d
 *
0bf02d
 * - params_cf_pass: order is sufficiently close to p to compute cofactor
0bf02d
 * - params_cf_fail: order is too far away from p to compute cofactor
0bf02d
 *
0bf02d
 * For standards-compliant curves, cofactor is chosen as small as possible.
0bf02d
 * So you can see neither of these curves are fit for cryptographic use.
0bf02d
 *
0bf02d
 * Some standards even mandate an upper bound on the cofactor, e.g. SECG1 v2:
0bf02d
 * h <= 2**(t/8) where t is the security level of the curve, for which the lib
0bf02d
 * will always succeed in computing the cofactor. Neither of these curves
0bf02d
 * conform to that -- this is just robustness testing.
0bf02d
 */
0bf02d
static int cofactor_range_test(void)
0bf02d
{
0bf02d
    EC_GROUP *group = NULL;
0bf02d
    BIGNUM *cf = NULL;
0bf02d
    int ret = 0;
0bf02d
    const unsigned char *b1 = (const unsigned char *)params_cf_fail;
0bf02d
    const unsigned char *b2 = (const unsigned char *)params_cf_pass;
0bf02d
0bf02d
    if (!TEST_ptr(group = d2i_ECPKParameters(NULL, &b1, sizeof(params_cf_fail)))
0bf02d
        || !TEST_BN_eq_zero(EC_GROUP_get0_cofactor(group))
0bf02d
        || !TEST_ptr(group = d2i_ECPKParameters(&group, &b2,
0bf02d
                                                sizeof(params_cf_pass)))
0bf02d
        || !TEST_int_gt(BN_hex2bn(&cf, "12bc94785251297abfafddf1565100da"), 0)
0bf02d
        || !TEST_BN_eq(cf, EC_GROUP_get0_cofactor(group)))
0bf02d
        goto err;
0bf02d
    ret = 1;
0bf02d
 err:
0bf02d
    BN_free(cf);
0bf02d
    EC_GROUP_free(group);
0bf02d
    return ret;
0bf02d
}
0bf02d
0bf02d
/*-
0bf02d
 * For named curves, test that:
0bf02d
 * - the lib correctly computes the cofactor if passed a NULL or zero cofactor
0bf02d
 * - a nonsensical cofactor throws an error (negative test)
0bf02d
 * - nonsensical orders throw errors (negative tests)
0bf02d
 */
0bf02d
static int cardinality_test(int n)
0bf02d
{
0bf02d
    int ret = 0;
0bf02d
    int nid = curves[n].nid;
0bf02d
    BN_CTX *ctx = NULL;
0bf02d
    EC_GROUP *g1 = NULL, *g2 = NULL;
0bf02d
    EC_POINT *g2_gen = NULL;
0bf02d
    BIGNUM *g1_p = NULL, *g1_a = NULL, *g1_b = NULL, *g1_x = NULL, *g1_y = NULL,
0bf02d
           *g1_order = NULL, *g1_cf = NULL, *g2_cf = NULL;
0bf02d
0bf02d
    TEST_info("Curve %s cardinality test", OBJ_nid2sn(nid));
0bf02d
0bf02d
    if (!TEST_ptr(ctx = BN_CTX_new())
0bf02d
        || !TEST_ptr(g1 = EC_GROUP_new_by_curve_name(nid))
0bf02d
        || !TEST_ptr(g2 = EC_GROUP_new(EC_GROUP_method_of(g1)))) {
0bf02d
        EC_GROUP_free(g1);
0bf02d
        EC_GROUP_free(g2);
0bf02d
        BN_CTX_free(ctx);
0bf02d
        return 0;
0bf02d
    }
0bf02d
0bf02d
    BN_CTX_start(ctx);
0bf02d
    g1_p = BN_CTX_get(ctx);
0bf02d
    g1_a = BN_CTX_get(ctx);
0bf02d
    g1_b = BN_CTX_get(ctx);
0bf02d
    g1_x = BN_CTX_get(ctx);
0bf02d
    g1_y = BN_CTX_get(ctx);
0bf02d
    g1_order = BN_CTX_get(ctx);
0bf02d
    g1_cf = BN_CTX_get(ctx);
0bf02d
0bf02d
    if (!TEST_ptr(g2_cf = BN_CTX_get(ctx))
0bf02d
        /* pull out the explicit curve parameters */
0bf02d
        || !TEST_true(EC_GROUP_get_curve(g1, g1_p, g1_a, g1_b, ctx))
0bf02d
        || !TEST_true(EC_POINT_get_affine_coordinates(g1,
0bf02d
                      EC_GROUP_get0_generator(g1), g1_x, g1_y, ctx))
0bf02d
        || !TEST_true(BN_copy(g1_order, EC_GROUP_get0_order(g1)))
0bf02d
        || !TEST_true(EC_GROUP_get_cofactor(g1, g1_cf, ctx))
0bf02d
        /* construct g2 manually with g1 parameters */
0bf02d
        || !TEST_true(EC_GROUP_set_curve(g2, g1_p, g1_a, g1_b, ctx))
0bf02d
        || !TEST_ptr(g2_gen = EC_POINT_new(g2))
0bf02d
        || !TEST_true(EC_POINT_set_affine_coordinates(g2, g2_gen, g1_x, g1_y, ctx))
0bf02d
        /* pass NULL cofactor: lib should compute it */
0bf02d
        || !TEST_true(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL))
0bf02d
        || !TEST_true(EC_GROUP_get_cofactor(g2, g2_cf, ctx))
0bf02d
        || !TEST_BN_eq(g1_cf, g2_cf)
0bf02d
        /* pass zero cofactor: lib should compute it */
0bf02d
        || !TEST_true(BN_set_word(g2_cf, 0))
0bf02d
        || !TEST_true(EC_GROUP_set_generator(g2, g2_gen, g1_order, g2_cf))
0bf02d
        || !TEST_true(EC_GROUP_get_cofactor(g2, g2_cf, ctx))
0bf02d
        || !TEST_BN_eq(g1_cf, g2_cf)
0bf02d
        /* negative test for invalid cofactor */
0bf02d
        || !TEST_true(BN_set_word(g2_cf, 0))
0bf02d
        || !TEST_true(BN_sub(g2_cf, g2_cf, BN_value_one()))
0bf02d
        || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, g1_order, g2_cf))
0bf02d
        /* negative test for NULL order */
0bf02d
        || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, NULL, NULL))
0bf02d
        /* negative test for zero order */
0bf02d
        || !TEST_true(BN_set_word(g1_order, 0))
0bf02d
        || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL))
0bf02d
        /* negative test for negative order */
0bf02d
        || !TEST_true(BN_set_word(g2_cf, 0))
0bf02d
        || !TEST_true(BN_sub(g2_cf, g2_cf, BN_value_one()))
0bf02d
        || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL))
0bf02d
        /* negative test for too large order */
0bf02d
        || !TEST_true(BN_lshift(g1_order, g1_p, 2))
0bf02d
        || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL)))
0bf02d
        goto err;
0bf02d
    ret = 1;
0bf02d
 err:
0bf02d
    EC_POINT_free(g2_gen);
0bf02d
    EC_GROUP_free(g1);
0bf02d
    EC_GROUP_free(g2);
0bf02d
    BN_CTX_end(ctx);
0bf02d
    BN_CTX_free(ctx);
0bf02d
    return ret;
0bf02d
}
0bf02d
0bf02d
/*
0bf02d
 * Helper for ec_point_hex2point_test
0bf02d
 *
0bf02d
 * Self-tests EC_POINT_point2hex() against EC_POINT_hex2point() for the given
0bf02d
 * (group,P) pair.
0bf02d
 *
0bf02d
 * If P is NULL use point at infinity.
0bf02d
 */
0bf02d
static ossl_inline
0bf02d
int ec_point_hex2point_test_helper(const EC_GROUP *group, const EC_POINT *P,
0bf02d
                                   point_conversion_form_t form,
0bf02d
                                   BN_CTX *bnctx)
0bf02d
{
0bf02d
    int ret = 0;
0bf02d
    EC_POINT *Q = NULL, *Pinf = NULL;
0bf02d
    char *hex = NULL;
0bf02d
0bf02d
    if (P == NULL) {
0bf02d
        /* If P is NULL use point at infinity. */
0bf02d
        if (!TEST_ptr(Pinf = EC_POINT_new(group))
0bf02d
                || !TEST_true(EC_POINT_set_to_infinity(group, Pinf)))
0bf02d
            goto err;
0bf02d
        P = Pinf;
0bf02d
    }
0bf02d
0bf02d
    if (!TEST_ptr(hex = EC_POINT_point2hex(group, P, form, bnctx))
0bf02d
            || !TEST_ptr(Q = EC_POINT_hex2point(group, hex, NULL, bnctx))
0bf02d
            || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, bnctx)))
0bf02d
        goto err;
0bf02d
0bf02d
    /*
0bf02d
     * The next check is most likely superfluous, as EC_POINT_cmp should already
0bf02d
     * cover this.
0bf02d
     * Nonetheless it increases the test coverage for EC_POINT_is_at_infinity,
0bf02d
     * so we include it anyway!
0bf02d
     */
0bf02d
    if (Pinf != NULL
0bf02d
            && !TEST_true(EC_POINT_is_at_infinity(group, Q)))
0bf02d
        goto err;
0bf02d
0bf02d
    ret = 1;
0bf02d
0bf02d
 err:
0bf02d
    EC_POINT_free(Pinf);
0bf02d
    OPENSSL_free(hex);
0bf02d
    EC_POINT_free(Q);
0bf02d
0bf02d
    return ret;
0bf02d
}
0bf02d
0bf02d
/*
0bf02d
 * This test self-validates EC_POINT_hex2point() and EC_POINT_point2hex()
0bf02d
 */
0bf02d
static int ec_point_hex2point_test(int id)
0bf02d
{
0bf02d
    int ret = 0, nid;
0bf02d
    EC_GROUP *group = NULL;
0bf02d
    const EC_POINT *G = NULL;
0bf02d
    EC_POINT *P = NULL;
0bf02d
    BN_CTX * bnctx = NULL;
0bf02d
0bf02d
    /* Do some setup */
0bf02d
    nid = curves[id].nid;
0bf02d
    if (!TEST_ptr(bnctx = BN_CTX_new())
0bf02d
            || !TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))
0bf02d
            || !TEST_ptr(G = EC_GROUP_get0_generator(group))
0bf02d
            || !TEST_ptr(P = EC_POINT_dup(G, group)))
0bf02d
        goto err;
0bf02d
0bf02d
    if (!TEST_true(ec_point_hex2point_test_helper(group, P,
0bf02d
                                                  POINT_CONVERSION_COMPRESSED,
0bf02d
                                                  bnctx))
0bf02d
            || !TEST_true(ec_point_hex2point_test_helper(group, NULL,
0bf02d
                                                         POINT_CONVERSION_COMPRESSED,
0bf02d
                                                         bnctx))
0bf02d
            || !TEST_true(ec_point_hex2point_test_helper(group, P,
0bf02d
                                                         POINT_CONVERSION_UNCOMPRESSED,
0bf02d
                                                         bnctx))
0bf02d
            || !TEST_true(ec_point_hex2point_test_helper(group, NULL,
0bf02d
                                                         POINT_CONVERSION_UNCOMPRESSED,
0bf02d
                                                         bnctx))
0bf02d
            || !TEST_true(ec_point_hex2point_test_helper(group, P,
0bf02d
                                                         POINT_CONVERSION_HYBRID,
0bf02d
                                                         bnctx))
0bf02d
            || !TEST_true(ec_point_hex2point_test_helper(group, NULL,
0bf02d
                                                         POINT_CONVERSION_HYBRID,
0bf02d
                                                         bnctx)))
0bf02d
        goto err;
0bf02d
0bf02d
    ret = 1;
0bf02d
0bf02d
 err:
0bf02d
    EC_POINT_free(P);
0bf02d
    EC_GROUP_free(group);
0bf02d
    BN_CTX_free(bnctx);
0bf02d
0bf02d
    return ret;
0bf02d
}
0bf02d
0bf02d
/*
0bf02d
 * check the EC_METHOD respects the supplied EC_GROUP_set_generator G
0bf02d
 */
0bf02d
static int custom_generator_test(int id)
0bf02d
{
0bf02d
    int ret = 0, nid, bsize;
0bf02d
    EC_GROUP *group = NULL;
0bf02d
    EC_POINT *G2 = NULL, *Q1 = NULL, *Q2 = NULL;
0bf02d
    BN_CTX *ctx = NULL;
0bf02d
    BIGNUM *k = NULL;
0bf02d
    unsigned char *b1 = NULL, *b2 = NULL;
0bf02d
0bf02d
    /* Do some setup */
0bf02d
    nid = curves[id].nid;
0bf02d
    TEST_note("Curve %s", OBJ_nid2sn(nid));
0bf02d
    if (!TEST_ptr(ctx = BN_CTX_new()))
0bf02d
        return 0;
0bf02d
0bf02d
    BN_CTX_start(ctx);
0bf02d
0bf02d
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(nid)))
0bf02d
        goto err;
0bf02d
0bf02d
    /* expected byte length of encoded points */
0bf02d
    bsize = (EC_GROUP_get_degree(group) + 7) / 8;
0bf02d
    bsize = 2 * bsize + 1;
0bf02d
0bf02d
    if (!TEST_ptr(k = BN_CTX_get(ctx))
0bf02d
        /* fetch a testing scalar k != 0,1 */
0bf02d
        || !TEST_true(BN_rand(k, EC_GROUP_order_bits(group) - 1,
0bf02d
                              BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
0bf02d
        /* make k even */
0bf02d
        || !TEST_true(BN_clear_bit(k, 0))
0bf02d
        || !TEST_ptr(G2 = EC_POINT_new(group))
0bf02d
        || !TEST_ptr(Q1 = EC_POINT_new(group))
0bf02d
        /* Q1 := kG */
0bf02d
        || !TEST_true(EC_POINT_mul(group, Q1, k, NULL, NULL, ctx))
0bf02d
        /* pull out the bytes of that */
0bf02d
        || !TEST_int_eq(EC_POINT_point2oct(group, Q1,
0bf02d
                                           POINT_CONVERSION_UNCOMPRESSED, NULL,
0bf02d
                                           0, ctx), bsize)
0bf02d
        || !TEST_ptr(b1 = OPENSSL_malloc(bsize))
0bf02d
        || !TEST_int_eq(EC_POINT_point2oct(group, Q1,
0bf02d
                                           POINT_CONVERSION_UNCOMPRESSED, b1,
0bf02d
                                           bsize, ctx), bsize)
0bf02d
        /* new generator is G2 := 2G */
0bf02d
        || !TEST_true(EC_POINT_dbl(group, G2, EC_GROUP_get0_generator(group),
0bf02d
                                   ctx))
0bf02d
        || !TEST_true(EC_GROUP_set_generator(group, G2,
0bf02d
                                             EC_GROUP_get0_order(group),
0bf02d
                                             EC_GROUP_get0_cofactor(group)))
0bf02d
        || !TEST_ptr(Q2 = EC_POINT_new(group))
0bf02d
        || !TEST_true(BN_rshift1(k, k))
0bf02d
        /* Q2 := k/2 G2 */
0bf02d
        || !TEST_true(EC_POINT_mul(group, Q2, k, NULL, NULL, ctx))
0bf02d
        || !TEST_int_eq(EC_POINT_point2oct(group, Q2,
0bf02d
                                           POINT_CONVERSION_UNCOMPRESSED, NULL,
0bf02d
                                           0, ctx), bsize)
0bf02d
        || !TEST_ptr(b2 = OPENSSL_malloc(bsize))
0bf02d
        || !TEST_int_eq(EC_POINT_point2oct(group, Q2,
0bf02d
                                           POINT_CONVERSION_UNCOMPRESSED, b2,
0bf02d
                                           bsize, ctx), bsize)
0bf02d
        /* Q1 = kG = k/2 G2 = Q2 should hold */
0bf02d
        || !TEST_int_eq(CRYPTO_memcmp(b1, b2, bsize), 0))
0bf02d
        goto err;
0bf02d
0bf02d
    ret = 1;
0bf02d
0bf02d
 err:
0bf02d
    BN_CTX_end(ctx);
0bf02d
    EC_POINT_free(Q1);
0bf02d
    EC_POINT_free(Q2);
0bf02d
    EC_POINT_free(G2);
0bf02d
    EC_GROUP_free(group);
0bf02d
    BN_CTX_free(ctx);
0bf02d
    OPENSSL_free(b1);
0bf02d
    OPENSSL_free(b2);
0bf02d
0bf02d
    return ret;
0bf02d
}
0bf02d
0bf02d
#endif /* OPENSSL_NO_EC */
0bf02d
0bf02d
int setup_tests(void)
0bf02d
{
0bf02d
#ifndef OPENSSL_NO_EC
0bf02d
    crv_len = EC_get_builtin_curves(NULL, 0);
0bf02d
    if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len))
0bf02d
        || !TEST_true(EC_get_builtin_curves(curves, crv_len)))
0bf02d
        return 0;
0bf02d
0bf02d
    ADD_TEST(parameter_test);
0bf02d
    ADD_TEST(cofactor_range_test);
0bf02d
    ADD_ALL_TESTS(cardinality_test, crv_len);
0bf02d
    ADD_TEST(prime_field_tests);
0bf02d
# ifndef OPENSSL_NO_EC2M
0bf02d
    ADD_TEST(char2_field_tests);
0bf02d
    ADD_ALL_TESTS(char2_curve_test, OSSL_NELEM(char2_curve_tests));
0bf02d
# endif
0bf02d
# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
0bf02d
    ADD_ALL_TESTS(nistp_single_test, OSSL_NELEM(nistp_tests_params));
0bf02d
    ADD_TEST(underflow_test);
0bf02d
# endif
0bf02d
    ADD_ALL_TESTS(internal_curve_test, crv_len);
0bf02d
    ADD_ALL_TESTS(internal_curve_test_method, crv_len);
0bf02d
0bf02d
    ADD_ALL_TESTS(check_named_curve_from_ecparameters, crv_len);
0bf02d
    ADD_ALL_TESTS(ec_point_hex2point_test, crv_len);
0bf02d
    ADD_ALL_TESTS(custom_generator_test, crv_len);
0bf02d
#endif /* OPENSSL_NO_EC */
0bf02d
    return 1;
0bf02d
}
0bf02d
0bf02d
void cleanup_tests(void)
0bf02d
{
0bf02d
#ifndef OPENSSL_NO_EC
0bf02d
    OPENSSL_free(curves);
0bf02d
#endif
0bf02d
}