Blame SOURCES/ectest.c

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