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