Blame SOURCES/ectest.c

e4b8d1
/*
782d48
 * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
e4b8d1
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
e4b8d1
 *
e4b8d1
 * Licensed under the OpenSSL license (the "License").  You may not use
e4b8d1
 * this file except in compliance with the License.  You can obtain a copy
e4b8d1
 * in the file LICENSE in the source distribution or at
e4b8d1
 * https://www.openssl.org/source/license.html
e4b8d1
 */
e4b8d1
e4b8d1
#include "internal/nelem.h"
e4b8d1
#include "testutil.h"
e4b8d1
e4b8d1
#ifndef OPENSSL_NO_EC
e4b8d1
# include <openssl/ec.h>
e4b8d1
# ifndef OPENSSL_NO_ENGINE
e4b8d1
#  include <openssl/engine.h>
e4b8d1
# endif
e4b8d1
# include <openssl/err.h>
e4b8d1
# include <openssl/obj_mac.h>
e4b8d1
# include <openssl/objects.h>
e4b8d1
# include <openssl/rand.h>
e4b8d1
# include <openssl/bn.h>
e4b8d1
# include <openssl/opensslconf.h>
e4b8d1
e4b8d1
static size_t crv_len = 0;
e4b8d1
static EC_builtin_curve *curves = NULL;
e4b8d1
e4b8d1
/* test multiplication with group order, long and negative scalars */
e4b8d1
static int group_order_tests(EC_GROUP *group)
e4b8d1
{
e4b8d1
    BIGNUM *n1 = NULL, *n2 = NULL, *order = NULL;
e4b8d1
    EC_POINT *P = NULL, *Q = NULL, *R = NULL, *S = NULL;
e4b8d1
    const EC_POINT *G = NULL;
e4b8d1
    BN_CTX *ctx = NULL;
e4b8d1
    int i = 0, r = 0;
e4b8d1
e4b8d1
    if (!TEST_ptr(n1 = BN_new())
e4b8d1
        || !TEST_ptr(n2 = BN_new())
e4b8d1
        || !TEST_ptr(order = BN_new())
e4b8d1
        || !TEST_ptr(ctx = BN_CTX_new())
e4b8d1
        || !TEST_ptr(G = EC_GROUP_get0_generator(group))
e4b8d1
        || !TEST_ptr(P = EC_POINT_new(group))
e4b8d1
        || !TEST_ptr(Q = EC_POINT_new(group))
e4b8d1
        || !TEST_ptr(R = EC_POINT_new(group))
e4b8d1
        || !TEST_ptr(S = EC_POINT_new(group)))
e4b8d1
        goto err;
e4b8d1
e4b8d1
    if (!TEST_true(EC_GROUP_get_order(group, order, ctx))
e4b8d1
        || !TEST_true(EC_POINT_mul(group, Q, order, NULL, NULL, ctx))
e4b8d1
        || !TEST_true(EC_POINT_is_at_infinity(group, Q))
e4b8d1
        || !TEST_true(EC_GROUP_precompute_mult(group, ctx))
e4b8d1
        || !TEST_true(EC_POINT_mul(group, Q, order, NULL, NULL, ctx))
e4b8d1
        || !TEST_true(EC_POINT_is_at_infinity(group, Q))
e4b8d1
        || !TEST_true(EC_POINT_copy(P, G))
e4b8d1
        || !TEST_true(BN_one(n1))
e4b8d1
        || !TEST_true(EC_POINT_mul(group, Q, n1, NULL, NULL, ctx))
e4b8d1
        || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx))
e4b8d1
        || !TEST_true(BN_sub(n1, order, n1))
e4b8d1
        || !TEST_true(EC_POINT_mul(group, Q, n1, NULL, NULL, ctx))
e4b8d1
        || !TEST_true(EC_POINT_invert(group, Q, ctx))
e4b8d1
        || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx)))
e4b8d1
        goto err;
e4b8d1
e4b8d1
    for (i = 1; i <= 2; i++) {
e4b8d1
        const BIGNUM *scalars[6];
e4b8d1
        const EC_POINT *points[6];
e4b8d1
e4b8d1
        if (!TEST_true(BN_set_word(n1, i))
e4b8d1
            /*
e4b8d1
             * If i == 1, P will be the predefined generator for which
e4b8d1
             * EC_GROUP_precompute_mult has set up precomputation.
e4b8d1
             */
e4b8d1
            || !TEST_true(EC_POINT_mul(group, P, n1, NULL, NULL, ctx))
e4b8d1
            || (i == 1 && !TEST_int_eq(0, EC_POINT_cmp(group, P, G, ctx)))
e4b8d1
            || !TEST_true(BN_one(n1))
e4b8d1
            /* n1 = 1 - order */
e4b8d1
            || !TEST_true(BN_sub(n1, n1, order))
e4b8d1
            || !TEST_true(EC_POINT_mul(group, Q, NULL, P, n1, ctx))
e4b8d1
            || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx))
e4b8d1
e4b8d1
            /* n2 = 1 + order */
e4b8d1
            || !TEST_true(BN_add(n2, order, BN_value_one()))
e4b8d1
            || !TEST_true(EC_POINT_mul(group, Q, NULL, P, n2, ctx))
e4b8d1
            || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx))
e4b8d1
e4b8d1
            /* n2 = (1 - order) * (1 + order) = 1 - order^2 */
e4b8d1
            || !TEST_true(BN_mul(n2, n1, n2, ctx))
e4b8d1
            || !TEST_true(EC_POINT_mul(group, Q, NULL, P, n2, ctx))
e4b8d1
            || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx)))
e4b8d1
            goto err;
e4b8d1
e4b8d1
        /* n2 = order^2 - 1 */
e4b8d1
        BN_set_negative(n2, 0);
e4b8d1
        if (!TEST_true(EC_POINT_mul(group, Q, NULL, P, n2, ctx))
e4b8d1
            /* Add P to verify the result. */
e4b8d1
            || !TEST_true(EC_POINT_add(group, Q, Q, P, ctx))
e4b8d1
            || !TEST_true(EC_POINT_is_at_infinity(group, Q))
e4b8d1
e4b8d1
            /* Exercise EC_POINTs_mul, including corner cases. */
e4b8d1
            || !TEST_false(EC_POINT_is_at_infinity(group, P)))
e4b8d1
            goto err;
e4b8d1
e4b8d1
        scalars[0] = scalars[1] = BN_value_one();
e4b8d1
        points[0]  = points[1]  = P;
e4b8d1
e4b8d1
        if (!TEST_true(EC_POINTs_mul(group, R, NULL, 2, points, scalars, ctx))
e4b8d1
            || !TEST_true(EC_POINT_dbl(group, S, points[0], ctx))
e4b8d1
            || !TEST_int_eq(0, EC_POINT_cmp(group, R, S, ctx)))
e4b8d1
            goto err;
e4b8d1
e4b8d1
        scalars[0] = n1;
e4b8d1
        points[0] = Q;          /* => infinity */
e4b8d1
        scalars[1] = n2;
e4b8d1
        points[1] = P;          /* => -P */
e4b8d1
        scalars[2] = n1;
e4b8d1
        points[2] = Q;          /* => infinity */
e4b8d1
        scalars[3] = n2;
e4b8d1
        points[3] = Q;          /* => infinity */
e4b8d1
        scalars[4] = n1;
e4b8d1
        points[4] = P;          /* => P */
e4b8d1
        scalars[5] = n2;
e4b8d1
        points[5] = Q;          /* => infinity */
e4b8d1
        if (!TEST_true(EC_POINTs_mul(group, P, NULL, 6, points, scalars, ctx))
e4b8d1
            || !TEST_true(EC_POINT_is_at_infinity(group, P)))
e4b8d1
            goto err;
e4b8d1
    }
e4b8d1
e4b8d1
    r = 1;
e4b8d1
err:
e4b8d1
    if (r == 0 && i != 0)
e4b8d1
        TEST_info(i == 1 ? "allowing precomputation" :
e4b8d1
                           "without precomputation");
e4b8d1
    EC_POINT_free(P);
e4b8d1
    EC_POINT_free(Q);
e4b8d1
    EC_POINT_free(R);
e4b8d1
    EC_POINT_free(S);
e4b8d1
    BN_free(n1);
e4b8d1
    BN_free(n2);
e4b8d1
    BN_free(order);
e4b8d1
    BN_CTX_free(ctx);
e4b8d1
    return r;
e4b8d1
}
e4b8d1
e4b8d1
static int prime_field_tests(void)
e4b8d1
{
e4b8d1
    BN_CTX *ctx = NULL;
e4b8d1
    BIGNUM *p = NULL, *a = NULL, *b = NULL, *scalar3 = NULL;
e4b8d1
    EC_GROUP *group = NULL, *tmp = NULL;
e4b8d1
    EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL,
e4b8d1
             *P_256 = NULL, *P_384 = NULL, *P_521 = NULL;
e4b8d1
    EC_POINT *P = NULL, *Q = NULL, *R = NULL;
e4b8d1
    BIGNUM *x = NULL, *y = NULL, *z = NULL, *yplusone = NULL;
e4b8d1
    const EC_POINT *points[4];
e4b8d1
    const BIGNUM *scalars[4];
e4b8d1
    unsigned char buf[100];
e4b8d1
    size_t len, r = 0;
e4b8d1
    int k;
e4b8d1
e4b8d1
    if (!TEST_ptr(ctx = BN_CTX_new())
e4b8d1
        || !TEST_ptr(p = BN_new())
e4b8d1
        || !TEST_ptr(a = BN_new())
e4b8d1
        || !TEST_ptr(b = BN_new())
e4b8d1
        /*
e4b8d1
         * applications should use EC_GROUP_new_curve_GFp so
e4b8d1
         * that the library gets to choose the EC_METHOD
e4b8d1
         */
e4b8d1
        || !TEST_ptr(group = EC_GROUP_new(EC_GFp_mont_method()))
e4b8d1
        || !TEST_ptr(tmp = EC_GROUP_new(EC_GROUP_method_of(group)))
e4b8d1
        || !TEST_true(EC_GROUP_copy(tmp, group)))
e4b8d1
        goto err;
e4b8d1
    EC_GROUP_free(group);
e4b8d1
    group = tmp;
e4b8d1
    tmp = NULL;
e4b8d1
e4b8d1
    buf[0] = 0;
e4b8d1
    if (!TEST_ptr(P = EC_POINT_new(group))
e4b8d1
        || !TEST_ptr(Q = EC_POINT_new(group))
e4b8d1
        || !TEST_ptr(R = EC_POINT_new(group))
e4b8d1
        || !TEST_ptr(x = BN_new())
e4b8d1
        || !TEST_ptr(y = BN_new())
e4b8d1
        || !TEST_ptr(z = BN_new())
e4b8d1
        || !TEST_ptr(yplusone = BN_new()))
e4b8d1
        goto err;
e4b8d1
e4b8d1
    /* Curve P-224 (FIPS PUB 186-2, App. 6) */
e4b8d1
e4b8d1
    if (!TEST_true(BN_hex2bn(&p,         "FFFFFFFFFFFFFFFFFFFFFFFF"
e4b8d1
                                    "FFFFFFFF000000000000000000000001"))
e4b8d1
        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
e4b8d1
        || !TEST_true(BN_hex2bn(&a,         "FFFFFFFFFFFFFFFFFFFFFFFF"
e4b8d1
                                    "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE"))
e4b8d1
        || !TEST_true(BN_hex2bn(&b,         "B4050A850C04B3ABF5413256"
e4b8d1
                                    "5044B0B7D7BFD8BA270B39432355FFB4"))
e4b8d1
        || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
e4b8d1
        || !TEST_true(BN_hex2bn(&x,         "B70E0CBD6BB4BF7F321390B9"
e4b8d1
                                    "4A03C1D356C21122343280D6115C1D21"))
e4b8d1
        || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, 0, ctx))
e4b8d1
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
e4b8d1
        || !TEST_true(BN_hex2bn(&z,         "FFFFFFFFFFFFFFFFFFFFFFFF"
e4b8d1
                                    "FFFF16A2E0B8F03E13DD29455C5C2A3D"))
e4b8d1
        || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
e4b8d1
        || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx)))
e4b8d1
        goto err;
e4b8d1
e4b8d1
    TEST_info("NIST curve P-224 -- Generator");
e4b8d1
    test_output_bignum("x", x);
e4b8d1
    test_output_bignum("y", y);
e4b8d1
    /* G_y value taken from the standard: */
e4b8d1
    if (!TEST_true(BN_hex2bn(&z,         "BD376388B5F723FB4C22DFE6"
e4b8d1
                                 "CD4375A05A07476444D5819985007E34"))
e4b8d1
        || !TEST_BN_eq(y, z)
e4b8d1
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
e4b8d1
    /*
e4b8d1
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
e4b8d1
     * and therefore setting the coordinates should fail.
e4b8d1
     */
e4b8d1
        || !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
e4b8d1
                                                       ctx))
e4b8d1
        || !TEST_int_eq(EC_GROUP_get_degree(group), 224)
e4b8d1
        || !group_order_tests(group)
e4b8d1
        || !TEST_ptr(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))
e4b8d1
        || !TEST_true(EC_GROUP_copy(P_224, group))
e4b8d1
e4b8d1
    /* Curve P-256 (FIPS PUB 186-2, App. 6) */
e4b8d1
e4b8d1
        || !TEST_true(BN_hex2bn(&p, "FFFFFFFF000000010000000000000000"
e4b8d1
                                    "00000000FFFFFFFFFFFFFFFFFFFFFFFF"))
e4b8d1
        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
e4b8d1
        || !TEST_true(BN_hex2bn(&a, "FFFFFFFF000000010000000000000000"
e4b8d1
                                    "00000000FFFFFFFFFFFFFFFFFFFFFFFC"))
e4b8d1
        || !TEST_true(BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC"
e4b8d1
                                    "651D06B0CC53B0F63BCE3C3E27D2604B"))
e4b8d1
        || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
e4b8d1
e4b8d1
        || !TEST_true(BN_hex2bn(&x, "6B17D1F2E12C4247F8BCE6E563A440F2"
e4b8d1
                                    "77037D812DEB33A0F4A13945D898C296"))
e4b8d1
        || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, 1, ctx))
e4b8d1
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
e4b8d1
        || !TEST_true(BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFF"
e4b8d1
                                    "BCE6FAADA7179E84F3B9CAC2FC632551"))
e4b8d1
        || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
e4b8d1
        || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx)))
e4b8d1
        goto err;
e4b8d1
e4b8d1
    TEST_info("NIST curve P-256 -- Generator");
e4b8d1
    test_output_bignum("x", x);
e4b8d1
    test_output_bignum("y", y);
e4b8d1
    /* G_y value taken from the standard: */
e4b8d1
    if (!TEST_true(BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E16"
e4b8d1
                                 "2BCE33576B315ECECBB6406837BF51F5"))
e4b8d1
        || !TEST_BN_eq(y, z)
e4b8d1
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
e4b8d1
    /*
e4b8d1
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
e4b8d1
     * and therefore setting the coordinates should fail.
e4b8d1
     */
e4b8d1
        || !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
e4b8d1
                                                       ctx))
e4b8d1
        || !TEST_int_eq(EC_GROUP_get_degree(group), 256)
e4b8d1
        || !group_order_tests(group)
e4b8d1
        || !TEST_ptr(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))
e4b8d1
        || !TEST_true(EC_GROUP_copy(P_256, group))
e4b8d1
e4b8d1
    /* Curve P-384 (FIPS PUB 186-2, App. 6) */
e4b8d1
e4b8d1
        || !TEST_true(BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
e4b8d1
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
e4b8d1
                                    "FFFFFFFF0000000000000000FFFFFFFF"))
e4b8d1
        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
e4b8d1
        || !TEST_true(BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
e4b8d1
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
e4b8d1
                                    "FFFFFFFF0000000000000000FFFFFFFC"))
e4b8d1
        || !TEST_true(BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19"
e4b8d1
                                    "181D9C6EFE8141120314088F5013875A"
e4b8d1
                                    "C656398D8A2ED19D2A85C8EDD3EC2AEF"))
e4b8d1
        || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
e4b8d1
e4b8d1
        || !TEST_true(BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD74"
e4b8d1
                                    "6E1D3B628BA79B9859F741E082542A38"
e4b8d1
                                    "5502F25DBF55296C3A545E3872760AB7"))
e4b8d1
        || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, 1, ctx))
e4b8d1
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
e4b8d1
        || !TEST_true(BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
e4b8d1
                                    "FFFFFFFFFFFFFFFFC7634D81F4372DDF"
e4b8d1
                                    "581A0DB248B0A77AECEC196ACCC52973"))
e4b8d1
        || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
e4b8d1
        || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx)))
e4b8d1
        goto err;
e4b8d1
e4b8d1
    TEST_info("NIST curve P-384 -- Generator");
e4b8d1
    test_output_bignum("x", x);
e4b8d1
    test_output_bignum("y", y);
e4b8d1
    /* G_y value taken from the standard: */
e4b8d1
    if (!TEST_true(BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29"
e4b8d1
                                 "F8F41DBD289A147CE9DA3113B5F0B8C0"
e4b8d1
                                 "0A60B1CE1D7E819D7A431D7C90EA0E5F"))
e4b8d1
        || !TEST_BN_eq(y, z)
e4b8d1
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
e4b8d1
    /*
e4b8d1
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
e4b8d1
     * and therefore setting the coordinates should fail.
e4b8d1
     */
e4b8d1
        || !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
e4b8d1
                                                       ctx))
e4b8d1
        || !TEST_int_eq(EC_GROUP_get_degree(group), 384)
e4b8d1
        || !group_order_tests(group)
e4b8d1
        || !TEST_ptr(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))
e4b8d1
        || !TEST_true(EC_GROUP_copy(P_384, group))
e4b8d1
e4b8d1
    /* Curve P-521 (FIPS PUB 186-2, App. 6) */
e4b8d1
        || !TEST_true(BN_hex2bn(&p,                              "1FF"
e4b8d1
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
e4b8d1
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
e4b8d1
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
e4b8d1
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"))
e4b8d1
        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
e4b8d1
        || !TEST_true(BN_hex2bn(&a,                              "1FF"
e4b8d1
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
e4b8d1
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
e4b8d1
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
e4b8d1
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC"))
e4b8d1
        || !TEST_true(BN_hex2bn(&b,                              "051"
e4b8d1
                                    "953EB9618E1C9A1F929A21A0B68540EE"
e4b8d1
                                    "A2DA725B99B315F3B8B489918EF109E1"
e4b8d1
                                    "56193951EC7E937B1652C0BD3BB1BF07"
e4b8d1
                                    "3573DF883D2C34F1EF451FD46B503F00"))
e4b8d1
        || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
e4b8d1
        || !TEST_true(BN_hex2bn(&x,                               "C6"
e4b8d1
                                    "858E06B70404E9CD9E3ECB662395B442"
e4b8d1
                                    "9C648139053FB521F828AF606B4D3DBA"
e4b8d1
                                    "A14B5E77EFE75928FE1DC127A2FFA8DE"
e4b8d1
                                    "3348B3C1856A429BF97E7E31C2E5BD66"))
e4b8d1
        || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, 0, ctx))
e4b8d1
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
e4b8d1
        || !TEST_true(BN_hex2bn(&z,                              "1FF"
e4b8d1
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
e4b8d1
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA"
e4b8d1
                                    "51868783BF2F966B7FCC0148F709A5D0"
e4b8d1
                                    "3BB5C9B8899C47AEBB6FB71E91386409"))
e4b8d1
        || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
e4b8d1
        || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx)))
e4b8d1
        goto err;
e4b8d1
e4b8d1
    TEST_info("NIST curve P-521 -- Generator");
e4b8d1
    test_output_bignum("x", x);
e4b8d1
    test_output_bignum("y", y);
e4b8d1
    /* G_y value taken from the standard: */
e4b8d1
    if (!TEST_true(BN_hex2bn(&z,                              "118"
e4b8d1
                                 "39296A789A3BC0045C8A5FB42C7D1BD9"
e4b8d1
                                 "98F54449579B446817AFBD17273E662C"
e4b8d1
                                 "97EE72995EF42640C550B9013FAD0761"
e4b8d1
                                 "353C7086A272C24088BE94769FD16650"))
e4b8d1
        || !TEST_BN_eq(y, z)
e4b8d1
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
e4b8d1
    /*
e4b8d1
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
e4b8d1
     * and therefore setting the coordinates should fail.
e4b8d1
     */
e4b8d1
        || !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
e4b8d1
                                                       ctx))
e4b8d1
        || !TEST_int_eq(EC_GROUP_get_degree(group), 521)
e4b8d1
        || !group_order_tests(group)
e4b8d1
        || !TEST_ptr(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))
e4b8d1
        || !TEST_true(EC_GROUP_copy(P_521, group))
e4b8d1
e4b8d1
    /* more tests using the last curve */
e4b8d1
e4b8d1
    /* Restore the point that got mangled in the (x, y + 1) test. */
e4b8d1
        || !TEST_true(EC_POINT_set_affine_coordinates(group, P, x, y, ctx))
e4b8d1
        || !TEST_true(EC_POINT_copy(Q, P))
e4b8d1
        || !TEST_false(EC_POINT_is_at_infinity(group, Q))
e4b8d1
        || !TEST_true(EC_POINT_dbl(group, P, P, ctx))
e4b8d1
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
e4b8d1
        || !TEST_true(EC_POINT_invert(group, Q, ctx))       /* P = -2Q */
e4b8d1
        || !TEST_true(EC_POINT_add(group, R, P, Q, ctx))
e4b8d1
        || !TEST_true(EC_POINT_add(group, R, R, Q, ctx))
e4b8d1
        || !TEST_true(EC_POINT_is_at_infinity(group, R))    /* R = P + 2Q */
e4b8d1
        || !TEST_false(EC_POINT_is_at_infinity(group, Q)))
e4b8d1
        goto err;
e4b8d1
    points[0] = Q;
e4b8d1
    points[1] = Q;
e4b8d1
    points[2] = Q;
e4b8d1
    points[3] = Q;
e4b8d1
e4b8d1
    if (!TEST_true(EC_GROUP_get_order(group, z, ctx))
e4b8d1
        || !TEST_true(BN_add(y, z, BN_value_one()))
e4b8d1
        || !TEST_BN_even(y)
e4b8d1
        || !TEST_true(BN_rshift1(y, y)))
e4b8d1
        goto err;
e4b8d1
    scalars[0] = y;         /* (group order + 1)/2, so y*Q + y*Q = Q */
e4b8d1
    scalars[1] = y;
e4b8d1
e4b8d1
    TEST_note("combined multiplication ...");
e4b8d1
e4b8d1
    /* z is still the group order */
e4b8d1
    if (!TEST_true(EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))
e4b8d1
        || !TEST_true(EC_POINTs_mul(group, R, z, 2, points, scalars, ctx))
e4b8d1
        || !TEST_int_eq(0, EC_POINT_cmp(group, P, R, ctx))
e4b8d1
        || !TEST_int_eq(0, EC_POINT_cmp(group, R, Q, ctx))
e4b8d1
        || !TEST_true(BN_rand(y, BN_num_bits(y), 0, 0))
e4b8d1
        || !TEST_true(BN_add(z, z, y)))
e4b8d1
        goto err;
e4b8d1
    BN_set_negative(z, 1);
e4b8d1
    scalars[0] = y;
e4b8d1
    scalars[1] = z;         /* z = -(order + y) */
e4b8d1
e4b8d1
    if (!TEST_true(EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))
e4b8d1
        || !TEST_true(EC_POINT_is_at_infinity(group, P))
e4b8d1
        || !TEST_true(BN_rand(x, BN_num_bits(y) - 1, 0, 0))
e4b8d1
        || !TEST_true(BN_add(z, x, y)))
e4b8d1
        goto err;
e4b8d1
    BN_set_negative(z, 1);
e4b8d1
    scalars[0] = x;
e4b8d1
    scalars[1] = y;
e4b8d1
    scalars[2] = z;         /* z = -(x+y) */
e4b8d1
e4b8d1
    if (!TEST_ptr(scalar3 = BN_new()))
e4b8d1
        goto err;
e4b8d1
    BN_zero(scalar3);
e4b8d1
    scalars[3] = scalar3;
e4b8d1
e4b8d1
    if (!TEST_true(EC_POINTs_mul(group, P, NULL, 4, points, scalars, ctx))
e4b8d1
        || !TEST_true(EC_POINT_is_at_infinity(group, P)))
e4b8d1
        goto err;
e4b8d1
e4b8d1
    TEST_note(" ok\n");
e4b8d1
e4b8d1
e4b8d1
    r = 1;
e4b8d1
err:
e4b8d1
    BN_CTX_free(ctx);
e4b8d1
    BN_free(p);
e4b8d1
    BN_free(a);
e4b8d1
    BN_free(b);
e4b8d1
    EC_GROUP_free(group);
e4b8d1
    EC_GROUP_free(tmp);
e4b8d1
    EC_POINT_free(P);
e4b8d1
    EC_POINT_free(Q);
e4b8d1
    EC_POINT_free(R);
e4b8d1
    BN_free(x);
e4b8d1
    BN_free(y);
e4b8d1
    BN_free(z);
e4b8d1
    BN_free(yplusone);
e4b8d1
    BN_free(scalar3);
e4b8d1
e4b8d1
    EC_GROUP_free(P_224);
e4b8d1
    EC_GROUP_free(P_256);
e4b8d1
    EC_GROUP_free(P_384);
e4b8d1
    EC_GROUP_free(P_521);
e4b8d1
    return r;
e4b8d1
}
e4b8d1
e4b8d1
static int internal_curve_test(int n)
e4b8d1
{
e4b8d1
    EC_GROUP *group = NULL;
e4b8d1
    int nid = curves[n].nid;
e4b8d1
e4b8d1
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))) {
e4b8d1
        TEST_info("EC_GROUP_new_curve_name() failed with curve %s\n",
e4b8d1
                  OBJ_nid2sn(nid));
e4b8d1
        return 0;
e4b8d1
    }
e4b8d1
    if (!TEST_true(EC_GROUP_check(group, NULL))) {
e4b8d1
        TEST_info("EC_GROUP_check() failed with curve %s\n", OBJ_nid2sn(nid));
e4b8d1
        EC_GROUP_free(group);
e4b8d1
        return 0;
e4b8d1
    }
e4b8d1
    EC_GROUP_free(group);
e4b8d1
    return 1;
e4b8d1
}
e4b8d1
e4b8d1
static int internal_curve_test_method(int n)
e4b8d1
{
e4b8d1
    int r, nid = curves[n].nid;
e4b8d1
    EC_GROUP *group;
e4b8d1
e4b8d1
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))) {
e4b8d1
        TEST_info("Curve %s failed\n", OBJ_nid2sn(nid));
e4b8d1
        return 0;
e4b8d1
    }
e4b8d1
    r = group_order_tests(group);
e4b8d1
    EC_GROUP_free(group);
e4b8d1
    return r;
e4b8d1
}
e4b8d1
e4b8d1
# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
e4b8d1
/*
e4b8d1
 * nistp_test_params contains magic numbers for testing our optimized
e4b8d1
 * implementations of several NIST curves with characteristic > 3.
e4b8d1
 */
e4b8d1
struct nistp_test_params {
e4b8d1
    const EC_METHOD *(*meth) (void);
e4b8d1
    int degree;
e4b8d1
    /*
e4b8d1
     * Qx, Qy and D are taken from
e4b8d1
     * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf
e4b8d1
     * Otherwise, values are standard curve parameters from FIPS 180-3
e4b8d1
     */
e4b8d1
    const char *p, *a, *b, *Qx, *Qy, *Gx, *Gy, *order, *d;
e4b8d1
};
e4b8d1
e4b8d1
static const struct nistp_test_params nistp_tests_params[] = {
e4b8d1
    {
e4b8d1
     /* P-224 */
e4b8d1
     EC_GFp_nistp224_method,
e4b8d1
     224,
e4b8d1
     /* p */
e4b8d1
     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
e4b8d1
     /* a */
e4b8d1
     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
e4b8d1
     /* b */
e4b8d1
     "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
e4b8d1
     /* Qx */
e4b8d1
     "E84FB0B8E7000CB657D7973CF6B42ED78B301674276DF744AF130B3E",
e4b8d1
     /* Qy */
e4b8d1
     "4376675C6FC5612C21A0FF2D2A89D2987DF7A2BC52183B5982298555",
e4b8d1
     /* Gx */
e4b8d1
     "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
e4b8d1
     /* Gy */
e4b8d1
     "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
e4b8d1
     /* order */
e4b8d1
     "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
e4b8d1
     /* d */
e4b8d1
     "3F0C488E987C80BE0FEE521F8D90BE6034EC69AE11CA72AA777481E8",
e4b8d1
     },
e4b8d1
    {
e4b8d1
     /* P-256 */
e4b8d1
     EC_GFp_nistp256_method,
e4b8d1
     256,
e4b8d1
     /* p */
e4b8d1
     "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
e4b8d1
     /* a */
e4b8d1
     "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
e4b8d1
     /* b */
e4b8d1
     "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
e4b8d1
     /* Qx */
e4b8d1
     "b7e08afdfe94bad3f1dc8c734798ba1c62b3a0ad1e9ea2a38201cd0889bc7a19",
e4b8d1
     /* Qy */
e4b8d1
     "3603f747959dbf7a4bb226e41928729063adc7ae43529e61b563bbc606cc5e09",
e4b8d1
     /* Gx */
e4b8d1
     "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
e4b8d1
     /* Gy */
e4b8d1
     "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
e4b8d1
     /* order */
e4b8d1
     "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
e4b8d1
     /* d */
e4b8d1
     "c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96",
e4b8d1
     },
e4b8d1
    {
e4b8d1
     /* P-521 */
e4b8d1
     EC_GFp_nistp521_method,
e4b8d1
     521,
e4b8d1
     /* p */
e4b8d1
                                                                  "1ff"
e4b8d1
     "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
e4b8d1
     "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
e4b8d1
     /* a */
e4b8d1
                                                                  "1ff"
e4b8d1
     "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
e4b8d1
     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
e4b8d1
     /* b */
e4b8d1
                                                                  "051"
e4b8d1
     "953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e1"
e4b8d1
     "56193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
e4b8d1
     /* Qx */
e4b8d1
                                                                 "0098"
e4b8d1
     "e91eef9a68452822309c52fab453f5f117c1da8ed796b255e9ab8f6410cca16e"
e4b8d1
     "59df403a6bdc6ca467a37056b1e54b3005d8ac030decfeb68df18b171885d5c4",
e4b8d1
     /* Qy */
e4b8d1
                                                                 "0164"
e4b8d1
     "350c321aecfc1cca1ba4364c9b15656150b4b78d6a48d7d28e7f31985ef17be8"
e4b8d1
     "554376b72900712c4b83ad668327231526e313f5f092999a4632fd50d946bc2e",
e4b8d1
     /* Gx */
e4b8d1
                                                                   "c6"
e4b8d1
     "858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dba"
e4b8d1
     "a14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
e4b8d1
     /* Gy */
e4b8d1
                                                                  "118"
e4b8d1
     "39296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c"
e4b8d1
     "97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
e4b8d1
     /* order */
e4b8d1
                                                                  "1ff"
e4b8d1
     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"
e4b8d1
     "51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
e4b8d1
     /* d */
e4b8d1
                                                                 "0100"
e4b8d1
     "085f47b8e1b8b11b7eb33028c0b2888e304bfc98501955b45bba1478dc184eee"
e4b8d1
     "df09b86a5f7c21994406072787205e69a63709fe35aa93ba333514b24f961722",
e4b8d1
     },
e4b8d1
};
e4b8d1
e4b8d1
static int nistp_single_test(int idx)
e4b8d1
{
e4b8d1
    const struct nistp_test_params *test = nistp_tests_params + idx;
e4b8d1
    BN_CTX *ctx = NULL;
e4b8d1
    BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL;
e4b8d1
    BIGNUM *n = NULL, *m = NULL, *order = NULL, *yplusone = NULL;
e4b8d1
    EC_GROUP *NISTP = NULL;
e4b8d1
    EC_POINT *G = NULL, *P = NULL, *Q = NULL, *Q_CHECK = NULL;
e4b8d1
    int r = 0;
e4b8d1
e4b8d1
    TEST_note("NIST curve P-%d (optimised implementation):",
e4b8d1
              test->degree);
e4b8d1
    if (!TEST_ptr(ctx = BN_CTX_new())
e4b8d1
        || !TEST_ptr(p = BN_new())
e4b8d1
        || !TEST_ptr(a = BN_new())
e4b8d1
        || !TEST_ptr(b = BN_new())
e4b8d1
        || !TEST_ptr(x = BN_new())
e4b8d1
        || !TEST_ptr(y = BN_new())
e4b8d1
        || !TEST_ptr(m = BN_new())
e4b8d1
        || !TEST_ptr(n = BN_new())
e4b8d1
        || !TEST_ptr(order = BN_new())
e4b8d1
        || !TEST_ptr(yplusone = BN_new())
e4b8d1
e4b8d1
        || !TEST_ptr(NISTP = EC_GROUP_new(test->meth()))
e4b8d1
        || !TEST_true(BN_hex2bn(&p, test->p))
e4b8d1
        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
e4b8d1
        || !TEST_true(BN_hex2bn(&a, test->a))
e4b8d1
        || !TEST_true(BN_hex2bn(&b, test->b))
e4b8d1
        || !TEST_true(EC_GROUP_set_curve(NISTP, p, a, b, ctx))
e4b8d1
        || !TEST_ptr(G = EC_POINT_new(NISTP))
e4b8d1
        || !TEST_ptr(P = EC_POINT_new(NISTP))
e4b8d1
        || !TEST_ptr(Q = EC_POINT_new(NISTP))
e4b8d1
        || !TEST_ptr(Q_CHECK = EC_POINT_new(NISTP))
e4b8d1
        || !TEST_true(BN_hex2bn(&x, test->Qx))
e4b8d1
        || !TEST_true(BN_hex2bn(&y, test->Qy))
e4b8d1
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
e4b8d1
    /*
e4b8d1
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
e4b8d1
     * and therefore setting the coordinates should fail.
e4b8d1
     */
e4b8d1
        || !TEST_false(EC_POINT_set_affine_coordinates(NISTP, Q_CHECK, x,
e4b8d1
                                                       yplusone, ctx))
e4b8d1
        || !TEST_true(EC_POINT_set_affine_coordinates(NISTP, Q_CHECK, x, y,
e4b8d1
                                                      ctx))
e4b8d1
        || !TEST_true(BN_hex2bn(&x, test->Gx))
e4b8d1
        || !TEST_true(BN_hex2bn(&y, test->Gy))
e4b8d1
        || !TEST_true(EC_POINT_set_affine_coordinates(NISTP, G, x, y, ctx))
e4b8d1
        || !TEST_true(BN_hex2bn(&order, test->order))
e4b8d1
        || !TEST_true(EC_GROUP_set_generator(NISTP, G, order, BN_value_one()))
e4b8d1
        || !TEST_int_eq(EC_GROUP_get_degree(NISTP), test->degree))
e4b8d1
        goto err;
e4b8d1
e4b8d1
    TEST_note("NIST test vectors ... ");
e4b8d1
    if (!TEST_true(BN_hex2bn(&n, test->d)))
e4b8d1
        goto err;
e4b8d1
    /* fixed point multiplication */
e4b8d1
    EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx);
e4b8d1
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
e4b8d1
        goto err;
e4b8d1
    /* random point multiplication */
e4b8d1
    EC_POINT_mul(NISTP, Q, NULL, G, n, ctx);
e4b8d1
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx))
e4b8d1
e4b8d1
        /* set generator to P = 2*G, where G is the standard generator */
e4b8d1
        || !TEST_true(EC_POINT_dbl(NISTP, P, G, ctx))
e4b8d1
        || !TEST_true(EC_GROUP_set_generator(NISTP, P, order, BN_value_one()))
e4b8d1
        /* set the scalar to m=n/2, where n is the NIST test scalar */
e4b8d1
        || !TEST_true(BN_rshift(m, n, 1)))
e4b8d1
        goto err;
e4b8d1
e4b8d1
    /* test the non-standard generator */
e4b8d1
    /* fixed point multiplication */
e4b8d1
    EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx);
e4b8d1
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
e4b8d1
        goto err;
e4b8d1
    /* random point multiplication */
e4b8d1
    EC_POINT_mul(NISTP, Q, NULL, P, m, ctx);
e4b8d1
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx))
e4b8d1
e4b8d1
    /*
e4b8d1
     * We have not performed precomputation so have_precompute mult should be
e4b8d1
     * false
e4b8d1
     */
e4b8d1
        || !TEST_false(EC_GROUP_have_precompute_mult(NISTP))
e4b8d1
e4b8d1
    /* now repeat all tests with precomputation */
e4b8d1
        || !TEST_true(EC_GROUP_precompute_mult(NISTP, ctx))
e4b8d1
        || !TEST_true(EC_GROUP_have_precompute_mult(NISTP)))
e4b8d1
        goto err;
e4b8d1
e4b8d1
    /* fixed point multiplication */
e4b8d1
    EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx);
e4b8d1
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
e4b8d1
        goto err;
e4b8d1
    /* random point multiplication */
e4b8d1
    EC_POINT_mul(NISTP, Q, NULL, P, m, ctx);
e4b8d1
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx))
e4b8d1
e4b8d1
    /* reset generator */
e4b8d1
        || !TEST_true(EC_GROUP_set_generator(NISTP, G, order, BN_value_one())))
e4b8d1
        goto err;
e4b8d1
    /* fixed point multiplication */
e4b8d1
    EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx);
e4b8d1
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
e4b8d1
        goto err;
e4b8d1
    /* random point multiplication */
e4b8d1
    EC_POINT_mul(NISTP, Q, NULL, G, n, ctx);
e4b8d1
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
e4b8d1
        goto err;
e4b8d1
e4b8d1
    /* regression test for felem_neg bug */
e4b8d1
    if (!TEST_true(BN_set_word(m, 32))
e4b8d1
        || !TEST_true(BN_set_word(n, 31))
e4b8d1
        || !TEST_true(EC_POINT_copy(P, G))
e4b8d1
        || !TEST_true(EC_POINT_invert(NISTP, P, ctx))
e4b8d1
        || !TEST_true(EC_POINT_mul(NISTP, Q, m, P, n, ctx))
e4b8d1
        || !TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, G, ctx)))
e4b8d1
      goto err;
e4b8d1
e4b8d1
    r = group_order_tests(NISTP);
e4b8d1
err:
e4b8d1
    EC_GROUP_free(NISTP);
e4b8d1
    EC_POINT_free(G);
e4b8d1
    EC_POINT_free(P);
e4b8d1
    EC_POINT_free(Q);
e4b8d1
    EC_POINT_free(Q_CHECK);
e4b8d1
    BN_free(n);
e4b8d1
    BN_free(m);
e4b8d1
    BN_free(p);
e4b8d1
    BN_free(a);
e4b8d1
    BN_free(b);
e4b8d1
    BN_free(x);
e4b8d1
    BN_free(y);
e4b8d1
    BN_free(order);
e4b8d1
    BN_free(yplusone);
e4b8d1
    BN_CTX_free(ctx);
e4b8d1
    return r;
e4b8d1
}
782d48
782d48
/*
782d48
 * Tests a point known to cause an incorrect underflow in an old version of
782d48
 * ecp_nist521.c
782d48
 */
782d48
static int underflow_test(void)
782d48
{
782d48
    BN_CTX *ctx = NULL;
782d48
    EC_GROUP *grp = NULL;
782d48
    EC_POINT *P = NULL, *Q = NULL, *R = NULL;
782d48
    BIGNUM *x1 = NULL, *y1 = NULL, *z1 = NULL, *x2 = NULL, *y2 = NULL;
782d48
    BIGNUM *k = NULL;
782d48
    int testresult = 0;
782d48
    const char *x1str =
782d48
        "1534f0077fffffe87e9adcfe000000000000000000003e05a21d2400002e031b1f4"
782d48
        "b80000c6fafa4f3c1288798d624a247b5e2ffffffffffffffefe099241900004";
782d48
    const char *p521m1 =
782d48
        "1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
782d48
        "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe";
782d48
782d48
    ctx = BN_CTX_new();
782d48
    if (!TEST_ptr(ctx))
782d48
        return 0;
782d48
782d48
    BN_CTX_start(ctx);
782d48
    x1 = BN_CTX_get(ctx);
782d48
    y1 = BN_CTX_get(ctx);
782d48
    z1 = BN_CTX_get(ctx);
782d48
    x2 = BN_CTX_get(ctx);
782d48
    y2 = BN_CTX_get(ctx);
782d48
    k = BN_CTX_get(ctx);
782d48
    if (!TEST_ptr(k))
782d48
        goto err;
782d48
782d48
    grp = EC_GROUP_new_by_curve_name(NID_secp521r1);
782d48
    P = EC_POINT_new(grp);
782d48
    Q = EC_POINT_new(grp);
782d48
    R = EC_POINT_new(grp);
782d48
    if (!TEST_ptr(grp) || !TEST_ptr(P) || !TEST_ptr(Q) || !TEST_ptr(R))
782d48
        goto err;
782d48
782d48
    if (!TEST_int_gt(BN_hex2bn(&x1, x1str), 0)
782d48
            || !TEST_int_gt(BN_hex2bn(&y1, p521m1), 0)
782d48
            || !TEST_int_gt(BN_hex2bn(&z1, p521m1), 0)
782d48
            || !TEST_int_gt(BN_hex2bn(&k, "02"), 0)
782d48
            || !TEST_true(EC_POINT_set_Jprojective_coordinates_GFp(grp, P, x1,
782d48
                                                                   y1, z1, ctx))
782d48
            || !TEST_true(EC_POINT_mul(grp, Q, NULL, P, k, ctx))
782d48
            || !TEST_true(EC_POINT_get_affine_coordinates(grp, Q, x1, y1, ctx))
782d48
            || !TEST_true(EC_POINT_dbl(grp, R, P, ctx))
782d48
            || !TEST_true(EC_POINT_get_affine_coordinates(grp, R, x2, y2, ctx)))
782d48
        goto err;
782d48
782d48
    if (!TEST_int_eq(BN_cmp(x1, x2), 0)
782d48
            || !TEST_int_eq(BN_cmp(y1, y2), 0))
782d48
        goto err;
782d48
782d48
    testresult = 1;
782d48
782d48
 err:
782d48
    BN_CTX_end(ctx);
782d48
    EC_POINT_free(P);
782d48
    EC_POINT_free(Q);
782d48
    EC_POINT_free(R);
782d48
    EC_GROUP_free(grp);
782d48
    BN_CTX_free(ctx);
782d48
782d48
    return testresult;
782d48
}
e4b8d1
# endif
e4b8d1
e4b8d1
static const unsigned char p521_named[] = {
e4b8d1
    0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23,
e4b8d1
};
e4b8d1
e4b8d1
static const unsigned char p521_explicit[] = {
e4b8d1
    0x30, 0x82, 0x01, 0xc3, 0x02, 0x01, 0x01, 0x30, 0x4d, 0x06, 0x07, 0x2a,
e4b8d1
    0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x42, 0x01, 0xff, 0xff, 0xff,
e4b8d1
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
e4b8d1
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
e4b8d1
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
e4b8d1
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
e4b8d1
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
e4b8d1
    0xff, 0xff, 0x30, 0x81, 0x9f, 0x04, 0x42, 0x01, 0xff, 0xff, 0xff, 0xff,
e4b8d1
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
e4b8d1
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
e4b8d1
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
e4b8d1
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
e4b8d1
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
e4b8d1
    0xfc, 0x04, 0x42, 0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, 0x9a,
e4b8d1
    0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85, 0x40, 0xee, 0xa2, 0xda, 0x72,
e4b8d1
    0x5b, 0x99, 0xb3, 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1, 0x09,
e4b8d1
    0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e, 0x93, 0x7b, 0x16, 0x52, 0xc0,
e4b8d1
    0xbd, 0x3b, 0xb1, 0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, 0x34,
e4b8d1
    0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50, 0x3f, 0x00, 0x03, 0x15, 0x00,
e4b8d1
    0xd0, 0x9e, 0x88, 0x00, 0x29, 0x1c, 0xb8, 0x53, 0x96, 0xcc, 0x67, 0x17,
e4b8d1
    0x39, 0x32, 0x84, 0xaa, 0xa0, 0xda, 0x64, 0xba, 0x04, 0x81, 0x85, 0x04,
e4b8d1
    0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd, 0x9e, 0x3e,
e4b8d1
    0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f,
e4b8d1
    0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba, 0xa1, 0x4b,
e4b8d1
    0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff,
e4b8d1
    0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, 0xf9, 0x7e,
e4b8d1
    0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66, 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78,
e4b8d1
    0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9,
e4b8d1
    0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17,
e4b8d1
    0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40,
e4b8d1
    0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86,
e4b8d1
    0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,
e4b8d1
    0x02, 0x42, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
e4b8d1
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
e4b8d1
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa,
e4b8d1
    0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, 0x7f, 0xcc, 0x01, 0x48,
e4b8d1
    0xf7, 0x09, 0xa5, 0xd0, 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae,
e4b8d1
    0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09, 0x02, 0x01, 0x01,
e4b8d1
};
e4b8d1
e4b8d1
static int parameter_test(void)
e4b8d1
{
e4b8d1
    EC_GROUP *group = NULL, *group2 = NULL;
e4b8d1
    ECPARAMETERS *ecparameters = NULL;
e4b8d1
    unsigned char *buf = NULL;
e4b8d1
    int r = 0, len;
e4b8d1
e4b8d1
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_secp384r1))
e4b8d1
        || !TEST_ptr(ecparameters = EC_GROUP_get_ecparameters(group, NULL))
e4b8d1
        || !TEST_ptr(group2 = EC_GROUP_new_from_ecparameters(ecparameters))
e4b8d1
        || !TEST_int_eq(EC_GROUP_cmp(group, group2, NULL), 0))
e4b8d1
        goto err;
e4b8d1
e4b8d1
    EC_GROUP_free(group);
e4b8d1
    group = NULL;
e4b8d1
e4b8d1
    /* Test the named curve encoding, which should be default. */
e4b8d1
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_secp521r1))
e4b8d1
        || !TEST_true((len = i2d_ECPKParameters(group, &buf)) >= 0)
e4b8d1
        || !TEST_mem_eq(buf, len, p521_named, sizeof(p521_named)))
e4b8d1
        goto err;
e4b8d1
e4b8d1
    OPENSSL_free(buf);
e4b8d1
    buf = NULL;
e4b8d1
e4b8d1
    /*
e4b8d1
     * Test the explicit encoding. P-521 requires correctly zero-padding the
e4b8d1
     * curve coefficients.
e4b8d1
     */
e4b8d1
    EC_GROUP_set_asn1_flag(group, OPENSSL_EC_EXPLICIT_CURVE);
e4b8d1
    if (!TEST_true((len = i2d_ECPKParameters(group, &buf)) >= 0)
e4b8d1
        || !TEST_mem_eq(buf, len, p521_explicit, sizeof(p521_explicit)))
e4b8d1
        goto err;
e4b8d1
e4b8d1
    r = 1;
e4b8d1
err:
e4b8d1
    EC_GROUP_free(group);
e4b8d1
    EC_GROUP_free(group2);
e4b8d1
    ECPARAMETERS_free(ecparameters);
e4b8d1
    OPENSSL_free(buf);
e4b8d1
    return r;
e4b8d1
}
e4b8d1
#endif
e4b8d1
e4b8d1
int setup_tests(void)
e4b8d1
{
e4b8d1
#ifndef OPENSSL_NO_EC
e4b8d1
    crv_len = EC_get_builtin_curves(NULL, 0);
e4b8d1
    if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len))
e4b8d1
        || !TEST_true(EC_get_builtin_curves(curves, crv_len)))
e4b8d1
        return 0;
e4b8d1
e4b8d1
    ADD_TEST(parameter_test);
e4b8d1
    ADD_TEST(prime_field_tests);
e4b8d1
# ifndef OPENSSL_NO_EC2M
e4b8d1
    ADD_TEST(char2_field_tests);
e4b8d1
    ADD_ALL_TESTS(char2_curve_test, OSSL_NELEM(char2_curve_tests));
e4b8d1
# endif
e4b8d1
# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
e4b8d1
    ADD_ALL_TESTS(nistp_single_test, OSSL_NELEM(nistp_tests_params));
782d48
    ADD_TEST(underflow_test);
e4b8d1
# endif
e4b8d1
    ADD_ALL_TESTS(internal_curve_test, crv_len);
e4b8d1
    ADD_ALL_TESTS(internal_curve_test_method, crv_len);
e4b8d1
#endif
e4b8d1
    return 1;
e4b8d1
}
e4b8d1
e4b8d1
void cleanup_tests(void)
e4b8d1
{
e4b8d1
#ifndef OPENSSL_NO_EC
e4b8d1
    OPENSSL_free(curves);
e4b8d1
#endif
e4b8d1
}