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
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
3a273b
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_secp384r1))
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
}
3a273b
#endif
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);
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);
3a273b
#endif
3a273b
    return 1;
3a273b
}
3a273b
3a273b
void cleanup_tests(void)
3a273b
{
3a273b
#ifndef OPENSSL_NO_EC
3a273b
    OPENSSL_free(curves);
3a273b
#endif
3a273b
}